2015-10-25 12 views
6

Der Code istSuche nach fehlendem C-Code, gegebenem Assembler-Code?

int f(int x, int y, int z) { 
    if (/* missing code here */) 
    return z; 
    else 
    return -z; 
} 

Und die Montage ist

pushl %ebp 
    movl %esp, %ebp 
    movl 8(%ebp), %eax 
    cmpl 12(%ebp), %eax 
    jge .L2 
    movl 16(%ebp), %eax 
    jmp .L3 
.L2: 
    movl 16(%ebp), %eax 
    negl %eax 
.L3: 
    popl %ebp 
    ret 

Und die Frage bittet um mich zu finden, was die fehlenden Testausdruck der Assembler-Code gegeben zu erhalten sein muss. Okay, einfach genug. Es gibt einen offensichtlichen Vergleich zwischen x und y. Der jge Operator wird den Sprung in den Körper der Schleife vorgeben, wenn 12(%ebp) > %eax.

Die Wahlmöglichkeiten sind

x<=y x>=y x>y x<y

Meine Antwort x<=y, da 12(%ebp) ist ein Verweis auf y war, und es ist das Ziel. Aber diese Antwort war falsch, und ich sehe nicht wie. Irgendwelche Hinweise? Ich danke dir sehr. Hier

+1

Bedeutet jge nicht: Sprung größer oder gleich? '> =' –

+2

Sie könnten dekompilieren/zerlegen, aber ehrlich gesagt, es ist nicht viel da, also könnten Sie wahrscheinlich versuchen, herauszufinden, was passiert. Ich denke, es macht x - y ('8 (% ebp)' und '12 (% ebp)' sind die ersten beiden Funktionsargumente außerhalb des Stacks) und springt dann, wenn es größer als Null ist. Was für mich bedeuten würde, dass x größer als y ist. –

+1

Mit Intelsyntax und Pseudocode entspricht der Vergleich "cmp x, y". Von hier aus gelangen wir zum 'return -z'-Zweig, wenn x> = y.Da wir wissen wollen, was die getestete Bedingung ist, kehren wir diesen Test einfach um und geben uns den Test, der für den gewünschten Zweig wahr sein muss. Es wird bald klar, dass die tatsächliche getestete Bedingung war x = y) – enhzflep

Antwort

5

ist die kommentierte x86 assembly:

pushl %ebp ; save the old stack movl %esp, %ebp ; set up your local, new stack movl 8(%ebp), %eax ; take the first function argument and store it into eax cmpl 12(%ebp), %eax ; compare the 2nd function arg with the 1st (in eax)

Danach gibt es ein jge was bedeutet, im Wesentlichen, „jump wenn größer oder gleich“, die Sie nach der cmp Anweisung tun können.

Dies bedeutet, dass es springt, wenn das erste Argument größer als das zweite Argument ist und somit x >= y.

Allerdings wird dieser Sprung (zu L2) tatsächlich z negieren und dann z zurückgeben. Was Sie eigentlich wollen, ist der Sprung nach L3, was passieren würde, wenn x < y, was das Endergebnis sein sollte.

+0

Ich frage mich, warum Parameter auf dem Stapel statt Register, nach der Aufrufkonvention übergeben werden. – edmz

+3

@black, unter Linux, scheint der Code in der Frage 32-Bit zu sein, so dass Parameter im Allgemeinen auf dem Stapel (32-Bit i386 ABI) im Gegensatz zu dem System V 64-Bit ABI übergeben werden, wo Parameter, die passen, in Registern übergeben werden können (und wenn nötig auf dem Stapel sein) –

2

Sie können GCC fragen, was es tun wird. Erstellen einer Quelle mit mehreren Funktionen:

test.c

int f1 (int x, int y, int z) { 
    if (x < y) 
    return z; 
    else 
    return -z; 
} 

int f2 (int x, int y, int z) { 
    if (x > y) 
    return z; 
    else 
    return -z; 
} 

int main (void) 
{ 
    return 0; 
} 

f1 führt (x < y), f2 führt (x> y). Jetzt bauen sie:

gcc test.c -m32 -Wa,-ahln -fno-asynchronous-unwind-tables 

Sie die Montage von test.c sehen. Suchen Sie nach f1: und f2:, die die Einstiegspunkte der Funktionen sind. Welche passt zu deinem Snippet? Sie werden sehen, dass f1 übereinstimmt, während f2 mit jle behandelt.