2010-03-30 10 views

Odpowiedz

3

To zależy od ABI i architektury, ale jeśli adres powrotu kończy się na stosie, jest to efekt uboczny instrukcji, która je tam umieszcza.

5

Idealnie, oświadczenie call powinno to załatwić. Następna lokalizacja licznika programu zostanie przesunięta do stosu. Kiedy wywoływana funkcja (podprogram) kończy działanie, a po napotkaniu instrukcji return, kontrolka przechodzi teraz do adresu, który został wepchnięty do stosu i zostanie pobity.

+1

Jak 'sprawa call' z nim potem? chcę tylko zobaczyć, gdzie * adres ret * jest podana – Mask

+0

Będziesz musiał rozbić metodę wywołania na kolejny kod szesnastkowy. Oszukający zestaw instrukcji dla określonego procesora ujawniłby to. Na przykład, jeśli weźmiesz najprostszy mikroprocesor, instrukcja 8085 i ADD X nie pokaże drugiej wartości (pozwala przyjąć Y jak ADD X, Y). Zamiast tego doda wartość X do jakiegoś zarezerwowanego rejestru w procesorze, na przykład H i zapisze wartość w H. Bit przepełnienia, jeśli taki istnieje, zostanie zapisany w innym rejestrze. Tak zaprojektowano instrukcje ADD. Instrukcja CALL również będzie miała podobne predefiniowane reguły. – bragboy

+5

Częścią zadania instrukcji call jest przesunięcie adresu zwrotnego na stos. Adres zwrotny to tylko adres bezpośrednio po parametrach instrukcji wywoławczej. Aby zobaczyć, jaki jest adres zwrotny w powyższym przykładzie, musisz przejrzeć stos, gdy tylko program przejdzie do procedury pod adresem 0x4012d0. –

4

Na procesorze x86 (jak na przykład w języku asemblerowym) instrukcja call przesuwa adres powrotu na stos i przekazuje sterowanie do funkcji.

Nie wszystkie architektury procesorów umieszczają adres powrotu na stosie - często istnieje zestaw jednego lub więcej rejestrów zaprojektowanych do przechowywania adresów zwrotnych. W procesorach ARM instrukcja BL umieszcza adres zwrotny w określonym rejestrze (LR lub "rejestr połączeń") i przekazuje sterowanie do funkcji. Procesor ia64 robi coś podobnego, z wyjątkiem tego, że istnieje kilka możliwych rejestrów (b0 -), które mogą odbierać adres zwrotny, a jeden zostanie określony w instrukcji (domyślnie jest to b0).

1

wezwanie popycha bieżącą wartość rejestru RIP (adres zwrotny) do stosu + robi wywołanie
ret wyskakuje adres zwrotny (który wezwanie pchane) z wierzchu stosu (RSP zarejestruj tam punkty) i zapisuje je w rejestrze RIP.

Przykład na pudełku GNU/Linux: funkcja f wywołuje funkcję g i pozwala spojrzeć na ramkę g.

LOW ADRES

... < - RSP (wskaźnik stosu wskazuje szczyt stosu) zarejestrować punkty pod tym adresem
G lokalne Vars
baza wskaźnik F jest (stara wartość RBP) < - RBP (wskaźnik bazowy) zarejestrować punkty pod tym adresem
f adres ret (stara wartość RIP) (to właśnie wezwanie (od f) wciśnięty, a co ret (od g) pojawi)
argumentuje, że f nazywa g i nie mieści się w rejestrach (myślę, że w systemie Windows jest inaczej)
...

HIGH ADRES

g uwolni lokalnych vars (MOVQ% RSP% RBP)
g pop "starej RBP" i przechowywać go w RBP rejestru (pop% RBP)
g będzie ret, który zmodyfikuje RIP o wartości, które są przechowywane gdzie RSP wskazuje na

Nadzieja pomaga

Powiązane problemy