2010-04-28 13 views
5

Znam ten wątek został pokryty znudzenia tutaj oraz w innych miejscach w internecie - ale mam nadzieję, że sprawa jest prosta jak próbuję uzyskać moja głowa wokół zespołu ...Plik/bazowe wskaźniki w zespole

Więc jeśli rozumiem poprawnie, ebp (wskaźnik bazowy) wskaże wierzchołek stosu, a esp (wskaźnik stosu) wskaże na dół - ponieważ stos rośnie w dół. szczególnie dlatego wskazuje na "obecną lokalizację". Tak więc po wywołaniu funkcji, po zapisaniu ebp na stosie wstawia się nową ramkę stosu - dla funkcji. Tak więc w przypadku poniższego obrazu, jeśli zacząłeś od N-3, poszedłbyś na N-2 z wywołaniem funkcji. Ale kiedy jesteś na poziomie N-2 - czy twój ebp == 25 i esp == 24 (przynajmniej początkowo, zanim jakiekolwiek dane zostaną umieszczone na stosie)?

Czy to prawda, czy jestem tutaj na stycznej?

Dzięki!

http://upload.wikimedia.org/wikipedia/en/a/a7/ProgramCallStack2.png http://upload.wikimedia.org/wikipedia/en/a/a7/ProgramCallStack2.png

+0

Zamierzam dodać to jako C, ponieważ wygląda na to, że próbujesz zrozumieć, jaki kod generuje kompilator języka C. Możesz go usunąć, jeśli to nie jest w porządku. – Earlz

Odpowiedz

3

Faktycznie zależy to nie tylko od architektury sprzętowej i kompilatora, ale także od calling convention, który jest po prostu uzgodnionym sposobem, w którym funkcje działają ze stosem, aby wywoływać się nawzajem. Innymi słowy, istnieją różne porządki, w których funkcja może przesuwać rzeczy na stos, w zależności od ustawień kompilatora (i specyficznych opcji #pragma itd.).

Wygląda na to, że mówisz o konwencie wywoływania cdecl w architekturze x86. W takim przypadku osoba dzwoniąca ebp jest zwykle przesyłana na stos bezpośrednio po adresie zwrotnym. Tak więc, w przykładzie N-2, położenie 25 będzie zawierało wskaźnik z powrotem do funkcji wywołującej N-3 (tj. Będzie zawierało adres instrukcji bezpośrednio po call, który dostał cię do N-2), a lokalizacja 24 będzie zawierają starą ebp, a twoja funkcja esp będzie = 23 tuż po zakończeniu połączenia, zanim wszyscy mieszkańcy zostaną zepchnięci na stos. (Z wyjątkiem niektórych kompilatorów będzie miejsce na stosie bezpośrednio po wywołaniu, a więc ESP będzie mieć 20 zamiast poruszać się w górę iw dół w funkcji N-2.)

Jednak mieć świadomość, że na x86 istnieje szczególna optymalizacji kompilator może czasem nie nazywa frame pointer omission, który unika popychając starą ebp na stos całkowicie pod pewnymi warunkami.

0

To zależy od platformy, ale na ogół jest to jak to wszystko działa.

Na architekturach, z którymi jestem najbardziej znany, adres "calling" (zwany również "return") znajduje się w rejestrze $ ra, a stos jest tam, gdzie został pozostawiony przez osobę dzwoniącą. Tak więc dzieje się tak, że adres powrotu jest przesyłany do stosu, podobnie jak wskaźnik bazowy (wywołujący), a następnie wskaźnik bazowy jest aktualizowany do punktu, w którym znajduje się stos, a stos ciągle się indeksuje. Dokładna kolejność, w której rzeczy się popychają i co jest ustawione, gdy nie pamiętam, ale zazwyczaj to od kasty zależy, aby zaoszczędzić na rejestrach, które zostaną spętane. W ten sposób funkcja wywołująca nie musi zapisywać wszystkiego, jeśli wywoływana funkcja używa tylko jednego lub dwóch rejestrów. (W rzeczywistości rejestr adresu zwrotnego jest taki sam - nie zostanie on wciśnięty na stos, jeśli funkcja nie wywoła niczego innego.)

Jest to całkiem łatwe do wykonania, jeśli zdemontujesz program i zrobisz zajrzyj do funkcji prolog i epilogu. Wszystkie one podążają za dość powszechnymi wzorcami "przechowywania wszystkiego" na górze i "przywracania wszystkiego" na samym dole. (Zauważ, że są czasami "specjalne" rejestry, które nigdy nie są przechowywane ani odtwarzane, a kompilator wie, że może liczyć tylko na spójne wartości, jeśli nie było żadnych wywołań funkcji.) W MIPS uważam, że są rejestrami S, i PPC nazywa je t?)

2
  1. Po wywołaniu w N-3, ebp jest 28 i esp jest 25.
  2. Stary jest popychany, a następnie dla ebp jest ustawiony na bieżącą wartość z esp. Teraz zarówno esp, jak i ebp są .
  3. Wreszcie, esp jest dostosowywany, aby pomieszczenie pomieściło zmienne lokalne. esp jest teraz prawdopodobnie teraz 20, w zależności od tego, jak zachowuje się funkcja po wywołaniu N-2.

Najlepszym sposobem na sprawdzenie tego jest przeczytanie o function prologues i zapoznanie się z implementacją x86. Pomaga także zaakceptować, że esp i ebp są używane do zlokalizowania użycia stosu w każdej funkcji, z pewnymi odmianami pomiędzy kompilatorami, architekturami i platformami (i prawie nieistotnymi dla użytkownika dowolnego języka wyższego poziomu lub równego C).

+1

Wstyd Nie mogę zaakceptować dwóch odpowiedzi - dziękuję za wskazówki! – malangi