栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++:汇编:函数里return 栈内vector变量时,是怎么走的

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++:汇编:函数里return 栈内vector变量时,是怎么走的

代码
const int max_v=100;
const string abc="abc";
//int foo()
//{}
vector foo()
{
        vector abc(max_v,"test");
        return abc;
}
int main()
{
//vector v_s_a;
//unique_ptr u_s_b (new abc);
//v_s_a.push_back(move(u_s_b));
vector  a;
a=foo();
for(auto b:a)
        cout< 
汇编 
0000000000400bb6 :
  400bb6:       55                      push   %rbp
  400bb7:       48 89 e5                mov    %rsp,%rbp
  400bba:       53                      push   %rbx
  400bbb:       48 83 ec 58             sub    $0x58,%rsp   分配栈空间
  400bbf:       48 89 7d a8             mov    %rdi,-0x58(%rbp)   第一个参数放到 0x58这个位置;就是vector的this 指针。
  400bc3:       48 8d 45 bf             lea    -0x41(%rbp),%rax   分配一个string类型的allocator的对象指针在041 这个位置
  400bc7:       48 89 c7                mov    %rax,%rdi
  400bca:       e8 89 01 00 00          callq  400d58 , allocator > >::allocator()>   分配器,分配string;
  400bcf:       48 8d 45 ef             lea    -0x11(%rbp),%rax   11 这个位置 是做什么? 是一个 allocator对象的地址。
  400bd3:       48 89 c7                mov    %rax,%rdi
  400bd6:       e8 d5 fe ff ff          callq  400ab0 ::allocator()@plt>
  400bdb:       48 8d 55 ef             lea    -0x11(%rbp),%rdx   第三个参数,allocator地址
  400bdf:       48 8d 45 c0             lea    -0x40(%rbp),%rax  string 对象地址
  400be3:       be e8 13 40 00          mov    $0x4013e8,%esi   全局字符常量地址
  400be8:       48 89 c7                mov    %rax,%rdi    string 对象指针。
  400beb:       e8 60 fe ff ff          callq  400a50 , std::allocator >::basic_string(char const*, std::allocator const&)@plt>  、、、构造string
  400bf0:       48 8d 4d bf             lea    -0x41(%rbp),%rcx   string 对象allocator指针
  400bf4:       48 8d 55 c0             lea    -0x40(%rbp),%rdx   string 对象
  400bf8:       48 8b 45 a8             mov    -0x58(%rbp),%rax   vector 对象地址  直接放到了 调用者栈里   !!!!!
  400bfc:       be 64 00 00 00          mov    $0x64,%esi,数量大小。调用 vector的 构造函数构造100 个元素
  400c01:       48 89 c7                mov    %rax,%rdi    vector 对象 this 指针
  400c04:       e8 87 01 00 00          callq  400d90 , std::allocator >, std::allocator, std::allocator > > >::vector(unsigned long, std::__cxx11::basic_string, std::allocator > const&, std::allocator, std::allocator > > const&)>
  400c09:       48 8d 45 c0             lea    -0x40(%rbp),%rax   将 rbp-0x40 地址放到rax
  400c0d:       48 89 c7                mov    %rax,%rdi           传入第一个参数,析构 string;
  400c10:       e8 eb fd ff ff          callq  400a00 , std::allocator >::~basic_string()@plt>
  400c15:       48 8d 45 ef             lea    -0x11(%rbp),%rax    、、、、 后续就是做析构对象操作。
  400c19:       48 89 c7                mov    %rax,%rdi
  400c1c:       e8 1f fe ff ff          callq  400a40 ::~allocator()@plt>
  400c21:       48 8d 45 bf             lea    -0x41(%rbp),%rax
  400c25:       48 89 c7                mov    %rax,%rdi
  400c28:       e8 47 01 00 00          callq  400d74 , std::allocator >  >::~allocator()>
  400c2d:       eb 37                   jmp    400c66 
  400c2f:       48 89 c3                mov    %rax,%rbx
  400c32:       48 8d 45 c0             lea    -0x40(%rbp),%rax
  400c36:       48 89 c7                mov    %rax,%rdi
  400c39:       e8 c2 fd ff ff          callq  400a00 , std::allocator >::~basic_string()@plt>
  400c3e:       eb 03                   jmp    400c43 
  400c40:       48 89 c3                mov    %rax,%rbx
  400c43:       48 8d 45 ef             lea    -0x11(%rbp),%rax
  400c47:       48 89 c7                mov    %rax,%rdi
  400c4a:       e8 f1 fd ff ff          callq  400a40 ::~allocator()@plt>
  400c4f:       48 8d 45 bf             lea    -0x41(%rbp),%rax
  400c53:       48 89 c7                mov    %rax,%rdi
  400c56:       e8 19 01 00 00          callq  400d74 , std::allocator > >::~allocator()>
  400c5b:       48 89 d8                mov    %rbx,%rax
  400c5e:       48 89 c7                mov    %rax,%rdi
  400c61:       e8 3a fe ff ff          callq  400aa0 <_Unwind_Resume@plt>
  400c66:       48 8b 45 a8             mov    -0x58(%rbp),%rax   将-x58 这个地址放到 rax,其实栈上的数据还在。看看调用者怎么用?
  400c6a:       48 83 c4 58             add    $0x58,%rsp
  400c6e:       5b                      pop    %rbx
  400c6f:       5d                      pop    %rbp
  400c70:       c3                      retq


0000000000400e31 
: 400e31: 55 push %rbp 400e32: 48 89 e5 mov %rsp,%rbp 400e35: 53 push %rbx 400e36: 48 83 ec 78 sub $0x78,%rsp 400e3a: 48 8d 45 b0 lea -0x50(%rbp),%rax 400e3e: 48 89 c7 mov %rax,%rdi 400e41: e8 c8 02 00 00 callq 40110e , std::allocator >, std::allocator, std::allocator > > >::vector()> 400e46: 48 8d 45 d0 lea -0x30(%rbp),%rax 将 rbp-x30地址放到 第一个参数 400e4a: 48 89 c7 mov %rax,%rdi 400e4d: e8 24 ff ff ff callq 400d76 400e52: 48 8d 55 d0 lea -0x30(%rbp),%rdx foo 函数创建的 vector,地址。 400e56: 48 8d 45 b0 lea -0x50(%rbp),%rax 在 栈上新建 rbp-50 ,vector 400e5a: 48 89 d6 mov %rdx,%rsi 400e5d: 48 89 c7 mov %rax,%rdi 400e60: e8 c5 02 00 00 callq 40112a , std::allocator >, std::allocator, std::allocator > > >::operator=(std::vector, std::allocator >, std::allocator, std::allocator > > >&&)> 400e65: 48 8d 45 d0 lea -0x30(%rbp),%rax 400e69: 48 89 c7 mov %rax,%rdi 400e6c: e8 59 02 00 00 callq 4010ca , std::allocator >, std::allocator, std::allocator > > >::~vector()> 400e71: 48 8d 45 b0 lea -0x50(%rbp),%rax 400e75: 48 89 45 e8 mov %rax,-0x18(%rbp) 400e79: 48 8b 45 e8 mov -0x18(%rbp),%rax 400e7d: 48 89 c7 mov %rax,%rdi 400e80: e8 dd 02 00 00 callq 401162 , std::allocator >, std::allocator, std::allocator > > >::begin()> 400e85: 48 89 45 a8 mov %rax,-0x58(%rbp) 400e89: 48 8b 45 e8 mov -0x18(%rbp),%rax 400e90: e8 f3 02 00 00 callq 401188 , std::allocator >, s td::allocator, std::allocator > > >::end()> 400e95: 48 89 45 a0 mov %rax,-0x60(%rbp) 400e99: 48 8d 55 a0 lea -0x60(%rbp),%rdx 400e9d: 48 8d 45 a8 lea -0x58(%rbp),%rax 400ea1: 48 89 d6 mov %rdx,%rsi 400ea4: 48 89 c7 mov %rax,%rdi 400ea7: e8 05 03 00 00 callq 4011b1 , std::alloc ator >*, std::vector, std::allocator >, std::allocator, std::allocator > > > >(__gnu_cxx::__normal_iterator, std ::allocator >*, std::vector, std::allocator >, std::allocator, std::allocator > > > > const&, __gnu_cxx::__normal_iterator, std::allocator >*, std::vector, std::allocator >, std::allocator, std::allocator > > > > const&)> 400eac: 84 c0 test %al,%al 400eae: 74 56 je 400f06 400eb0: 48 8d 45 a8 lea -0x58(%rbp),%rax 400eb4: 48 89 c7 mov %rax,%rdi 400eb7: e8 52 03 00 00 callq 40120e <__gnu_cxx::__normal_iterator, std::all ocator >*, std::vector, std::allocator >, std::allocator, std::allocator > > > >::operator*() const> 400ebc: 48 89 c2 mov %rax,%rdx 400ebf: 48 8d 45 80 lea -0x80(%rbp),%rax 400ec3: 48 89 d6 mov %rdx,%rsi 400ec6: 48 89 c7 mov %rax,%rdi 400ec9: e8 b2 fc ff ff callq 400b80 , std::allocator >::basic_string(std::__cxx11::basic_string, std::allocator > const&)@plt> 400ece: 48 8d 45 80 lea -0x80(%rbp),%rax 400ed2: 48 89 c6 mov %rax,%rsi 400ed5: bf c0 30 60 00 mov $0x6030c0,%edi 400eda: e8 e1 fc ff ff callq 400bc0 >& std::operator<< , std::allocator >(std::basic_ostream >&, std::__cxx11::basic_string, std::allocator > const&)@plt> 400edf: be 90 0b 40 00 mov $0x400b90,%esi 400ee4: 48 89 c7 mov %rax,%rdi 400ee7: e8 04 fd ff ff callq 400bf0 400eec: 48 8d 45 80 lea -0x80(%rbp),%rax 400ef0: 48 89 c7 mov %rax,%rdi 400ef3: e8 a8 fc ff ff callq 400ba0 , std::allocator >::~basic_string()@plt> 400ef8: 48 8d 45 a8 lea -0x58(%rbp),%rax 400efc: 48 89 c7 mov %rax,%rdi 400eff: e8 ea 02 00 00 callq 4011ee <__gnu_cxx::__normal_iterator, std::all ocator >*, std::vector, std::allocator >, std::allocator, std::allocator > > > >::operator++()> 400f04: eb 93 jmp 400e99 400f06: bb 00 00 00 00 mov $0x0,%ebx 400f0b: 48 8d 45 b0 lea -0x50(%rbp),%rax 400f0f: 48 89 c7 mov %rax,%rdi 400f12: e8 b3 01 00 00 callq 4010ca , std::allocator >, s td::allocator, std::allocator > > >::~vector()> 400f17: 89 d8 mov %ebx,%eax 400f19: eb 2b jmp 400f46 400f1b: 48 89 c3 mov %rax,%rbx 400f1e: 48 8d 45 80 lea -0x80(%rbp),%rax 400f22: 48 89 c7 mov %rax,%rdi 400f25: e8 76 fc ff ff callq 400ba0 , std::allocator >::~basic_string ()@plt> 400f2a: eb 03 jmp 400f2f 400f2c: 48 89 c3 mov %rax,%rbx 400f2f: 48 8d 45 b0 lea -0x50(%rbp),%rax 400f33: 48 89 c7 mov %rax,%rdi 400f36: e8 8f 01 00 00 callq 4010ca , std::allocator >, s td::allocator, std::allocator > > >::~vector()> 400f3b: 48 89 d8 mov %rbx,%rax 400f3e: 48 89 c7 mov %rax,%rdi 400f41: e8 1a fd ff ff callq 400c60 <_Unwind_Resume@plt> 400f46: 48 83 c4 78 add $0x78,%rsp 400f4a: 5b pop %rbx 400f4b: 5d pop %rbp 400f4c: c3 retq 000000000040112a , std::allocator >, std::allocator, std::allocator > > >::operator=(std::vector, std::allocator >, std::allocator, std::allocator > > >&&)>: 、、、、 move 赋值构造函数 40112a: 55 push %rbp 40112b: 48 89 e5 mov %rsp,%rbp 40112e: 48 83 ec 20 sub $0x20,%rsp 401132: 48 89 7d e8 mov %rdi,-0x18(%rbp) 401136: 48 89 75 e0 mov %rsi,-0x20(%rbp) 40113a: c6 45 ff 01 movb $0x1,-0x1(%rbp) 40113e: 48 8b 45 e0 mov -0x20(%rbp),%rax 第二个参数传入 remove_reference,去除引用, 401142: 48 89 c7 mov %rax,%rdi 401145: e8 36 02 00 00 callq 401380 , std::allocator >, std::allocator, std::allocator > > >&>::type&& std::move, std::allocator >, std::allocator, std::allocator > > >&>(std::vector, std::allocator >, std::allocator, std::allocator > > >&)> 40114a: 48 89 c2 mov %rax,%rdx 40114d: 48 8b 45 e8 mov -0x18(%rbp),%rax 401151: 48 89 d6 mov %rdx,%rsi 401154: 48 89 c7 mov %rax,%rdi 401157: e8 4e 02 00 00 callq 4013aa , std::allocator >, std::allocator, std::allocator > > >::_M_move_assign(std::vector, std::allocator >, std::allocator, std::allocator > > >&&, std::integral_constant)> 右值引用的allocator 40115c: 48 8b 45 e8 mov -0x18(%rbp),%rax 右值 401160: c9 leaveq 401161: c3 retq 00000000004013aa , std::allocator >, std::allocator, std::allocator > > >::_M_move_assign(std::vector, std ::allocator >, std::allocator, std::allocator > > >&&, std::integral_constant)>: 4013aa: 55 push %rbp 4013ab: 48 89 e5 mov %rsp,%rbp 4013ae: 53 push %rbx 4013af: 48 83 ec 38 sub $0x38,%rsp 4013b3: 48 89 7d c8 mov %rdi,-0x38(%rbp) 4013b7: 48 89 75 c0 mov %rsi,-0x40(%rbp) 4013bb: 48 8b 55 c8 mov -0x38(%rbp),%rdx 4013bf: 48 8d 45 ef lea -0x11(%rbp),%rax 4013c3: 48 89 d6 mov %rdx,%rsi 4013c6: 48 89 c7 mov %rax,%rdi 4013c9: e8 84 02 00 00 callq 401652 , std::allocator >, std::allocator, std::allocator > > >::get_allocator() const> 4013ce: 48 8d 55 ef lea -0x11(%rbp),%rdx 4013d2: 48 8d 45 d0 lea -0x30(%rbp),%rax 4013d6: 48 89 d6 mov %rdx,%rsi 4013d9: 48 89 c7 mov %rax,%rdi 4013dc: e8 a5 02 00 00 callq 401686 , std::allocator >, std::allocator, std::allocator > > >::vector(std::allocator, std::allocator > > const&)> 4013e1: 48 8d 45 ef lea -0x11(%rbp),%rax 4013e5: 48 89 c7 mov %rax,%rdi 4013e8: e8 57 fc ff ff callq 401044 , std::allocator > >::~allocator()> 4013ed: 48 8b 45 c8 mov -0x38(%rbp),%rax 4013f1: 48 8d 55 d0 lea -0x30(%rbp),%rdx 4013f5: 48 89 d6 mov %rdx,%rsi 4013f8: 48 89 c7 mov %rax,%rdi
解释

gcc 分了两步做这个return value的转移:

  1. 在calling function,分配栈地址,传递给foo 函数,作为vector 引用的传递媒介。
  2. 使用 move 赋值 构造函数,并利用 上一步的媒介地址,右值引用,创建新的vector 列表。

汇编里的函数符号真是太长了。
打印输出一下地址看看;地址都是一样的。
10 addr=0x1ca6ff0 50 addr=0x1ca7630
10 addr=0x1ca6ff0 50 addr=0x1ca7630

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/605397.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号