The stack

Intermediate

The stack is a region of memory used last in, first out, like a pile of plates. The stack segment register SS says where it is, and SP, the stack pointer, holds the offset of its top.

InstructionDoes
PUSH srcSP = SP − 2, then the word goes to SS:SP
POP destthe word at SS:SP goes to dest, then SP = SP + 2
PUSHF / POPFthe same with the flags

Three things to notice:

  • The stack grows down: each PUSH lowers SP by 2. With .STACK 100H, an empty stack has SP = 0100h.
  • It holds words only: PUSH AX is allowed, PUSH AL is not.
  • The last value pushed is the first popped. Push AX then BX, and the first POP gets BX's value.
; Last in, first out: two pushes, two pops.
.MODEL SMALL
.STACK 100H
.CODE
MAIN PROC
    MOV AX, 1111H
    MOV BX, 2222H
    PUSH AX            ; SP: 0100h -> 00FEh
    PUSH BX            ; SP: 00FEh -> 00FCh
    POP CX             ; CX = 2222h: the last one pushed
    POP DX             ; DX = 1111h
    MOV AH, 4CH
    INT 21H
MAIN ENDP
END MAIN
Open in compiler

The CPU view lists the stack from the top, with SP marked, and says where each word came from.

Saving registers

A piece of code that needs AX and BX for itself, but must not disturb them, saves them first and restores them in the reverse order:

    PUSH AX
    PUSH BX
    ...            ; use AX and BX freely
    POP BX         ; last pushed, first popped
    POP AX

Reversing with the stack

Last in, first out is exactly a reversal. Push each character as it is read, then pop them all:

; Read a word (up to Enter) and print it backwards with the stack.
.MODEL SMALL
.STACK 100H
.CODE
MAIN PROC
    MOV CX, 0          ; how many characters
READ:
    MOV AH, 1
    INT 21H
    CMP AL, 0DH        ; Enter ends the word
    JE BACKWARDS
    PUSH AX            ; the character is in AL
    INC CX
    JMP READ
BACKWARDS:
    MOV DL, 0AH        ; down a line (Enter already went back to the start)
    MOV AH, 2
    INT 21H
    JCXZ DONE          ; nothing was typed
PRINT:
    POP DX             ; DL = a character, last one first
    MOV AH, 2
    INT 21H
    LOOP PRINT
DONE:
    MOV AH, 4CH
    INT 21H
MAIN ENDP
END MAIN

Input used: stack

Open in compiler

Every PUSH needs a POP before the program (or the procedure, in lesson 12) finishes, or the stack is left with extra words: StepVioz reports a POP with nothing pushed, and a stack that overflows.

Common mistakes

  • Popping in the same order as pushing: restore in reverse.
  • Pushing a byte register: PUSH AL is not an 8086 instruction. Push AX.
  • A PUSH inside a loop with no POP: the stack fills up.
  • Thinking SP goes up on a PUSH: the stack grows towards lower addresses.

Quick check

1. SP = 0100h. What is SP after PUSH AX?
2. PUSH AX (AX = 1), then PUSH BX (BX = 2), then POP CX. What is CX?
3. Which is a valid 8086 PUSH?
4. Why does pushing each typed character and then popping them all print the text backwards?

Practice problems for this lesson

My notes

Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.