We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
我们知道一般情况下函数的返回值是通过eax或rax寄存器来返回的,但是当我们返回值超过eax和rax所能存储的大小情况呢?
以下面代码为例,函数返回大小为32字节的结构体对象
本机环境:Linux cike-pc 4.14.0-deepin2-amd64 #1 SMP PREEMPT Deepin 4.14.12-2 (2018-01-06) x86_64 GNU/Linux
struct Test { char buf[32]; }; struct Test foo() { struct Test t2; return t2; } int main() { struct Test t1 = foo(); return 0; }
查看该文件编译后的汇编代码
$ objdump -d test.o test.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <foo>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 48 89 7d d8 mov %rdi,-0x28(%rbp) 8: 48 8b 45 d8 mov -0x28(%rbp),%rax c: 48 8b 55 e0 mov -0x20(%rbp),%rdx 10: 48 89 10 mov %rdx,(%rax) 13: 48 8b 55 e8 mov -0x18(%rbp),%rdx 17: 48 89 50 08 mov %rdx,0x8(%rax) 1b: 48 8b 55 f0 mov -0x10(%rbp),%rdx 1f: 48 89 50 10 mov %rdx,0x10(%rax) 23: 48 8b 55 f8 mov -0x8(%rbp),%rdx 27: 48 89 50 18 mov %rdx,0x18(%rax) 2b: 48 8b 45 d8 mov -0x28(%rbp),%rax 2f: 5d pop %rbp 30: c3 retq 0000000000000031 <main>: 31: 55 push %rbp 32: 48 89 e5 mov %rsp,%rbp 35: 48 83 ec 20 sub $0x20,%rsp 39: 48 8d 45 e0 lea -0x20(%rbp),%rax 3d: 48 89 c7 mov %rax,%rdi 40: b8 00 00 00 00 mov $0x0,%eax 45: e8 00 00 00 00 callq 4a <main+0x19> 4a: b8 00 00 00 00 mov $0x0,%eax 4f: c9 leaveq 50: c3 retq
汇编代码的意义如下
首先看main函数,函数main在栈上开辟0x20大小的空间,并将栈顶的地址赋值给rdi寄存器(作为传递给foo的第一个参数)。
35: 48 83 ec 20 sub $0x20,%rsp 39: 48 8d 45 e0 lea -0x20(%rbp),%rax 3d: 48 89 c7 mov %rax,%rdi
接下来看foo函数,函数foo在栈上开辟0x28大小的空间,并将栈顶(8个字节)的值赋值为%rdi(即main函数传递进来的地址)。然后将该栈上剩下的0x20大小的内存数据对应复制到main函数开辟的0x20大小的栈空间。
4: 48 89 7d d8 mov %rdi,-0x28(%rbp) 8: 48 8b 45 d8 mov -0x28(%rbp),%rax c: 48 8b 55 e0 mov -0x20(%rbp),%rdx 10: 48 89 10 mov %rdx,(%rax) 13: 48 8b 55 e8 mov -0x18(%rbp),%rdx 17: 48 89 50 08 mov %rdx,0x8(%rax) 1b: 48 8b 55 f0 mov -0x10(%rbp),%rdx 1f: 48 89 50 10 mov %rdx,0x10(%rax) 23: 48 8b 55 f8 mov -0x8(%rbp),%rdx 27: 48 89 50 18 mov %rdx,0x18(%rax)
可以这样理解上述的执行过程:
由于t2的内容已经拷贝到t1了,所以t1就相当于foo函数返回的t2
从上面分析来看,其实foo函数的声明struct Test foo()更像是void foo(struct Test *ret)
struct Test foo()
void foo(struct Test *ret)
The text was updated successfully, but these errors were encountered:
No branches or pull requests
我们知道一般情况下函数的返回值是通过eax或rax寄存器来返回的,但是当我们返回值超过eax和rax所能存储的大小情况呢?
以下面代码为例,函数返回大小为32字节的结构体对象
查看该文件编译后的汇编代码
汇编代码的意义如下
首先看main函数,函数main在栈上开辟0x20大小的空间,并将栈顶的地址赋值给rdi寄存器(作为传递给foo的第一个参数)。
接下来看foo函数,函数foo在栈上开辟0x28大小的空间,并将栈顶(8个字节)的值赋值为%rdi(即main函数传递进来的地址)。然后将该栈上剩下的0x20大小的内存数据对应复制到main函数开辟的0x20大小的栈空间。
可以这样理解上述的执行过程:
由于t2的内容已经拷贝到t1了,所以t1就相当于foo函数返回的t2
从上面分析来看,其实foo函数的声明
struct Test foo()
更像是void foo(struct Test *ret)
The text was updated successfully, but these errors were encountered: