Skip to content

Concepts

general

The Stack

The call stack is a LIFO region of memory managed by RSP where function frames, saved registers, return addresses, and local variables live.

The stack is a contiguous region of memory that grows downward on x86-64: pushing data decrements RSP; popping data increments it. RSP always points to the current top (lowest address) of the stack.

Stack layout for a typical frame

High addresses
  ...
  [return address]      ← pushed by CALL
  [saved RBP]           ← push rbp
  [local variable 1]    ← rbp - 8
  [local variable 2]    ← rbp - 16
  [saved r12]           ← callee-saved register
  [saved rbx]
RSP →                   ← bottom of current frame
Low addresses

Standard prologue / epilogue

asm
; Prologue
push rbp              ; save caller's frame pointer
mov  rbp, rsp         ; establish our own frame pointer
sub  rsp, 0x30        ; allocate 48 bytes for locals

; ... function body — locals at [rbp-8], [rbp-16], etc. ...

; Epilogue
mov  rsp, rbp         ; or: leave  (equivalent)
pop  rbp
ret

The LEAVE instruction is a shorthand for mov rsp, rbp; pop rbp.

Frame-pointer omission (FPO)

With -O2 and above, compilers often omit the push rbp; mov rbp, rsp pair and access locals relative to RSP directly. Debuggers and unwinders use .eh_frame / UNWIND_INFO tables instead of RBP to unwind the stack.

Stack alignment

The System V ABI requires RSP to be 16-byte aligned before a CALL (meaning 8-byte aligned at function entry, after the return address is pushed). Compilers emit and rsp, ~0xF or adjust the allocation size to maintain this.

Reverse-engineering notes

  • Identifying function boundaries is easier when frame pointers are present: push rbp marks a function entry; pop rbp; ret marks its exit.
  • When FPO is enabled, locals appear as [rsp + constant] rather than [rbp - constant]. Decompilers compute the constant offsets from the ABI unwind tables.
  • The return address sits above the saved RBP on the stack. A stack overflow that corrupts [rbp+8] overwrites the return address — the classic stack-buffer-overflow target.
  • Stack canaries (mov rax, fs:[0x28]; mov [rsp+N], rax) appear between the return address and locals in SSP-protected binaries.