Appendix A: x86-64 Register Reference
General-Purpose Registers
+--------+--------+------+-------+----------------------------------+
| 64-bit | 32-bit | 16b | 8-bit | Primary Purpose |
+--------+--------+------+-------+----------------------------------+
| rax | eax | ax | al/ah | Return value, syscall number |
| rbx | ebx | bx | bl/bh | Callee-saved (preserved) |
| rcx | ecx | cx | cl/ch | 4th integer argument |
| rdx | edx | dx | dl/dh | 3rd integer argument |
| rsi | esi | si | sil | 2nd integer argument |
| rdi | edi | di | dil | 1st integer argument |
| rbp | ebp | bp | bpl | Frame pointer (callee-saved) |
| rsp | esp | sp | spl | Stack pointer |
| r8 | r8d | r8w | r8b | 5th integer argument |
| r9 | r9d | r9w | r9b | 6th integer argument |
| r10 | r10d | r10w | r10b | Caller-saved temporary |
| r11 | r11d | r11w | r11b | Caller-saved temporary |
| r12 | r12d | r12w | r12b | Callee-saved |
| r13 | r13d | r13w | r13b | Callee-saved |
| r14 | r14d | r14w | r14b | Callee-saved |
| r15 | r15d | r15w | r15b | Callee-saved |
+--------+--------+------+-------+----------------------------------+
Writing to a 32-bit sub-register (e.g., eax) zero-extends into the full 64-bit register. Writing to a 16-bit or 8-bit sub-register does NOT zero-extend — the upper bits are preserved.
Special Registers
+--------+----------------------------------------------------------+
| rip | Instruction pointer — address of the NEXT instruction |
| | You cannot write to it directly (use jmp/call/ret) |
+--------+----------------------------------------------------------+
| rflags | Status flags, set by arithmetic/comparison instructions |
| | CF (bit 0) — Carry flag (unsigned overflow) |
| | ZF (bit 6) — Zero flag (result was zero) |
| | SF (bit 7) — Sign flag (result was negative) |
| | OF (bit 11) — Overflow flag (signed overflow) |
+--------+----------------------------------------------------------+
System V AMD64 ABI Calling Convention
This is the calling convention used on Linux, macOS, and most Unix-like systems.
Integer / Pointer Arguments
Argument #: 1st 2nd 3rd 4th 5th 6th 7th+
Register: rdi rsi rdx rcx r8 r9 stack
Arguments beyond the 6th are passed on the stack, pushed right-to-left.
Floating-Point Arguments
Argument #: 1st 2nd 3rd 4th 5th 6th 7th 8th 9th+
Register: xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7 stack
Return Values
Integer / pointer: rax (and rdx for 128-bit returns)
Floating-point: xmm0 (and xmm1 for complex returns)
Callee-Saved Registers (Must Be Preserved Across Calls)
rbx, rbp, r12, r13, r14, r15
If a function uses any of these, it must save and restore them.
Caller-Saved Registers (May Be Destroyed By Calls)
rax, rcx, rdx, rsi, rdi, r8, r9, r10, r11
If you need values in these registers to survive a call, save them yourself.
Linux Syscall Convention
Syscall number: rax
Arguments: rdi rsi rdx r10 r8 r9
Return value: rax (negative = -errno)
Instruction: syscall
Clobbered: rcx, r11 (overwritten by the kernel)
Note: the 4th argument uses r10, not rcx — this differs from the normal calling convention because syscall clobbers rcx (it stores the return address there).
Common Syscall Numbers (x86-64 Linux)
0 read 1 write 2 open 3 close
9 mmap 11 munmap 12 brk 57 fork
59 execve 60 exit 62 kill 231 exit_group
Full list: /usr/include/asm/unistd_64.h or ausyscall --dump.
Quick Reference Diagram
Argument passing (System V AMD64):
my_function(a, b, c, d, e, f, g, h)
| | | | | | | |
v v v v v v v v
rdi rsi rdx rcx r8 r9 [stack] [stack]
Return: rax