Function Prologue

A function prologue is the sequence of instructions at the beginning of a function that sets up the function’s stack frame. This setup is necessary so that the function can manage its local variables and keep track of return addresses, arguments, and previous stack states.

In x86 assembly (32-bit), a typical function prologue looks like this:

push ebp          ; Save the base pointer of the previous stack frame
mov ebp, esp      ; Set up a new base pointer for this function
sub esp, <size>   ; Allocate space on the stack for local variables

Purpose of each instruction:

This is often matched at the end of the function with a function epilogue, which cleans up the stack:


mov esp, ebp    ; Clean up local stack space
pop ebp         ; Clean up local stack space
ret             ; Return to caller

Local Variable (C → Assembly)

Stored on the stack. Accessed using stack-relative addressing like [rbp - 0x4].

// C
void func() {
int x = 5;
}
; Assembly
mov DWORD PTR [rbp - 4], 5

Global Variable (C → Assembly)

Stored in the .data or .bss section. Accessed via RIP-relative addressing like [rip + global_x].

// C
int global_x = 10;

void func() {
    global_x = 20;
}
; Assembly
global_x:
    .long 10          ; in the .data section

foo:
    mov DWORD PTR [rip + global_x], 20  ; assign 20 to global_x

mov vs lea

mov rax, [rbx] copies the value at the memory address pointed to by rbx into rax. In other words, it dereferences the pointer in rbx.

lea rax, [rbx] does not dereference memory. It simply loads the effective address (in this case, the same as rbx) into rax. It is used for address calculations.

; Example:
mov rax, [rbx]    ; rax = *rbx (load the value pointed to by rbx)
lea rax, [rbx]    ; rax = rbx (just copy the address)

Heap Memory (Assembly)

The heap is a memory region used for dynamic allocation (e.g., malloc in C). Unlike the stack, it is manually managed and persists until explicitly freed.

You can allocate heap memory by calling malloc (libc) or directly using the mmap syscall.

Example using malloc:

mov edi, 32       ; malloc(32)
call malloc       ; rax = pointer to heap memory

mov qword [rax], 0xdeadbeef
mov rbx, [rax]

Example using syscall (Linux x86_64):

mov rax, 9        ; syscall number for mmap
mov rdi, 0        ; addr = NULL (let kernel choose)
mov rsi, 4096     ; length = 4096 bytes
mov rdx, 3        ; PROT_READ | PROT_WRITE
mov r10, 34       ; MAP_PRIVATE | MAP_ANONYMOUS
mov r8, -1        ; fd = -1
mov r9, 0         ; offset = 0
syscall           ; rax = pointer to heap memory

mov qword [rax], 0x12345678

This memory remains valid until you free it manually (e.g., using free or another syscall).