Memory layouts
Stack memory vs Heap memory
Whenever a program is run, it has two kinds of memories, stack and heap.

This describes the layout of memory when the program is run.
Higher memory address is read off first, then the data that was at the top of the stack is removed and the data below it is read.
Think of stack like a pile of dishes. To take a plate, sane people would pick up one from the top of the pile. Then the next one is picked, and so on.
Stack contains both function calls and local variables. Heap contains only variables.
BSS and data segments are not relevant, but they contain the global uninitialized and initialized data respectively.
Heap has a large amount of memory. More than stack. And most heap allocated things are freely resizable. However, the access to heap is significantly slower, and the elements may not be stored in a continuous fashion.
Stack Frames
Stack frames are the mechanism by which function calls are done. In x86 architecture
EBP1 |
main function local vars |
next function arg1 |
next function arg2 / ESP1 |
Assume that this is the stack, and main has already loaded the args in the stack. The current EBP and current ESP demarcate the current stack frame
Now we do a call fun
in assembly. What this implicitly does is pushes the return address
(basically address of the next instruction) onto the stack. So now the stack looks something like
this.
EBP1 |
main function local vars |
next function arg1 |
next function arg2 |
return addr / ESP1 |
Next, the very first steps of fun
would be to create its own stackframe.
The following instructions are executed in sequence:
push ebp mov ebp, esp sub esp, 0x08 ; an example here
push
and pop
are basically fancy ways of saying add this value and move to next element and
take this value and move to the previous element.
Now when we execute the first instruction:
old ebp / EBP1 |
main function local vars |
next function arg1 |
next function arg2 |
return addr |
EBP1 / ESP1 |
Next, a second value of ebp is created when we execute the second instruction.
old ebp / EBP1 |
main function local vars |
next function arg1 |
next function arg2 |
return addr |
EBP1 / ESP1 ; EBP2 |
Next, the sub creates the space for the local variables of fun.
old ebp / EBP1 |
main function local vars |
next function arg1 |
next function arg2 |
return addr |
EBP1 / ESP1 ; EBP2 |
fun function local vars |
fun function local var / ESP2 |
Now, when we're done with the function, we destroy the stack frame. There are two methods to do it.
leave ret
OR
mov rsp, rbp pop rbp ret
leave
is effectively equivalent to the second one. So for simplicity and elaboration we'll go with
the second form.
After the first instruction
old ebp / EBP1 |
main function local vars |
next function arg1 |
next function arg2 |
return addr |
EBP1 / ESP1 ; EBP2 ; ESP3 |
fun function local vars |
fun function local var / ESP2 |
After the second instruction
old ebp / EBP1 ; EBP3 |
main function local vars |
next function arg1 |
next function arg2 |
return addr / ESP3 |
EBP1 / ESP1 ; EBP2 |
fun function local vars |
fun function local var / ESP2 |
After the third instruction
old ebp / EBP1 ; EBP3 |
main function local vars |
next function arg1 |
next function arg2 / ESP3 |
return addr |
EBP1 / ESP1 ; EBP2 |
fun function local vars |
fun function local var / ESP2 |