System V amd64 如何处理很长的返回值? [英] How does System V amd64 handle very long return values?
问题描述
我正在简要研究用于 amd64/x86-64 架构的 System V ABI,并且很好奇它如何处理超过 128 位的返回值,其中 rax
和 rdx
还不够.
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.
我在 Ubuntu 18.04 64 位(更一般地说,任何符合 amd64 POSIX 的系统)上编写了以下 C 代码:
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;
}
编译为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
分配内存并分配初始值,然后返回它.
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.
如果我理解正确,在执行 ret
之前,寄存器 rax
在函数调用的开头包含 rdi
的值(来自 QWORD PTR -40[rbp]
).根据 SysV,rdi
是提供给函数的第一个参数,这是不可能的,因为该函数不接受任何参数.所以我在这里有几个问题:
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:
- 当函数
bigfunc
没有参数时,rdi
是什么? - 什么是
rax
(作为包含返回值的寄存器),当rdx
在这个函数中没有被触及时? - 函数如何返回这个 256 位 C 结构?
- 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?
推荐答案
根据 ABI (1),第 22 页
According to the ABI (1) ,page 22
如果类型有类 MEMORY,则调用者为返回提供空间value 并在 %rdi 中传递这个存储的地址,就好像它是第一个函数的参数.实际上,这个地址变成了一个隐藏的"第一个 ar-牙龈.此存储不得与被调用者可见的任何数据重叠除了这个参数之外的其他名称.返回时 %rax 将包含由%rdi
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 ar- gument. This storage must not overlap any data visible to the callee through other names than this argument. On return %rax will contain the address that has been passed in by the caller in %rdi
第 17、18 和 19 页描述了分类,我相信以下第 19 页是将 struct big
指定为 MEMORY 类的子句.
Page 17, 18 and 19 describes the classifications, I beliveve
the following on page 19 is the clause designating your struct big
as a MEMORY class.
(c) 如果聚合的大小超过两个八字节并且第一个八字节不是 SSE 或任何其他八字节不是 SSEUP,整个参数在内存中传递.
(c) If the size of the aggregate exceeds two eightbytes and the first eight- byte isn’t SSE or any other eightbyte isn’t SSEUP, the whole argument is passed in memory.
即调用者必须为返回值分配内存,并在 %rdi 中传递一个指向该内存的指针(并且被调用的函数在 %rax 中返回相同的地址)
i.e. the caller have to allocate memory for the return value, and pass a pointer to that memory in %rdi (and the called function returns that same address in %rax)
(1) https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI ,尽管链接目前无法正常工作.
(1) there's newer offical versions of the ABI at https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI , though the links arn't currently working properly.
这篇关于System V amd64 如何处理很长的返回值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!