How does the stack look during nested (and recursive) function calls?
Each call pushes a new frame onto the stack, so active calls form a chain of frames — and recursion works precisely because every invocation gets its own separate frame.
* Every call pushes its own separate frame, so an inner call can't clobber an outer call's locals — which is exactly why recursion works. *
When yoo calls who, which calls amI, which calls itself, the stack grows one frame per active call:
| yoo's frame |
| who's frame |
| amI frame | ← first amI call
| amI frame | ← recursive amI call
← %rsp
Each frame independently holds:
- the return address (where to resume in the caller)
- saved callee-saved registers
- that invocation's own local variables
- space to build arguments for further calls
Why recursion just works: because each call's locals live in a different frame at a different address, the inner call can't clobber the outer call's variables. The return addresses form a chain leading back through every caller — which is exactly what a debugger follows to print a stack trace (in IA-32, by walking the saved-%ebp links from frame to frame).
Go deeper:
Recursion (Wikipedia) — why recursion works with self-calls and separate frames.
Call stack (Wikipedia) — each active call is its own frame in the chain.