Sök…


Anmärkningar

Bunten med datorer är som en bunt böcker. PUSH lägger till en till toppen och POP tar det översta bort. Liksom i verkligheten kan stacken inte vara oändlig, så den har maximal storlek. Bunten kan användas för att sortera algoritmer, för att hantera en större mängd data eller för att säkra värden på register medan du gör en annan operation.

Zilog Z80 Stack

Registret sp används som stackpekaren och pekar på det senast lagrade värdet i stacken ("toppen" av stacken). Så EX (sp),hl att byta värde på hl med värdet ovanpå stacken.

I motsats till "översta" ordet växer stacken i minnet genom att minska sp och släpper ("pops") värden genom att öka sp .

För sp = $4844 med värden 1 , 2 , 3 lagrade på bunten (de 3 skjuts på bunten som sista värde, så att vara överst på det) kommer minnet att se ut så här:

|    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

Exempel på hur instruktioner fungerar med stack:

    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

Sammanfattning : PUSH kommer att lagra värde på toppen av stacken, POP hämtar värde från toppen av stacken, det är en LIFO (sist in, först ut) kö. CALL är samma som JP , men det trycker också på adressen till nästa instruktion efter CALL överst i bunten. RET liknar JP också, hoppar adressen från stacken och hoppar till den.

Varning : när avbrott är aktiverat måste sp vara giltigt under avbrottssignal, med tillräckligt med ledigt utrymme reserverat för avbrottshanteringsrutin, eftersom avbrottssignalen kommer att lagra returdressen (faktiska pc ) innan den ringer hanterarutin, vilket kan lagra ytterligare data på stack också. Alla värden före sp kan således ändras "oväntat", om avbrott inträffar.

Avancerat trick : på Z80 med PUSH tar 11 klockcykler (11t) och POP tar 10t, var det orullade POP / PUSH genom alla register, inklusive EXX för skuggvarianter, det snabbaste sättet att kopiera minnesblock, ännu snabbare än orullad LDI . Men du var tvungen att ställa in kopian mellan avbrottssignaler för att undvika minneskorruption. Ovalsad PUSH var också det snabbaste sättet att fylla minnet med särskilt värde på ZX Spectrum (återigen med risken för korruption av Interrupt, om inte tidsinställd korrekt, eller gjort under DI ).



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow