(gdb) disas func
Dump of assembler code for function func:
0x00000000004004b8 <func+0>: push %rbp
0x00000000004004b9 <func+1>: mov %rsp,%rbp
0x00000000004004bc <func+4>: movl $0x64,0xfffffffffffffff0(%rbp)
0x00000000004004c3 <func+11>: movb $0x61,0xfffffffffffffff4(%rbp)
0x00000000004004c7 <func+15>: mov 0xfffffffffffffff0(%rbp),%rax
0x00000000004004cb <func+19>: leaveq
0x00000000004004cc <func+20>: retq
End of assembler dump.
t_test func()
{
t_test t;
t.i = 100;
t.c = 'a';
return t;
}
Run Code Online (Sandbox Code Playgroud)
所以它似乎正在返回局部变量t,但这种工作是否有保证可以工作,是不是应该在返回时不引用任何局部变量?
RAX 足够大,可以容纳整个结构。在 0x00000000004004c7 处,您正在加载整个结构(使用 mov),而不是其地址(您将使用 lea 代替)。
x86-64 System V ABI 的调用约定以 RDX:RAX 或 RAX 形式返回最多 16 个字节的 C 结构。 x86-64 上的 C++:何时在寄存器中传递和返回结构/类?
对于较大的结构,调用者传递了一个“隐藏的”输出指针 arg。
根据我的经验,C返回结构没有标准方法.为了能够传递结构,编译器通常(不可见地向用户)传递指向结构的指针,函数可以将结构复制到该结构中.如何传递此指针(堆栈中的第一个或最后一个)是依赖于实现的.一些编译器,如32位MSVC++,在EAX和EDX等寄存器中返回小结构.显然,GCC以64位模式在RAX中返回这样的结构.
但是,再一次,没有标准的方法来完成这项工作.当使用函数的其余代码也由同一编译器编译时,这是没有问题的,但如果函数是DLL或lib的导出函数则是一个问题.当使用来自不同语言(Delphi)的这些函数或使用不同编译器的C时,我已经被这几次咬过了.也可以看到此链接.