How are function arguments passed in the x86-64 System V calling convention?
The first six integer/pointer arguments go in registers (%rdi, %rsi, %rdx, %rcx, %r8, %r9, in that order); a 7th and beyond go on the stack.
* System V passes integer args in %rdi, %rsi, %rdx, %rcx, %r8, %r9; the 7th+ goes on the stack, the result returns in %rax, floats use %xmm0-%xmm7. *
Passing arguments in registers instead of memory is a big reason x86-64 function calls are faster than IA-32's. The order is fixed by the System V ABI so that any two separately compiled functions agree.
| Argument # | Register |
|---|---|
| 1st | %rdi |
| 2nd | %rsi |
| 3rd | %rdx |
| 4th | %rcx |
| 5th | %r8 |
| 6th | %r9 |
| 7th+ | stack |
The return value comes back in %rax (a 128-bit return uses %rdx:%rax), and floating-point arguments use a separate set, %xmm0–%xmm7.
long foo(long a, long b, long c); // foo(1, 2, 3)
mov $1, %rdi # a
mov $2, %rsi # b
mov $3, %rdx # c
call foo # result returns in %rax
Mnemonic for the order: Diane's Silk Dress Costs 8 9 → rdi, rsi, rdx, rcx, r8, r9.
Go deeper:
x86 calling conventions (Wikipedia) — the exact six-register argument order the card teaches.
Application binary interface (Wikipedia) — why an ABI fixes the convention so separate code agrees.