Stack
Stack and Function Calls
- The stack grows downward in memory, so the top of the stack is lower in memory.
pushandpopperform stack operations.- To reserve a space, subtract size from the stack pointer
rsp. To give it back, add the space back. The space should be a multiple of 16 bytes (as stated under System V ABI Calling Convention for AMD64). - You can use,
ulimit -sto check the stack size.
| System Call (Linux Kernel) | Function Call (Userspace) |
|---|---|
| rdi | rdi |
| rsi | rsi |
| rdx | rdx |
| r10 | rcx |
| r8 | r8 |
| r9 | r9 |
Entering and Leaving Functions
To enter a function you need to:
- push the base pointer to the stack (this will decrease the rsp)
- copy the stack pointer (rsp) to rbp (points to the base pointer)
- reserve the memory w.r.t to the rsp

- To make clearing local variables easy, rbp base pointer is used. All the local variables are then placed in relative to the base pointer.
- To leave the function, you need to reverse: restore the stack pointer to the base pointer and pop the saved base pointer to rbp
; enter
popq %rbp ; push the base pointer to the stack
movq %rsp, %rbp ; save the stack pointer to rbp
subq $NUM_BYTES, %rsp ; allocate stack region
; The above code is equivalent to
; enter $NUM_BYTES, $0
; leave
movq %rbp, %rsp ; restore the stack pointer
popq %rbp ; restore the base pointer
- To prevent writing this much, we have
enterandleavefunction that perform this. However, enter is slower than these instructions and leave is faster. So compiler optimisations use the assembly instructions to enter andleaveto exit. (enter $NUM_BYTES, $0). The second argument is usually kept 0, unless we want to implement closures.
Passing arguments to the stack
- To look into the number of arguments and their assignment to the registers, we need to refer to the System V ABI Calling Convention as it is the one used by Linux. There are some exceptions like Golang uses its own Internal ABI to be able to keep the same ABI across platforms.
- For information on how the different types of parameters (float, int, pointers, structs, unions, arrays) are passed to a function, what happens if the registers are exhausted and how are vairadic (variable argument) functions are handled, refer to Notes on System V ABI (yet to be uploaded).
Tail-Call Elimination
- A recursive program can result into exhausting the stack space due to a large number of recursions.
- If the last thing the function does is return the value of another function and doesn’t work with the
return value, then in assembly, instead of
callthe compiler can optimise to do away with the stack usingleaveand instead ofcall, it can just issue ajmpfunction. - This will not return the control to the current function, but to the preceding function.