Grundprincipper i call stack
Udforsk principperne bag call stack, dets struktur, og hvordan det bruges til at håndtere funktionskald og lokale data.
Grundprincipper i call stack er en gratis Assembly-sprog og x86-systemprogrammering på lavt niveau-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Assembly-sprog og x86-systemprogrammering på lavt niveau, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Assembly-sprog og x86-systemprogrammering på lavt niveau-kurset indeholder 4 lektioner i alt.
Mød kaldestakken
Hver gang dit program kalder en funktion eller procedure, bruger det et særligt hukommelsesområde, der kaldes kaldestakken. Tænk på den som en stak tallerkener i en kantine. Du kan kun lægge tallerkener på eller fjerne dem fra toppen.
Kaldestakken er afgørende for håndtering af funktionskald, lokale variabler og registrering af, hvor der skal returneres, når en funktion er færdig.
LIFO: Sidst ind, først ud
Kaldestakken fungerer efter LIFO-princippet: Last In, First Out. Det betyder, at det senest tilføjede element på stakken altid er det første, der fjernes.
- Når en funktion kaldes, skubbes dens data op på stakken.
- Når den returnerer, fjernes dens data fra stakken.
- Det sikrer den korrekte rækkefølge ved indlejrede kald.
Stakpege: ESP og EBP
To hovedregistre er afgørende for håndtering af stakken i x86-assembly:
- ESP (stakpeger): Peget altid på toppen af stakken, altså det senest lagte element. Stakken vokser nedad (mod lavere hukommelsesadresser).
- EBP (basispeger): Peger på en fast placering i den aktuelle stakramme og gør det lettere at finde lokale variable og funktionsargumenter.
Vi skal se, hvordan de arbejder sammen om at organisere data.
Tilføjelse af data med PUSH
Instruktionen PUSH tilføjer data øverst på stakken. Når du udfører PUSH på en værdi (f.eks. et 32-bit-register):
- bliver registret ESP først dekrementeret med datastørrelsen (4 byte for en 32-bit-værdi).
- Derefter skrives værdien til den hukommelsesplacering, som ESP nu peger på.
Det svarer til at placere en ny tallerken øverst i stakken, så stakken bliver 'højere', mens toppen flyttes 'nedad'.
PUSH i praksis
Se, hvordan PUSH ændrer stakpegeren og gemmer værdier. I dette eksempel antager vi, at ESP oprindeligt peger på 0x100 (en høj hukommelsesadresse). Stakken vokser nedad.
section .text
global _start
_start:
; Assume ESP initially points to 0x100
; Stack grows downwards (towards lower addresses)
mov eax, 0x10 ; Load value 10 (hex) into EAX
push eax ; ESP becomes 0xFC, memory at [0xFC] = 0x10
mov ebx, 0x20 ; Load value 20 (hex) into EBX
push ebx ; ESP becomes 0xF8, memory at [0xF8] = 0x20
; At this point:
; ESP = 0xF8
; Memory at 0xF8 contains 0x20
; Memory at 0xFC contains 0x10
; Exit the program cleanly
mov eax, 1 ; sys_exit system call number
xor ebx, ebx ; exit code 0
int 0x80Fjernelse af data med POP
Instruktionen POP fjerner data fra toppen af stakken og placerer dem i et angivet register eller på en angivet hukommelsesplacering. Når du udfører POP på en værdi:
- læses værdien på den hukommelsesplacering, som ESP aktuelt peger på.
- Derefter bliver registret ESP inkrementeret med datastørrelsen (f.eks. 4 byte).
Det 'fjerner' i praksis det øverste element og flytter pegeren 'opad', så stakken bliver 'kortere'.
Eksempel med PUSH og POP
Lad os se PUSH og POP arbejde efter hinanden. Bemærk, hvordan ESP vender tilbage til sin oprindelige placering efter lige mange push- og pop-operationer.
section .text
global _start
_start:
; Assume ESP starts at some address (e.g., 0x100)
mov eax, 50 ; Load 50 into EAX
push eax ; Push EAX onto stack. ESP -= 4. [ESP] = 50
mov ebx, 100 ; Load 100 into EBX
push ebx ; Push EBX onto stack. ESP -= 4. [ESP] = 100
; Stack now has 100 at top, then 50.
; ESP is pointing to the 100.
pop ecx ; Pop top of stack into ECX. ESP += 4. ECX = 100
pop edx ; Pop next item into EDX. ESP += 4. EDX = 50
; After pops, ECX is 100, EDX is 50.
; ESP is back to its initial position before the pushes.
; Exit
mov eax, 1
xor ebx, ebx
int 0x80Forståelse af stakrammer
Når der kaldes på en funktion (eller procedure), oprettes der et dedikeret område på stakken, som kaldes en stakramme (eller aktiveringsrecord). Denne ramme indeholder alle data, der er knyttet til det pågældende funktionskald.
En stakramme indeholder typisk:
- Funktionsargumenter, der er sendt til den
- Lokale variable, der bruges i funktionen
- Returadressen (det sted, programmet skal hoppe tilbage til, når funktionen er færdig)
- Gemte registerværdier fra den kaldende funktion
EBP: Rammepegeren
Registret EBP (basispeger) bruges primært til at håndtere stakrammer. I modsætning til ESP, som hele tiden flytter sig, når data pushes og poppes, forbliver EBP normalt fast ved basis af den aktuelle funktions stakramme.
Denne stabilitet gør det nemt at få adgang til lokale variable og argumenter ved hjælp af faste forskydninger fra EBP (f.eks. [EBP-4] for en lokal variabel og [EBP+8] for et argument), selv hvis ESP ændres på grund af push- og pop-operationer i funktionen.
Stakkontrol
Se på følgende assembly-kodestykke:
mov eax, 10
push eax
mov ebx, 20
push ebx
pop ecx
pop edx
Hvad er den endelige værdi i registret EDX, når denne kode er kørt?
Opsamling: Grundlæggende om kaldestakken
Du har lært det grundlæggende om x86-kaldestakken!
- Kaldestakken er en LIFO-datastruktur, som er grundlæggende for håndtering af funktionskald.
- ESP (stakpegeren) peger altid på toppen af stakken og flytter sig ved
PUSH/POP-operationer. - EBP (basispegeren) bruges til at definere en stabil stakramme for en funktion, så det bliver lettere at få adgang til lokale data og argumenter.
PUSHdekrementerer ESP og gemmer derefter værdien;POPhenter værdien og inkrementerer derefter ESP.
Derefter bygger vi videre på dette ved at lære, hvordan du definerer og kalder dine egne procedurer ved hjælp af disse stakkoncepter.
Lær Assembly med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 12
- Lektioner
- 48
Ofte stillede spørgsmål
Er lektionen “Grundprincipper i call stack” gratis?
Ja — hele teksten til “Grundprincipper i call stack” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Assembly-sprog og x86-systemprogrammering på lavt niveau-kurset, skal du opgradere til CoddyKit PRO. Assembly-sprog og x86-systemprogrammering på lavt niveau-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Grundprincipper i call stack”?
Udforsk principperne bag call stack, dets struktur, og hvordan det bruges til at håndtere funktionskald og lokale data. Du øver dig i Assembly-sprog og x86-systemprogrammering på lavt niveau med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Assembly-sprog og x86-systemprogrammering på lavt niveau?
Der kræves ingen tidligere erfaring. Assembly-sprog og x86-systemprogrammering på lavt niveau på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.
Hvor lang tid tager lektionen “Grundprincipper i call stack”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Assembly-sprog og x86-systemprogrammering på lavt niveau-lektion?
Ja. Alle Assembly-sprog og x86-systemprogrammering på lavt niveau-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Grundprincipper i call stack
- Definition og kald af procedurer
- Videregivelse af argumenter og returværdier
- Stack frames og lokale variabler