Intuition The one core idea
A running program keeps a single strip of memory called the stack , and each function call carves off a fresh little block on it to hold that call's private stuff. Because calls always finish in the reverse order they started, that strip is only ever added-to or trimmed-from at one end — so bookkeeping is as simple as sliding one marker up and down.
Everything in the parent topic is just this picture with names attached. Below we earn every one of those names, one at a time.
Before any of the fancy words, you need ONE picture: computer memory is a very long row of numbered boxes . Each box holds one byte (a small number), and each box has an address — its house number.
Definition Memory & address
Byte : one storage box, holds a small number.
Address : the house-number of a box. Just an integer, like 0x7ffe4a10. Bigger number = further along the strip.
When we say "store x at some address", we mean: pick a box, write the value in it, remember its number.
Why do we need addresses at all? Because to come back to a variable — or to a line of code — you must be able to name where it lives . That single need (naming a location) is the seed of the whole topic. You'll meet addresses again in depth in Pointers and addresses in C .
Definition Slot — a group of boxes we treat as one unit
A single value like an int usually needs several bytes (commonly 4). We call one such fixed-size chunk a slot , and we write w for its size in bytes. So a slot is just a run of w adjacent boxes that we push or pop together. Whenever a later section says "one slot", picture w of the numbered boxes from section 0 taped side by side.
Main memory (the long strip) is far away and slowish. The CPU keeps a handful of ultra-fast boxes inside itself called registers . There are only a few, each with a name.
A named storage box living inside the CPU. Reading/writing it is near-instant. Examples we care about: the stack pointer , the base pointer , the link register , and the box holding a return value .
Intuition Why registers matter here
The stack is in memory (the far strip), but the CPU tracks where the top of the stack is using a register. So a register acts like your finger held on a page — it doesn't store the page, it marks your place in it.
Take the memory strip and agree on a rule: we only ever add or remove slots at one end . That disciplined strip is the stack .
Definition Stack, push, pop
Stack : a region of memory used with a one-end-only rule.
push : reserve a new slot at the active end and put a value in it.
pop : throw away the slot at the active end.
The active end is called the top of the stack — even though, as the figure shows, on real CPUs that "top" is the lowest address in use.
Intuition Why one end only? → LIFO
Because function calls nest perfectly : if main calls f, and f calls g, then g must finish before f, which finishes before main. The last thing started is the first thing to finish — Last In, First Out (LIFO). A one-end strip is the exact shape of that pattern. This is the deep reason the topic uses a stack and not, say, a list you delete from the middle. (More on nesting in Recursion .)
Common mistake "The stack grows upward like a tower."
Why it feels right: we draw it growing up and "push" sounds like piling higher. The fix: on x86/ARM every push decreases the address — it grows toward lower numbers. Same idea, flipped picture. See figure s02: the arrow points down the address axis.
Now give the "top of stack" a name. S P is a register holding the address of the current top slot.
Intuition Why this is the whole magic of cleanup
To throw away ten slots at once, you don't erase them — you just add 10 w back to S P . The marker jumps past them and they're considered gone. That one move is why "local variables disappear the instant a function returns."
Definition Function & call
Function : a named block of code you can run on demand, handing it inputs (arguments ) and getting back an output (return value ).
Call : the act of jumping to that block; when it's done, execution must resume right after the call.
Here is the problem that forces the next symbol into existence: when the CPU jumps into a function, how does it remember the line to jump back to ?
Definition Return address
The address of the instruction to run after the called function finishes. It must be saved somewhere before the jump.
Definition The four instruction names you'll meet
These are machine instructions — the CPU's tiniest built-in commands. Two families of CPU appear in this topic: x86/x64 (desktops/laptops) and ARM/RISC-V (phones, Raspberry Pi, many chips).
CALL (x86): jump into a function AND automatically push the return address onto the stack.
RET (x86): pop that saved return address and jump back to it — the undo of CALL.
BL ("branch and link", ARM): jump into a function but put the return address in a register (LR), not the stack.
JAL ("jump and link", RISC-V): ARM's BL under a different name — same "jump, save return address in a register" idea.
The full instruction set lives in Assembly: push, pop, call, ret, BL ; you only need the one-line meaning above for this page.
Intuition Two ways to save the return address (why the parent shows x86 vs ARM)
x86/x64 : CALL pushes the return address onto the stack , and RET pops it back.
ARM/RISC-V : BL / JAL puts it in a special register — the link register (LR) — first. It only reaches the stack if that function calls another function and would otherwise overwrite LR.
Same goal (remember where to return), different first hop. The platform rules for which method is used live in Calling conventions (cdecl, stdcall) .
Common mistake "The return address is always pushed on the stack."
Why it feels right: on x86 CALL literally pushes it. The fix: RISC chips like ARM (BL) and RISC-V (JAL) park it in LR first; it only spills to the stack when needed.
Bundle together everything ONE call needs, and you have its frame.
Definition Stack frame (activation record)
The block of stack memory belonging to a single active call. It holds that call's local variables , its arguments (or where they were passed), the return address , and saved registers .
Think of each call grabbing a fresh sheet of scratch paper. The sheets pile at the stack's active end. When a call finishes, its sheet is crumpled (SP jumps back) and the sheet underneath — the caller's — is exposed again.
S P keeps moving (every push during the function shifts it). So addressing "my third local" as "SP minus something" is a moving target. Fix a second marker that stays put for the whole call: the base/frame pointer B P .
B P
A register holding a fixed reference address inside the current frame, set once on entry. Locals and arguments are then reached by constant offsets from it, even while S P wanders.
Intuition Why save the caller's
B P ?
B P is shared hardware — there's only one. When your function starts, that register still holds the caller's nail. So the very first thing a function does is push the old B P (save it) and set B P = S P (plant its own nail). On exit it restores the old B P , so the caller finds its desk exactly as it left it.
Definition Prologue / epilogue
Prologue : the setup code at a function's start — save old B P , set new B P , carve space for locals (S P ← S P − N ).
Epilogue : the teardown at the end — drop locals (S P ← B P ), restore old B P , RET.
These are the "grab a scratch sheet" and "crumple it" steps, made concrete.
Read this map bottom-up . The leftmost roots are the raw ideas from section 0 (memory boxes and addresses). They feed into the stack (a disciplined strip), which needs two register markers — S P (top) and B P (fixed base). Those markers, plus the return address, are exactly what a stack frame bundles together, and the prologue/epilogue rituals are what every function performs on that frame. Follow any arrow: it means "you need the earlier idea to understand the later one."
memory strip of numbered boxes
slot = w bytes taped together
stack = one-end-only strip
register = fast box in CPU
Frames live on the stack; longer-lived data lives elsewhere — see Heap vs Stack memory .
Overwrite a return address on the stack and you can hijack control — Buffer overflow & return-address smashing .
Deep nesting is Recursion ; the raw addresses are Pointers and addresses in C .
Cover the right side and answer aloud.
A byte is... one storage box in memory holding a small number.
An address is... the house-number (an integer) identifying a memory box; bigger = further along.
A slot is... a fixed run of w adjacent bytes/boxes treated as one unit (e.g. 4 bytes for an int).
A register is... a fast named storage box inside the CPU (e.g. SP, BP, LR).
The stack is... a memory region you only add to / remove from at one end.
"push" does what to SP (downward stack)? decreases SP by one slot size w, then writes the value there.
"pop" does what to SP? reads at SP, then increases SP by w — logically discarding the top slot.
LIFO stands for and comes from... Last In, First Out; it comes from function lifetimes nesting perfectly.
The stack pointer SP holds... the address of the current top of the stack.
The base pointer BP holds... a fixed reference address inside the current frame, for constant-offset access.
A return address is... the address of the instruction to run after the called function finishes.
What does x86 CALL do? jumps into the function and pushes the return address onto the stack.
What does x86 RET do? pops the saved return address and jumps back to it.
What do ARM BL / RISC-V JAL do? jump into the function and put the return address in a register (LR), not the stack.
A stack frame contains... one call's locals, arguments, saved registers, and the return address.
addr(local_k) = ... and why? BP − offset; locals sit below BP because the stack grows to lower addresses.
addr(arg_k) = ... and why? BP + offset; args were pushed before BP, so they sit at higher addresses.
Why save the caller's BP on entry? BP is a single shared register; saving/restoring lets the caller keep its own frame.
Prologue does... save old BP, set BP = SP, carve local space (SP −= N).
Epilogue does... SP = BP, restore old BP, RET.