Я кратко изучаю ABI System V для архитектуры amd64 / x86-64, и мне любопытно, как он обрабатывает возвращаемые значения более 128 бит, где rax
и rdx
недостаточно.
Я написал следующий код C на 64-битной Ubuntu 18.04 (в более общем случае, на любой POSIX-совместимой системе amd64):
struct big {
long long a, b, c, d;
};
struct big bigfunc(void) {
struct big r = {12, 34, 56, 78};
return r;
}
Скомпилировал его как gcc -S -masm=intel t.c
и проверил 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
Не удивительно, что определение структуры не компилируется ни в какие инструкции, поэтому вывод содержит только функцию bigfunc
. Выходная сборка выглядит довольно просто, выделяя память из стека для struct big r
, назначая начальные значения и возвращая ее.
Если я правильно понимаю, перед выполнением ret
регистр rax
содержит значение rdi
в начале вызова функции (с QWORD PTR -40[rbp]
). Согласно SysV, rdi
является первым аргументом, предоставленным функции, что невозможно, потому что функция не принимает аргументов. Итак, у меня есть несколько вопросов здесь:
- Что такое
rdi
, когда функция bigfunc
не принимает аргументов?
- Что такое
rax
(как регистр, содержащий возвращаемое значение), когда rdx
не затрагивается в этой функции?
- Как функция возвращает эту 256-битную структуру C?