Assembly Language
De stapel
Zoeken…
Opmerkingen
De stapel computers is als een stapel boeken. PUSH voegt er één aan de top toe en POP haalt de bovenste weg. Net als in het echte leven kan de stapel niet eindeloos zijn, dus hij heeft een maximale grootte. De stapel kan worden gebruikt voor het sorteren van algoritmen, om een grotere hoeveelheid gegevens te verwerken of om waarden van registers te beveiligen tijdens een andere bewerking.
Zilog Z80 Stack
Het register sp
wordt gebruikt als stapelwijzer , wijzend naar de laatst opgeslagen waarde in stapel ("bovenkant" van stapel). Dus EX (sp),hl
zal de waarde van hl
ruilen met de waarde bovenaan de stapel.
In tegenstelling tot het woord "top" groeit de stapel in het geheugen door de sp
verlagen en worden de "pops" -waarden vrijgegeven door sp
verhogen.
Voor sp
= $4844
met waarden 1
, 2
, 3
opgeslagen op stapel (de 3
worden als laatste waarde op stapel geplaatst, dus bovenaan), ziet het geheugen er als volgt uit:
| address | value bytes | comment (btw, all numbers are in hexadecimal)
| ---------- | ----------- | ---------------------------------
| 4840 | ?? ?? | free stack spaces to be used by next push/call
| 4842 | ?? ?? | or by interrupt call! (don't expect values to stay here)
| sp -> 4844 | 03 00 | 16 bit value "3" on top of stack
| 4846 | 02 00 | 16 bit value "2"
| 4848 | 01 00 | 16 bit value "1"
| 484A | ?? ?? | Other values in stack (up to it's origin)
| 484C | ?? ?? | like for example return address for RET instruction
Voorbeelden van hoe instructies werken met stapel:
LD hl,$0506
EX (sp),hl ; $0003 into hl, "06 05" bytes at $4844
POP bc ; like: LD c,(sp); INC sp; LD b,(sp); INC sp
; so bc is now $0506, and sp is $4846
XOR a ; a = 0, sets zero and parity flags
PUSH af ; like: DEC sp; LD (sp),a; DEC sp; LD (sp),f
; so at $4844 is $0044 (44 = z+p flags), sp is $4844
CALL $8000 ; sp is $4842, with address of next ins at top of stack
; pc = $8000 (jumping to sub-routine)
; after RET will return here, the sp will be $4844 again
LD (L1+1),sp ; stores current sp into LD sp,nn instruction (self modification)
DEC sp ; sp is $4843
L1 LD sp,$1234 ; restores sp to $4844 ($1234 was modified)
POP de ; de = $0044, sp = $4846
POP ix ; ix = $0002, sp = $4848
...
...
ORG $8000
RET ; LD pc,(sp); INC sp; INC sp
; jumps to address at top of stack, "returning" to caller
Samenvatting : PUSH
slaat waarde op stapel op, POP
haalt waarde op van stapel, het is een LIFO (last in, first out) wachtrij. CALL
is hetzelfde als JP
, maar het duwt ook het adres van de volgende instructie na CALL
bovenaan de stapel. RET
is ook vergelijkbaar met JP
, het adres uit de stapel halen en er naartoe springen.
Waarschuwing : wanneer interrupts zijn ingeschakeld, moet de sp
geldig zijn tijdens het interruptsignaal, met voldoende vrije ruimte gereserveerd voor de interrupt-handlerroutine, omdat het interruptsignaal het retouradres (werkelijke pc
) opslaat voordat de handler-routine wordt aangeroepen, die mogelijk meer gegevens opslaat stapel ook. Elke waarde vóór sp
kan dus "onverwacht" worden gewijzigd, als er een onderbreking optreedt.
Geavanceerde truc : op Z80 met PUSH
die 11 klokcycli (11t) nam en POP
die 10t nam, was de uitgerolde POP
/ PUSH
door alle registers, inclusief EXX
voor schaduwvarianten, de snelste manier om een geheugenblok te kopiëren, zelfs sneller dan afgerolde LDI
. Maar je moest de kopie tussen de interruptsignalen plaatsen om geheugenbeschadiging te voorkomen. Ook uitgerold PUSH
was de snelste manier om geheugen te vullen met een bepaalde waarde op ZX Spectrum (opnieuw met het risico op corruptie door Interrupt, indien niet correct getimed, of gedaan onder DI
).