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