Assembly Language & Procedure Calls

the stack pointer

Imagine a spike on a desk where you skewer notes: you always add a new note on top and always take the top one off first. That last-in, first-out pile is a stack, and it is exactly how programs manage the scratch space a function needs while it runs. The stack lives in memory, and a single register, the stack pointer, remembers where the top of the pile currently is. Everything pushed and popped happens relative to that one address.

On most machines the stack grows downward, toward smaller addresses, which feels backwards but is just a convention. To push a value, you subtract from the stack pointer to make room (claiming a few bytes of memory), then store the value there. To pop, you load the value back and add to the stack pointer to release the space. Because the stack pointer always marks the boundary between used and free stack memory, a function can safely carve out a chunk for its own locals simply by moving the pointer down on entry and back up on exit.

The stack pointer matters because it is the linchpin of how functions call each other. Each active call gets its own region of the stack (its stack frame) below the previous one, and the stack pointer keeps these regions from colliding. If a function forgets to restore the stack pointer to where it found it before returning, the caller's view of the stack is corrupted and the program usually crashes. Keeping the stack pointer balanced, down on entry and exactly back up on exit, is one of the iron rules of writing correct assembly.

Pushing one register and later popping it (RISC-V, 8-byte values): addi sp, sp, -8 # make room: move stack pointer down sd ra, 0(sp) # store the return address on the stack ... # body that might call other functions ld ra, 0(sp) # restore it addi sp, sp, 8 # release the space: move stack pointer back up

Subtract to push (claim space), add to pop (release it); the stack pointer marks the live top.

The downward-growth convention is the usual one but not a law of physics; what is non-negotiable is that a function must restore the stack pointer to its entry value before returning.

Also called
SPsp