Stack
Der Stack (Kellerspeicher oder Stapel) ist eine der wichtigsten Datenstrukturen sowohl für Software als auch Hardware, da dieser u.a. Parameter und Rücksprungadressen speichert.
Inhaltsverzeichnis
Funktionsweise
Der Stack arbeitet nach dem LIFO-Prinzip ("Last in, first out"). Das bedeutet, dass neue Elemente immer oben auf den Stack gelegt werden, sodass das zuletzt auf den Stack gelegte Element auch das zuerst wieder zurück geholte ist. Dabei kann man bei jedem Stack zwei Grundoperationen ausführen:
- push legt ein neues Element oben auf den Stack
- pop holt das oberste Element vom Stack
Implementierung durch die CPU
Die CPU bietet zwei Register zum Arbeiten mit dem Stack an:
- das SS-Register speichert das Stacksegment (im Real Mode) bzw. den Stackselektor (im Protected Mode).
- das ESP-Register (=StackPointer) zeigt auf das oberste Element des aktuellen Stacks. Die Real-Mode-Variante dieses Registers ist das SP-Register.
Zudem sind die Befehle PUSH und POP in die CPU integriert. Dabei ist zu beachten, dass der Stack von den höheren zu den niedrigeren Adressen wächst.
- Der PUSH-Befehl vermindert den Wert von ESP um die Größe des Operanden und schreibt diesen an die Stelle, auf die das Register dann zeigt
- Der POP-Befehl liest das Element, auf das ESP zeigt und erhöht das Register um die Operandengröße.
Das bedeutet, dass der Stack seine maximale Größe erreicht hat, wenn der Wert 0 im ESP-Register steht. In diesem Fall wird ein Stackfault ausgelöst.
Das EBP-Register
Zur Verwendung des Stacks bietet die CPU noch ein EBP-Register (Base Pointer). Dieses wird von vielen Hochsprachen verwendet, um lokale Variablen auf dem Stack zu speichern.
Befehle, die sich auf den Stack auswirken
Befehl | Beschreibung |
---|---|
push operand | schreibt den Operanden auf den Stack |
pop operand | liest das oberste Element vom Stack in den Operanden |
pushf | schreibt das EFLAGS-Register auf den Stack |
popf | liest das EFLAGS-Register vom Stack |
pusha | legt alle "allgemeinen" Register (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI) auf den Stack |
popa | Holt diese Register wieder vom Stack, wobei ESP übersprungen wird |
call (far) | Legt CS und EIP auf den Stack |
retf | Lädt diese Register wieder, um zur aufrufenden Codestelle zurückzukehren |
call | Legt EIP auf den Stack |
ret | Lädt EIP vom Stack, um zur aufrufenden Codestelle zurückzukehren |
int | Legt SS, ESP (beide nur bei Ringwechsel), EFLAGS, CS, EIP auf den Stack |
iret | Lädt diese Register wieder, um zur aufrufenden Codestelle zurückzukehren |
sysenter / sysleave | siehe Sysenter |
syscall / sysret | |
enter / leave | siehe Enter / Leave |