# Calling Conventions ## Cheatsheet | Platform | Return Value | Parameter Registers | Additional Parameters | Stack Alignment | Scratch Registers | Preserved Registers | Call List | | -------------------------------------------------------------------- | ------------ | -------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------- | ----------------------------------------- | ------------------------------------------- | --------- | | System V i386 | eax, edx | none | stack (right to left)[1](https://wiki.osdev.org/Calling_Conventions#Note1) | | eax, ecx, edx | ebx, esi, edi, ebp, esp | ebp | | System V X86_64[2](https://wiki.osdev.org/Calling_Conventions#Note2) | rax, rdx | rdi, rsi, rdx, rcx, r8, r9 | stack (right to left)[1](https://wiki.osdev.org/Calling_Conventions#Note1) | 16-byte at call[3](https://wiki.osdev.org/Calling_Conventions#Note3) | rax, rdi, rsi, rdx, rcx, r8, r9, r10, r11 | rbx, rsp, rbp, r12, r13, r14, r15 | rbp | | Microsoft x64 | rax | rcx, rdx, r8, r9 | stack (right to left)[1](https://wiki.osdev.org/Calling_Conventions#Note1) | 16-byte at call[3](https://wiki.osdev.org/Calling_Conventions#Note3) | rax, rcx, rdx, r8, r9, r10, r11 | rbx, rdi, rsi, rsp, rbp, r12, r13, r14, r15 | rbp | | ARM (32-bit) | r0, r1 | r0, r1, r2, r3 | stack | 8 byte[4](https://wiki.osdev.org/Calling_Conventions#Note4) | r0, r1, r2, r3, r12 | r4, r5, r6, r7, r8, r9, r10, r11, r13, r14 | | ## System V i386 - Parametres are pushed to stack from right to left - Caller cleans the stack - Callee is free to modify parametres - Caller must not assume they stayed the same! - Scratch registers are `EAX`, `ECX` and `EDX` - Caller must preserve if needed - Function preserves `EBX`, `ESI`, `EDI` and `EBP` - Return value in `EAX` - If 64bit value: higher 32bits in `EDX` - Functions push `ebp` such that the caller-return-eip is 4 bytes above it, and set `ebp` to the address of the saved ebp. - Allows iterating through the existing stack frames. - Can be eliminated by specifying the -fomit-frame-pointer GCC option. ## CDECL **Caller's responsibilities** - Push parameters in reverse order (last parameter pushed first) - Perform the call - Pop the parameters, use them, or simply increment `ESP` to remove them (stack clearing) - The return value is stored in `EAX` **Callee's responsibilities (callee is the routine being called)** - Store caller's `EBP` on the stack - Save current `ESP` in `EBP` - Code, storing local data on the stack - For a fast exit load the old `ESP` from `EBP`, else pop local data elements - Pop the old `EBP` and return – store return value in `EAX` **It looks like this in assembly (NASM)** ``` nasm SECTION .text caller:  ; ...  ; Caller responsibilities: PUSH 3  ; push the parameters in reverse order PUSH 2 CALL callee  ; perform the call ADD ESP, 8  ; stack cleaning (remove the 2 words)  ; ... Use the return value in EAX ... callee:  ; Callee responsibilities: PUSH EBP  ; store caller's EBP MOV EBP, ESP  ; save current stack pointer in EBP  ; ... Code, store return value in EAX ...  ; Callee responsibilities: MOV ESP, EBP  ; remove an unknown number of local data elements POP EBP  ; restore caller's EBP RET  ; return ``` ## Sources - [https://wiki.osdev.org/Stack](https://wiki.osdev.org/Stack) - [https://wiki.osdev.org/Calling_Conventions](https://wiki.osdev.org/Calling_Conventions) - [https://wiki.osdev.org/System_V_ABI](https://wiki.osdev.org/System_V_ABI) **TODO:** Check if SysV ABI and CDECL are really the same thing?