# 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?