2013-07-07 10 views
12

Przeczytałem, że gdy wywołanie funkcji jest wykonywane przez program, wywoływana funkcja musi wiedzieć, jak powrócić do swojego wywołującego.W jaki sposób wywoływane funkcje powracają do swojego rozmówcy po wywołaniu?

Moje pytanie brzmi: w jaki sposób wywoływana funkcja wie, jak powrócić do rozmówcy? Czy za kulisami działa kompilator?

+1

Powinieneś przeczytać [to] (http://en.wikipedia.org/wiki/Call_stack#Structure) To jest bardzo dobra odpowiedź: [Rozdział 11 - Procedury] (http: //pages.cs.wisc. edu/~ smoler/x86text/lect.notes/procedures.html) A jeśli lubisz wideo: [Assembly Primer for Hackers (Część 11) Stack funkcji] (http://www.progamercity.net/code-tut/168- assembly-language-primer-hackers-video-series.html) spodoba ci się wszystkie filmy tutaj. –

Odpowiedz

12

Kompilator przestrzega określonej "konwencji wywoływania" zdefiniowanej jako część ABI, której celujesz. Ta konwencja wzywająca będzie zawierała sposób, aby system wiedział, do którego adresu powrócić. Konwencja wywołująca zwykle korzysta ze wsparcia sprzętowego dla wywołań procedur. Na Intel, na przykład adres zwrotny jest popychany do stosu:

... procesor pcha wartość rejestru EIP (który zawiera offset instrukcji po instrukcji CALL) na stosie (do wykorzystania później jako wskaźnik instrukcji powrotu).

powrocie z funkcji odbywa się za pomocą instrukcji ret:

... procesor pojawi się wskaźnik instrukcji return (offset) z wierzchu stosu do rejestru EIP i rozpoczyna wykonanie programu przy nowym wskaźniku instrukcji.

W przeciwieństwie do tego, na ramieniu, adres zwrotny jest umieszczony w rejestrze linku:

BL i BLX instrukcje skopiować adres następnej instrukcji do lr (r14, rejestr linków).

Zwroty zwykle wykonuje się, wykonując movs pc, lr, aby skopiować adres z rejestru linków z powrotem do rejestru licznika programów.

Odniesienia:

  1. Intel Software Developers Manual
  2. ARM Information Center
4

to jest możliwe przez stos (zwłaszcza w systemach Intel podobnych). Załóżmy, że mamy metodę caller, która obejmuje, powiedzmy, int, która jest przechowywana lokalnie.

Po wywołaniu caller( wywołania target( należy zapisać int. Jest on umieszczony na stosie razem z adresem, z którego nawiązano połączenie. target( może wykonywać swoją logikę, tworzyć własne zmienne lokalne i wywoływać inne metody. Zmienne lokalne zostaną umieszczone na stosie wraz z adresem połączenia.

Po zakończeniu target( stos jest "rozwijany".Górna część stosu zawierająca zmienne lokalne target( została usunięta.

Gdy metody powtarzają się zbyt daleko, stos może stać się zbyt duży i może wystąpić "przepełnienie stosu".

8
  1. Kompilator wie jak wywołać funkcję i jakie wywołanie konwencja jest stosowana. Na przykład w C argumenty dla funkcji są wypychane na stos. Wywoływacz jest odpowiedzialny za wyczyszczenie stosu, więc wywoływana funkcja nie musi usuwać argumentów. Inne konwencje wywoływania mogą obejmować popychanie argumentów na stosie i wywoływana funkcja musi je wyczyścić. W tym przypadku wygenerowany kod jest taki, że funkcja koryguje stos przed powrotem. Konwencje przywoływania mogą przekazywać argumenty w rejestrach, więc w takim przypadku wywoływana funkcja również nie musi się zajmować.

  2. Procesor ma mechanizm wywoływania podprogramu. Spowoduje to zapisanie bieżącego adresu wykonania na stosie, a następnie przeniesienie przetwarzania na nowy adres. Kiedy funkcja jest wykonana, wykonuje instrukcję return, która pobiera adres wywołującego i wznawia tam wykonywanie.

Jeśli adres zwrotny zostanie zniszczony, ponieważ stos nie zostanie odpowiednio wyczyszczony, lub pamięć zostanie nadpisana, otrzymamy niezdefiniowane zachowanie. Oczywiście dokładne szczegóły implementacji różnią się w zależności od platformy, która jest używana.

4

Wymaga współpracy między odbiorcą a dzwoniącym.

Osoba dzwoniąca zgadza się podać adres, który powracający powinien powrócić do adresata (zwykle poprzez naciśnięcie go na stosie lub przekazanie go do rejestru), a osoba odwołująca się zgadza się powrócić na ten adres po zakończeniu. wykonanie.

Powiązane problemy