Skip to content

Instantly share code, notes, and snippets.

@7etsuo
Created August 30, 2024 08:20
Show Gist options
  • Save 7etsuo/14810672cca4e40baf4e2f1fa954e549 to your computer and use it in GitHub Desktop.
Save 7etsuo/14810672cca4e40baf4e2f1fa954e549 to your computer and use it in GitHub Desktop.
x86 stackframe cheetsheet
// ___ ___ ________ ________________ __
_start: // | \/ || ___| \/ | _ | ___ \ \ / /
push 30 ; Arg 3 // | . . || |__ | . . | | | | |_/ /\ V /
push 20 ; Arg 2 // | |\/| || __|| |\/| | | | | / \ /
push 10 ; Arg 1 // | | | || |___| | | \ \_/ / |\ \ | |
call fun // ┌\_|──|_/\____/\_|──|_/\___/\_|─\_|─\_/─────────────────────────────────────────────────────┐ ► Notes
add esp, 12 ; Clean up the stack // │ Memory │ • This layout follows System V AMD64 ABI conventions
fun: // │ │ • Some compilers may optimize out RBP usage
; Prologue // │Lower Addresses ▲ ┌───────────────────────────────────┐ │ • Actual memory layout may vary with optimizations
push ebp // │0x7fffffffeda8 │ │Local variables ├─►[rsp] Top of stack │ • Windows x64 calling convention differs significantly
mov ebp, esp // │ │ │[rbp - 8] and below ├─►[rbp - (N+8)] Alignment padding │ • Always consult current ABI documentation for specifics
sub esp, 8 ; local variables // │ │ │Accessed via rbp offsets ├─►[rbp - N] Last local var │
// │ │ │mov [rbp - 8], eax ; store local ├─►[rbp - 16] Local var 2 │ ► Function Prologue
; Function body // │ │ │mov eax, [rbp - 16] ; load local ├─►[rbp - 8] Local var 1 │ • push rbp ; Save old base pointer
mov eax, [ebp+8] ; First argument // │ │ │May include alignment padding │ │ • mov rbp, rsp ; Set up new base pointer
mov ebx, [ebp+12] ; Second argument // │ │ └───────────────────────────────────┘ │ • sub rsp, N ; Allocate space for locals
mov ecx, [ebp+16] ; Third argument // │ │ ┌───────────────────────────────────┐ │ • and rsp, -16 ; Ensure 16-byte alignment
// │ │ │Saved RBP │ │
; Epilogue // │ │ │[rbp] ├─►[rbp] Saved RBP │ ► Function Epilogue
leave // │ │ │Preserved caller's base pointer │ │ • mov rsp, rbp ; Restore stack pointer
ret // │ │ └───────────────────────────────────┘ │ • pop rbp ; Restore old base pointer
// │ │ ┌───────────────────────────────────┐ │ • leave ; can be used inplace of the above
// │ │ │Return address │ │ • ret ; Return to caller
// │ │ │[rbp + 8] ├─►[rbp + 8] Return address │
// │ │ │Pushed by CALL instruction │ │ ► Argument Passing (System V AMD64 ABI)
// │ │ └───────────────────────────────────┘ │ ► Integer/Pointer arguments:
// │ │ ┌───────────────────────────────────┐ │ • 1st: rdi 4th: rcx
// │ │ │Stack arguments (if any) ├─►[rbp + 16] Arg 1 (if on stack) │ • 2nd: rsi 5th: r8
// │ │ │[rbp + 16] and above ├─►[rbp + 24] Arg 2 (if on stack) │ • 3rd: rdx 6th: r9
// │ │ │7th argument and beyond ├─►[rbp + 32] Arg 3 (if on stack) │ • 7th and beyond: pushed on stack right-to-left
// │ │ │Right to left push order │ ... │ ► Floating-point arguments:
// │0x7fffffffede8 │ │mov edi, [rbp + 16] ; 1st stack arg│ │ • Use xmm0 to xmm7 for first 8 arguments
// │Higher Addresses └───────────────────────────────────┘ │
// └─────────────────████████████████████████████────████████──────────────────────────────────┘ ► During a Nested Function Call
// ██ ██ ██ ██ ██ ███ ██ 1. Arguments for the callee are prepared
// ██ █████ ██ ████████ ███ ██ 2. call instruction pushes return address
// ██ ██ ██ ███ ███ ██ 3. Callee's stack frame is set up above
// ██ ███████ ██ █████████████ ██████ 4. RSP moves to top of callee's frame
// 5. On return, callee's frame is removed
// 6. RSP is restored to pre-call state
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment