Passing
Once arguments are classified, the registers get assigned (in left-to-right
order) for passing as follows:
1. If the class is MEMORY, pass the argument on the stack.
2. If the class is INTEGER, the next available register of the sequence %rdi,
%rsi, %rdx, %rcx, %r8 and %r9 is used 13 .
3. If the class is SSE, the next available vector register is used, the registers
are taken in the order from %xmm0 to %xmm7.
4. If the class is SSEUP, the eightbyte is passed in the next available eightbyte
chunk of the last used vector register.
5. If the class is X87, X87UP or COMPLEX_X87, it is passed in memory.
Returning of Values
The returning of values is done according to the following
algorithm:
1. Classify the return type with the classification algorithm.
2. If the type has class MEMORY, then the caller provides space for the return
value and passes the address of this storage in %rdi as if it were the first
argument to the function. In effect, this address becomes a “hidden” first
argument.
On return %rax will contain the address that has been passed in by the
caller in %rdi.
3. If the class is INTEGER, the next available register of the sequence %rax,
%rdx is used.
4. If the class is SSE, the next available vector register of the sequence %xmm0,
%xmm1 is used.
5. If the class is SSEUP, the eightbyte is returned in the next available eightbyte
chunk of the last used vector register.
6. If the class is X87, the value is returned on the X87 stack in %st0 as 80-bit
x87 number.
7. If the class is X87UP, the value is returned together with the previous X87
value in %st0.
8. If the class is COMPLEX_X87, the real part of the value is returned in
%st0 and the imaginary part in %st1.
Code
/* x64abi.c */ int func(int a, int b, int c, int d, int e, int f, int g, int h) { int ret; ret = a + b + c + d + e + f + g + h; return ret; } int main(void) { func(5, 6, 10, 11, 22, 23, 38, 39); return 0; }
$ objdump -d x64abi.o x64abi.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <func>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 89 7d ec mov %edi,-0x14(%rbp) 7: 89 75 e8 mov %esi,-0x18(%rbp) a: 89 55 e4 mov %edx,-0x1c(%rbp) d: 89 4d e0 mov %ecx,-0x20(%rbp) 10: 44 89 45 dc mov %r8d,-0x24(%rbp) 14: 44 89 4d d8 mov %r9d,-0x28(%rbp) 18: 8b 45 e8 mov -0x18(%rbp),%eax 1b: 8b 55 ec mov -0x14(%rbp),%edx 1e: 8d 04 02 lea (%rdx,%rax,1),%eax 21: 03 45 e4 add -0x1c(%rbp),%eax 24: 03 45 e0 add -0x20(%rbp),%eax 27: 03 45 dc add -0x24(%rbp),%eax 2a: 03 45 d8 add -0x28(%rbp),%eax 2d: 03 45 10 add 0x10(%rbp),%eax 30: 03 45 18 add 0x18(%rbp),%eax 33: 89 45 fc mov %eax,-0x4(%rbp) 36: 8b 45 fc mov -0x4(%rbp),%eax 39: c9 leaveq 3a: c3 retq 000000000000003b <main>: 3b: 55 push %rbp 3c: 48 89 e5 mov %rsp,%rbp 3f: 48 83 ec 10 sub $0x10,%rsp 43: c7 44 24 08 27 00 00 movl $0x27,0x8(%rsp) 4a: 00 4b: c7 04 24 26 00 00 00 movl $0x26,(%rsp) 52: 41 b9 17 00 00 00 mov $0x17,%r9d 58: 41 b8 16 00 00 00 mov $0x16,%r8d 5e: b9 0b 00 00 00 mov $0xb,%ecx 63: ba 0a 00 00 00 mov $0xa,%edx 68: be 06 00 00 00 mov $0x6,%esi 6d: bf 05 00 00 00 mov $0x5,%edi 72: e8 00 00 00 00 callq 77 <main+0x3c> 77: b8 00 00 00 00 mov $0x0,%eax 7c: c9 leaveq 7d: c3 retq