void g( int m )
{
int a;
…
f( a );
}
Vor dem Aufruf von f
in g
sieht der Speicher folgendermaßen aus:
Adresse | Inhalt | Inhalt | Inhalt | Inhalt | |
---|---|---|---|---|---|
123434 | |||||
123438 | |||||
123442 | |||||
123446 | |||||
123450 | |||||
123454 | <– esp | ||||
123458 | <– a | ||||
123462 | <– ebp von g | ||||
123466 | |||||
123470 | <– m | ||||
… | … | … | … | … | |
123490 | <– bottom |
Unmittelbar nach dem Aufruf von f
(noch in f
!) ergibt sich dann das folgende Bild:
Adresse | Inhalt | Inhalt | Inhalt | Inhalt | |
---|---|---|---|---|---|
123434 | <– esp | ||||
123438 | <– x | ||||
123442 | <– y | ||||
123446 | <– ebp von f | ||||
123450 | |||||
123454 | <– n | ||||
123458 | <– a | ||||
123462 | <– ebp von g | ||||
123466 | |||||
123470 | <– m | ||||
… | … | … | … | … | |
123490 | <– bottom |
In diesem Bild sehen wir 2 Stack Frames: einen im Bereich 123434
bis 123454
für die Funktion f
und einen im Bereich 123458
bis 123470
für die Funktion g
.
Gar nicht so schwierig, oder?
Bleiben noch die beiden nicht erklärten Speicherzeilen. In der Zeile, auf welche der aktuelle ebp
verweist, ist der ebp
-Wert der aufrufenden Funktion gespeichert. Dieser Wert wird vom Prozessor benötigt, um nach dem Ende einer Funktion den Wert des ebp
-Registers im Kontext der aufrufenden Funktion wiederherzustellen. Die Speicherzeile hinter dem so abgelegten ebp
-Wert enthält dagegen die Adresse der Anweisung, welche nach dem Ende der aktuellen Funktion ausgeführt werden soll – die sogenannte Rücksprungadresse. Nach dem Ende einer Funktion muss der Program Counter (also das Register, welches auf die nächste auszuführende Anweisung verweist) lediglich auf den in dieser Zeile gespeicherten Wert gesetzt werden, um mit dem Programmablauf an der Stelle vor dem Aufruf fortzufahren.
Und warum nun ausgerechnet 4 Zellen pro Zeile? Auch das ist einfach erklärt. Eine Zelle kann auf regulären Rechnern 8 Bit fassen – ein Byte. 4 Zellen entsprechen also 4 Bytes oder 32 Bit; 32 Bit ist aber die Grundlage vieler aktueller Betriebssysteme (weswegen wir auch in einigen Jahren da ein nettes kleines Problem bekommen können) und die meisten Werte während eines Programmablaufes passen genau in 4 Bytes oder Vielfache davon hinein – daher auch die entsprechende Darstellung. Auf 64-Bit-Systemen würden 8 Zellen (entsprechend 8 Bytes oder 64 Bit) für die Darstellung verwendet werden; für die Verwaltung des Stacks gibt es dort auch 2 eigene Register, nämlich rsp
(entspricht dem esp
unter 32 Bit) und rbp
(entspricht dem ebp
unter 32 Bit).
Kommentare (11)