I'm briefly studying the System V ABI for amd64 / x86-64 architecture, and am curious how it handles return values over 128 bits, where rax
and rdx
aren't enough.
I wrote the following C code on Ubuntu 18.04 64-bit (more generally, any amd64 POSIX-compliant system):
struct big {
long long a, b, c, d;
};
struct big bigfunc(void) {
struct big r = {12, 34, 56, 78};
return r;
}
Compiled it as gcc -S -masm=intel t.c
, and inspected t.s
:
.file "t.c"
.intel_syntax noprefix
.text
.globl bigfunc
.type bigfunc, @function
bigfunc:
.LFB0:
.cfi_startproc
mov QWORD PTR -40[rsp], rdi
mov QWORD PTR -32[rsp], 12
mov QWORD PTR -24[rsp], 34
mov QWORD PTR -16[rsp], 56
mov QWORD PTR -8[rsp], 78
mov rcx, QWORD PTR -40[rsp]
mov rax, QWORD PTR -32[rsp]
mov rdx, QWORD PTR -24[rsp]
mov QWORD PTR [rcx], rax
mov QWORD PTR 8[rcx], rdx
mov rax, QWORD PTR -16[rsp]
mov rdx, QWORD PTR -8[rsp]
mov QWORD PTR 16[rcx], rax
mov QWORD PTR 24[rcx], rdx
mov rax, QWORD PTR -40[rsp]
ret
.cfi_endproc
.LFE0:
.size bigfunc, .-bigfunc
.ident "GCC: (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0"
.section .note.GNU-stack,"",@progbits
No surprise that the struct definition doesn't compile into any instructions, so the output only contains function bigfunc
. The output assembly looks pretty straightforward, allocating memory from stack for struct big r
and assign initial values, and returning it.
If I am understanding correctly, before ret
is executed, register rax
contains the value of rdi
at the beginning of the function call (from QWORD PTR -40[rbp]
). According to SysV, rdi
is the first argument supplied to the function, which is impossible because the function accepts no arguments. So I have a few questions here:
- What is
rdi
when the functionbigfunc
takes no arguments? - What is
rax
(as the register that contains return value), whenrdx
is not touched in this function? - How does the function return this 256-bit C structure?