How do you allocate and deallocate local variables on the stack?
Subtract from %rsp to allocate stack space (the stack grows down), and add the same amount back to deallocate before returning.
Because the stack grows toward lower addresses, reserving space means making %rsp smaller, and releasing it means making %rsp larger again.
subq $32, %rsp # allocate 32 bytes of locals
...
addq $32, %rsp # release them before ret
Within that region you address locals by offset from %rsp:
movq %rdi, (%rsp) # local[0]
movq %rsi, 8(%rsp) # local[1]
movq %rdx, 16(%rsp) # local[2]
movq %rcx, 24(%rsp) # local[3]
Alignment constraint: the stack must be 16-byte aligned before a call. Since the function entered with %rsp already off by 8 (the return address call pushed), allocations are typically rounded so that alignment is restored — which is why you'll often see a function reserve, say, 24 bytes when it only needs 20.
Tip: a matched sub $N,%rsp … add $N,%rsp pair bracketing a function body is the no-frame-pointer style of managing locals, common in optimized x86-64.
Go deeper:
Call stack (Wikipedia) — frames, frame pointers and per-invocation local storage.