The stack is a region of memory addressed by SS:SP, where SP points at the word most recently stored. PUSH src first subtracts 2 from SP, then writes the 16-bit operand at SS:SP. The stack therefore grows towards lower addresses. The operand can be a general register, a segment register (CS included) or a word in memory. The stack works only in words: there is no PUSH AL. No flags change.
MOV BX, SP ; remember where the stack isPUSH AXPUSH CXPUSH DSSUB BX, SP ; BX = 6: three words, two bytes eachPOP DSPOP CXPOP AXMOV AL, BLADD AL, '0' ; digit -> characterMOV DL, ALMOV AH, 02h ; DOS: print DLINT 21h
Uses
Saving registers that a procedure is about to use and restoring them before RET. Passing arguments: the caller pushes them, the procedure reads them through BP, and someone removes them afterwards. Copying a segment register into another without a general register: PUSH CS then POP DS. Keeping a value aside while a loop needs the register, as in PUSH CX around an inner loop.
PRINTX PROC NEAR ; a procedure that leaves registers as it found themPUSH AXPUSH DX; ... work that changes AX and DX ...POP DX ; the reverse orderPOP AXRETPRINTX ENDP
Pitfalls
Every push needs a matching pop on every path out of a procedure; a leftover word means RET pops it as the return address and the program jumps into nowhere. An immediate cannot be pushed on the 8086: load it into a register first. PUSH SP stores the value SP has after the subtraction on the 8086 and 8088, but the value from before it on the 80286 and later, a difference some programs use to tell the processors apart. In a .COM the stack shares the 64 KB segment with code and data, so deep recursion can overwrite your own program.
Later CPUs
The 80186 adds PUSH imm and PUSHA, which pushes all eight general registers. The 80386 adds 32-bit pushes (PUSH EAX, PUSHAD) and the segment registers FS and GS.