Assembly Language & Procedure Calls

a stack frame

Every time a function starts running, it needs a private scratchpad: room for its local variables, somewhere to stash the return address, space to save any callee-saved registers it borrows. That private chunk of the stack, belonging to one active call, is its stack frame (also called an activation record). When the function returns, the frame is thrown away and the space goes back to the pool. Picture a stack of cafeteria trays: each call slides on a new tray with its own dishes, and removes it when done.

A frame is built on entry and torn down on exit. On entry the function executes a short prologue: it subtracts from the stack pointer to allocate the frame, then stores into the frame the things it must preserve (the return address, any callee-saved registers it will use). The body then reads and writes its locals at fixed offsets from the stack pointer. On exit an epilogue reverses everything: it reloads the saved registers, adds back to the stack pointer to free the frame, and returns. Because each call's frame sits just below its caller's, the frames naturally form the same last-in, first-out stack the hardware pointer tracks.

Stack frames matter because they are what make nested and recursive calls work: each call gets a fresh, independent copy of its locals, so a function calling itself does not stomp on its own variables. They also explain familiar phenomena. A stack overflow is simply too many frames piled up (often runaway recursion) overrunning the space reserved for the stack. And a debugger's backtrace is just a walk through the chain of frames, reading each saved return address to reconstruct who called whom.

A function with a 16-byte frame: f: addi sp, sp, -16 # prologue: allocate frame sd ra, 8(sp) # save return address into the frame sd s0, 0(sp) # save a callee-saved register ... # body uses 0(sp) and 8(sp) as its private slots ld s0, 0(sp) # epilogue: restore ld ra, 8(sp) addi sp, sp, 16 # free frame ret

Prologue allocates and saves; the body uses fixed offsets; the epilogue restores and frees. Frame size is balanced exactly.

Each active call has its own frame, which is exactly why recursion works. A stack overflow usually means frames piled up without returning, most often from recursion that never hits its base case.

Also called
activation record活動記錄活化記錄