What is the stack and how does it grow in x86-64?
The stack is a LIFO region of memory for function call data; it grows downward (toward lower addresses), with %rsp always pointing at the lowest in-use address.
* The stack grows downward: push subtracts 8 from %rsp then writes; pop reads then adds 8 back. *
The runtime stack is where functions store return addresses, saved registers, and locals. Its defining behaviors all follow from "grows down": push decreases %rsp then writes, pop reads then increases %rsp.
push %rax # %rsp -= 8 ; [%rsp] = %rax
pop %rbx # %rbx = [%rsp] ; %rsp += 8
You can do the same thing manually, which is exactly what sub $N,%rsp for local space does:
sub $8, %rsp # allocate 8 bytes (like push, without storing)
mov %rax, (%rsp) # store there
mov (%rsp), %rbx # read it back
add $8, %rsp # deallocate (like pop)
A typical frame, high to low addresses:
[ arguments 7+ ] ← pushed by caller
[ return address ] ← pushed by call
[ saved %rbp ] ← pushed by prologue
[ local variables ]
← %rsp points here
Why downward? It's convention from early systems, letting the stack and the heap grow toward each other from opposite ends of the address space.
Go deeper:
Call stack (Wikipedia) — the runtime call stack: return addresses and LIFO nesting.
Stack (Wikipedia) — the underlying LIFO push/pop abstraction.