decode < Assembler < Programmiersprachen < Praxis < Informatik < Vorhilfe
|
Aufgabe | Eine Funktion mit Prototyp int decode2(int x, int y, int z); wird in
Assemblercode uebersetzt. Der Rumpf des Codes sieht folgendermaßen aus:
1 movl 16(%ebp), %eax
2 movl 12(%ebp), %edx
3 subl %eax, %edx
4 movl %edx, %eax
5 imull 8(%ebp), %edx
6 sall $31, %eax
7 sarl $31, %eax
8 xorl %edx, %eax
Die Parameter x, y, z stehen im Speicher an Stellen mit den Offsets 8, 12
und 16 relativ zu der Adresse %ebp. Der Code speichert den Rueckgabewert
im Register %eax.
Schreiben Sie C-Code f¨ur decode2 der den gleichen Effekt wie der Assemblercode
hat. Sie koennen Ihre Loesung durch Kompilieren mit dem Flag
-S testen. Der Kompiler generiert moeglicherweise nicht identischen Code, er
sollte jedoch funktional ¨aquivalent sein. |
Kann mir jmd sagen wie ich das angehen soll?
Mein ansatz ist folgender :
z = z-y
(z-y) * x
Ich habe diese Frage in keinem Forum auf anderen Internetseiten gestellt.
|
|
|
|
Hallo Lessequal,
Ich denke der Assembler-Code entspricht annähernd folgendem Code:
1: | int decode1(int x, int y, int z)
| 2: | {
| 3: | y -= z;
| 4: | z = y;
| 5: | y = x*y;
| 6: | return ((z>>31)*(z&1))^y;
| 7: | } |
Annähernd deshalb, weil es einige Werte wie z.B. (-10,-9,-10) gibt, wo der Assembler-Code als Ergebnis 9 und decode1() -10 zurückliefert. Aber den Fehler konnte ich bisher nicht finden. Trotzdem ist es schonmal ein Anfang.
Viele Grüße
Karl
|
|
|
|
|
Hallo,
man muss das Hin- und Herschieben etwas anders interpretieren, dann kommt man schrittweise auf Folgendes:
1: | int decode2(int x, int y, int z)
| 2: | {
| 3: | y -= z;
| 4: | z = y;
| 5: | y *= x;
| 6: | z = -(z%2 != 0);
| 7: | z ^= y;
| 8: | return z;
| 9: | } |
Gruß
Martin
|
|
|
|
|
Bin jetzt alles noch einmal durchgegangen und komme bis auf Zeile 6 auf das gleiche Ergebnis. Mir ist noch unklar wieso ich für
4: sall $31, %eax
5: sarl $31, %eax
in C
6: z = -(z%2 != 0)
schreiben darf/muss. Könntest du das bitte näher erläutern?
|
|
|
|
|
Hallo,
da die erste Instruktion ein Linksshift ist, der (bei einem 32-Bit-Wort) alle Bits bis auf eines "vergisst", müssen wir nur zwei Fälle unterscheiden: Der Wert in EAX ist gerade oder ungerade.
gerade:
Wert von EAX: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0
sall $31, %eax
Wert von EAX: 00000000000000000000000000000000
sarl $31, %eax
Wert von EAX: 00000000000000000000000000000000 = 0
ungerade:
Wert von EAX: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1
sall $31, %eax
Wert von EAX: 10000000000000000000000000000000
sarl $31, %eax
Wert von EAX: 11111111111111111111111111111111 = -1
Mit z%2 kann ich zwischen gerade und ungerade unterscheiden, das !=0 hilt dabei, aus 1 und -1 einheitlich 1 zu machen, und das Minus am Anfang erzeugt eben aus der 1 eine -1. Bei einer Null macht es ja keinen Unterschied.
Du kannst das Ergebnis auch auf andere Weise bekommen, aber die erschien mir recht einfach.
Gruß
Martin
|
|
|
|