一 何为返回值
一个函数有返回值类型声明,比如int,char,int*,char*,struct xxxx 等。
在函数执行结束的末尾,需要显示的写代码return xxx与函数声明的返回值类型相同。
二 普通返回值类型
int,char,int*,char*,float* 等。
这种返回值类型都是直接通过eax寄存器返回的,返回值的生命周期,显然就是与eax寄存器的值是否有被覆盖有关。
我们看下具体实例:
int func()
{
printf("func running\n");
return 10;
}
00000000004005a4 <_Z4funcv>:
4005a4: 55 push %rbp
4005a5: 48 89 e5 mov %rsp,%rbp
4005a8: bf c8 06 40 00 mov $0x4006c8,%edi
4005ad: e8 d6 fe ff ff callq 400488 <puts@plt>
4005b2: b8 0a 00 00 00 mov $0xa,%eax ;//return 10
4005b7: c9 leaveq
4005b8: c3 retq
三 对象返回类型
对象返回类型和普通返回类型稍有不同,对象返回类型和返回动态申请的对象的地址是类似的,即便返回值是对象本身。
int main()
{
int b = func();
get_str();
return 0;
}
std::string get_str()
{
printf("get_str running\n");
return std::string("get_str");
}
0000000000400830 <main>:
400830: 55 push %rbp
400831: 48 89 e5 mov %rsp,%rbp
400834: 48 83 ec 10 sub $0x10,%rsp
400838: e8 67 ff ff ff callq 4007a4 <_Z4funcv>
40083d: 89 45 fc mov %eax,-0x4(%rbp);
400840: 48 8d 45 f0 lea -0x10(%rbp),%rax//从栈顶开始腾出一块空间,存到rax,转移到rdi传到函数内部
400844: 48 89 c7 mov %rax,%rdi
400847: e8 6d ff ff ff callq 4007b9 <_Z7get_strv>
00000000004007b9 <_Z7get_strv>:
4007b9: 55 push %rbp
4007ba: 48 89 e5 mov %rsp,%rbp
4007bd: 41 54 push %r12
4007bf: 53 push %rbx
4007c0: 48 83 ec 10 sub $0x10,%rsp
4007c4: 48 89 fb mov %rdi,%rbx ;//取出外面传进来的临时对象地址,进行赋值构造std::string
4007c7: bf 65 09 40 00 mov $0x400965,%edi
4007cc: e8 67 fe ff ff callq 400638 <puts@plt>
4007d1: 49 89 dc mov %rbx,%r12
4007d4: 48 8d 45 ef lea -0x11(%rbp),%rax
4007d8: 48 89 c7 mov %rax,%rdi
4007db: e8 a8 fe ff ff callq 400688 <_ZNSaIcEC1Ev@plt>
4007e0: 48 8d 45 ef lea -0x11(%rbp),%rax
4007e4: 48 89 c2 mov %rax,%rdx
4007e7: be 75 09 40 00 mov $0x400975,%esi
4007ec: 4c 89 e7 mov %r12,%rdi
4007ef: e8 74 fe ff ff callq 400668 <_ZNSsC1EPKcRKSaIcE@plt>
4007f4: eb 1f jmp 400815 <_Z7get_strv+0x5c>
4007f6: 89 d3 mov %edx,%ebx
4007f8: 49 89 c4 mov %rax,%r12
4007fb: 48 8d 45 ef lea -0x11(%rbp),%rax
4007ff: 48 89 c7 mov %rax,%rdi
注意:这里调用get_str函数调用之前,main函数先预留一块临时对象空间。sub $0x10,%rsp;
PS:如果读不懂此篇博客,建议先学习一下什么是栈帧,以及elf文件编译后调用函数的过程。
一个函数有返回值类型声明,比如int,char,int*,char*,struct xxxx 等。
在函数执行结束的末尾,需要显示的写代码return xxx与函数声明的返回值类型相同。
二 普通返回值类型
int,char,int*,char*,float* 等。
这种返回值类型都是直接通过eax寄存器返回的,返回值的生命周期,显然就是与eax寄存器的值是否有被覆盖有关。
我们看下具体实例:
int func()
{
printf("func running\n");
return 10;
}
00000000004005a4 <_Z4funcv>:
4005a4: 55 push %rbp
4005a5: 48 89 e5 mov %rsp,%rbp
4005a8: bf c8 06 40 00 mov $0x4006c8,%edi
4005ad: e8 d6 fe ff ff callq 400488 <puts@plt>
4005b2: b8 0a 00 00 00 mov $0xa,%eax ;//return 10
4005b7: c9 leaveq
4005b8: c3 retq
三 对象返回类型
对象返回类型和普通返回类型稍有不同,对象返回类型和返回动态申请的对象的地址是类似的,即便返回值是对象本身。
int main()
{
int b = func();
get_str();
return 0;
}
std::string get_str()
{
printf("get_str running\n");
return std::string("get_str");
}
0000000000400830 <main>:
400830: 55 push %rbp
400831: 48 89 e5 mov %rsp,%rbp
400834: 48 83 ec 10 sub $0x10,%rsp
400838: e8 67 ff ff ff callq 4007a4 <_Z4funcv>
40083d: 89 45 fc mov %eax,-0x4(%rbp);
400840: 48 8d 45 f0 lea -0x10(%rbp),%rax//从栈顶开始腾出一块空间,存到rax,转移到rdi传到函数内部
400844: 48 89 c7 mov %rax,%rdi
400847: e8 6d ff ff ff callq 4007b9 <_Z7get_strv>
00000000004007b9 <_Z7get_strv>:
4007b9: 55 push %rbp
4007ba: 48 89 e5 mov %rsp,%rbp
4007bd: 41 54 push %r12
4007bf: 53 push %rbx
4007c0: 48 83 ec 10 sub $0x10,%rsp
4007c4: 48 89 fb mov %rdi,%rbx ;//取出外面传进来的临时对象地址,进行赋值构造std::string
4007c7: bf 65 09 40 00 mov $0x400965,%edi
4007cc: e8 67 fe ff ff callq 400638 <puts@plt>
4007d1: 49 89 dc mov %rbx,%r12
4007d4: 48 8d 45 ef lea -0x11(%rbp),%rax
4007d8: 48 89 c7 mov %rax,%rdi
4007db: e8 a8 fe ff ff callq 400688 <_ZNSaIcEC1Ev@plt>
4007e0: 48 8d 45 ef lea -0x11(%rbp),%rax
4007e4: 48 89 c2 mov %rax,%rdx
4007e7: be 75 09 40 00 mov $0x400975,%esi
4007ec: 4c 89 e7 mov %r12,%rdi
4007ef: e8 74 fe ff ff callq 400668 <_ZNSsC1EPKcRKSaIcE@plt>
4007f4: eb 1f jmp 400815 <_Z7get_strv+0x5c>
4007f6: 89 d3 mov %edx,%ebx
4007f8: 49 89 c4 mov %rax,%r12
4007fb: 48 8d 45 ef lea -0x11(%rbp),%rax
4007ff: 48 89 c7 mov %rax,%rdi
注意:这里调用get_str函数调用之前,main函数先预留一块临时对象空间。sub $0x10,%rsp;
PS:如果读不懂此篇博客,建议先学习一下什么是栈帧,以及elf文件编译后调用函数的过程。
本文详细解释了函数中返回值的概念及其实现方式,包括基本类型的返回值如何通过寄存器传递,以及对象类型的返回值如何通过栈帧进行构造和传递。
939

被折叠的 条评论
为什么被折叠?



