2015-10-25 9 views
6

Kod jestOdnalezienie brakującego kodu C, z podanym kodem zespołu?

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

i montaż jest

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 

I pytanie prosi mnie, aby znaleźć to, co brakuje wyrażenie test musi być w celu otrzymania kodu montażu podane. W porządku, dość łatwo. Istnieje oczywiste porównanie pomiędzy x i y. Operator jge zamierza wykonać skok w ciele pętli, jeśli 12(%ebp) > %eax.

Możliwe wybory są

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

Moja odpowiedź była x<=y, ponieważ 12(%ebp) jest nawiązaniem do y, i to jest celem. Ale ta odpowiedź była błędna i nie wiem, jak to zrobić. Jakieś wskazówki? Dziękuję bardzo.

+1

Czy jge nie znaczy: skok większy lub równy? '> =' –

+2

Możesz dekompilować/dezasemblować, ale szczerze mówiąc nie ma tam zbyt wiele, więc prawdopodobnie mógłbyś spróbować dowiedzieć się, co się dzieje. Myślę, że to robi x - y ('8 (% ebp)' i '12 (% ebp)' są pierwszymi argumentami funkcji poza stosem), a następnie przeskakiwanie, jeśli jest większe od zera. Co dla mnie oznacza, że ​​x jest większe niż y. –

+1

Używając składni intel i pseudo kodu, porównanie jest równoważne 'cmp x, y'. Stąd dochodzimy do gałęzi 'return -z' jeśli x> = y.Ponieważ chcemy wiedzieć, jaki jest testowany warunek, po prostu odwracamy ten test, dając nam test, który musi dać wynik prawdziwy dla pożądanej gałęzi. Wkrótce staje się jasne, że faktycznym testowanym warunkiem było x = y). – enhzflep

Odpowiedz

5

Oto adnotacją montaż x86:

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)

Po tym, istnieje jge co oznacza w istocie, „skok jeśli większa lub równa”, co można zrobić po instrukcji cmp.

Oznacza to, że przeskakuje, jeśli pierwszy argument jest większy od drugiego argumentu, a tym samym, x >= y.

Jednak ten skok (do L2) faktycznie neguje z, a następnie zwraca z. To, czego naprawdę chcesz, to skok do L3, który nastąpi, jeśli x < y, co powinno być wynikiem końcowym.

+0

Zastanawiam się, dlaczego parametry są przekazywane na stos zamiast rejestrów, zgodnie z konwencją wywołującą. – edmz

+3

@black, Zakładając Linux, kod w pytaniu wydaje się być 32-bitowy, więc parametry są generalnie przekazywane na stosie (32-bitowy i386 ABI) w przeciwieństwie do 64-bitowego ABI systemu V, gdzie parametry, które pasują, mogą być przekazywane w rejestrach (w razie potrzeby na stosie) –

2

Możesz zapytać GCC, co zrobi. Utworzyć źródło kilka funkcji:

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 przeprowadza (x < Y) f2 przeprowadza (x> y). Teraz zbuduj:

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

Widzisz zespół test.c. Szukaj f1: i f2:, które są punktami wejścia funkcji. Który pasuje do Twojego fragmentu? Zobaczysz, że f1 odpowiada, podczas gdy f2 obsługuje z .

Powiązane problemy