x86-64 Procedures

A program would usually comprise of multiple functions and there needs to be a way of tracking which function has been called, and which data is passed from one function to another. The stack is a region of contiguous memory addresses and it is used to make it easy to transfer control and data between functions. The top of the stack is at the lowest memory address and the stack grows towards lower memory addresses. The most common operations of the stack are:

Pushing: used to add data onto the stack
Popping: used to remove data from the stack
push var
This is the assembly instruction to push a value onto the stack. It does the following:
Uses var or value stored in memory location of var


Decrements the stack pointer(known as
rsp) by 8Writes above value to new location of
rsp, which is now the top of the stack


pop var
This is an assembly instruction to read a value and pop it off the stack. It does the following:
Reads the value at the address given by the stack pointer
Stack Bottom()

rsp`rsp` points here)
Store the value that was read from
rspinto varIncrement the stack pointer by 8


It’s important to note that the memory does not change when popping values of the stack - it is only the value of the stack pointer that changes!
Each compiled program may include multiple functions, where each function would need to store local variables, arguments passed to the function and more. To make this easy to manage, each function has its own separate stack frame, where each new stack frame is allocated when a function is called, and deallocated when the function is complete.


This is easily explained using an example. Look at the two functions:
int add(int a, int b){
int new = a + b;
return new;
}
int calc(int a, int b){
int final = add(a, b);
return final;
}
calc(4, 5)```