Assembly & the CPU

the function prologue and epilogue

Most functions start and end with a little ritual that has nothing to do with what the function computes — it is housekeeping, like clearing a workbench before a job and tidying it after. Those bookkeeping instructions at the very start are the function prologue, and the mirror-image instructions at the very end are the epilogue. Together they set up and tear down the function's stack frame: its private slice of the stack holding its locals and saved registers.

A classic x86-64 prologue does three things: push rbp saves the caller's frame pointer onto the stack; mov rbp, rsp parks the frame pointer at the current top so locals can be addressed at fixed offsets like rbp-8; and sub rsp, N reserves N bytes for this function's local variables by lowering the stack pointer. If the function uses any callee-saved registers, it pushes those here too. The epilogue undoes all of it in reverse: it restores rsp (often via mov rsp, rbp or simply by adding N back), pops the saved registers and the saved rbp, and finally ret pops the return address to jump back to the caller. The single instruction leave is shorthand for the mov rsp, rbp ; pop rbp part.

Once you recognise this pattern, the shape of almost any compiled function jumps out: a few prologue instructions, the body in the middle, then the mirror-image epilogue and ret. It is also where the calling convention's promises are kept — the prologue saves the callee-saved registers the function will use, the epilogue restores them. Heavily optimised or tiny leaf functions may omit parts of it (no frame pointer, no separate stack reservation), so do not be surprised when a small function has barely any prologue at all.

A typical frame: prologue push rbp / mov rbp, rsp / sub rsp, 16, then the body, then epilogue leave / ret — leave being mov rsp, rbp ; pop rbp.

The prologue builds the stack frame; the epilogue tears it down and returns — the body sits between.

Prologues and epilogues are not mandated by the language but produced by the compiler to honour the calling convention, so they vary with optimisation level and target. A leaf function compiled with -fomit-frame-pointer may have almost no prologue, which can confuse a frame-pointer-based debugger backtrace.

Also called
prologueepiloguestack frame setup序言收尾