Why can't local variables be stored at fixed memory addresses?
Because recursion and re-entrancy need a separate copy of the locals per invocation — fixed addresses would let an inner call overwrite the outer call's variables.
Consider a recursive function with locals i and j:
int foo(int n) {
int i, j = 0;
for (i = 0; i < n; i++)
j = j + foo(n - 1); // recursive call
return j;
}
If i and j lived at fixed addresses, the recursive foo(n-1) would write to the same memory the outer call is using, corrupting the outer loop's counter and result.
The stack solves this by giving every call its own frame:
foo(3): i,j at -4(%rbp),-8(%rbp) ← one %rbp
foo(2): i,j at -4(%rbp),-8(%rbp) ← a DIFFERENT %rbp
foo(1): ... ← yet another %rbp
Each invocation has its own %rbp, so the same offset -4(%rbp) names a different physical location at every level. This per-invocation storage is exactly what makes recursion (and thread/signal re-entrancy) possible — and it's why "automatic" variables behave the way they do in C.
Go deeper:
Recursion (Wikipedia) — recursion is why per-invocation local copies are needed.
Call stack (Wikipedia) — per-invocation frames give each call its own locals.