汇编角度看函数返回大对象原理

汇编角度看函数返回大对象原理

Win32

测试代码

C++
struct ABCED
{
        int a;
        int b;
        int c;
        int d;
};
ABCED TestABC()
{
        ABCED aa;
        aa.a = 1;
        aa.b = 32;
        return aa;
}
MVoid TestA()
{
        TestABC();
        return;
}

 来看下汇编代码

TestA()

C++
00D70D30  push        ebp 
00D70D31  mov         ebp,esp 
00D70D33  sub         esp,0F4h 
00D70D39  push        ebx 
00D70D3A  push        esi 
00D70D3B  push        edi 
00D70D3C  lea         edi,[ebp+FFFFFF0Ch] 
00D70D42  mov         ecx,3Dh 
00D70D47  mov         eax,0CCCCCCCCh 
00D70D4C  rep stos    dword ptr es:[edi] 
00D70D4E  mov         eax,dword ptr ds:[023100B4h] 
00D70D53  xor         eax,ebp 
00D70D55  mov         dword ptr [ebp-4],eax 
00D70D58  lea         eax,[ebp+FFFFFF10h] 
00D70D5E  push        eax 
00D70D5F  call        00D70DB0 
00D70D64  add         esp,4 
00D70D67  mov         ecx,dword ptr [eax] 
00D70D69  mov         dword ptr [ebp+FFFFFF28h],ecx 
00D70D6F  mov         edx,dword ptr [eax+4] 
00D70D72  mov         dword ptr [ebp+FFFFFF2Ch],edx 
00D70D78  mov         ecx,dword ptr [eax+8] 
00D70D7B  mov         dword ptr [ebp+FFFFFF30h],ecx 
00D70D81  mov         edx,dword ptr [eax+0Ch] 
00D70D84  mov         dword ptr [ebp+FFFFFF34h],edx 
00D70D8A  pop         edi 
00D70D8B  pop         esi 
00D70D8C  pop         ebx 

TestABC()

C++
00D70DB0  push        ebp 
00D70DB1  mov         ebp,esp 
00D70DB3  sub         esp,0DCh 
00D70DB9  push        ebx 
00D70DBA  push        esi 
00D70DBB  push        edi 
00D70DBC  lea         edi,[ebp+FFFFFF24h] 
00D70DC2  mov         ecx,37h 
00D70DC7  mov         eax,0CCCCCCCCh 
00D70DCC  rep stos    dword ptr es:[edi];把函数栈空间初始化0xCCCCCCCC
00D70DCE  mov         eax,dword ptr ds:[023100B4h] 
00D70DD3  xor         eax,ebp 
00D70DD5  mov         dword ptr [ebp-4],eax 
00D70DD8  mov         dword ptr [ebp-18h],1 
00D70DDF  mov         dword ptr [ebp-14h],20h 
00D70DE6  mov         eax,dword ptr [ebp+8] 
00D70DE9  mov         ecx,dword ptr [ebp-18h];ecx = 1 
00D70DEC  mov         dword ptr [eax],ecx  ;AA.a;[ebp+8]=1
00D70DEE  mov         edx,dword ptr [ebp-14h] ;edx = 0x20
00D70DF1  mov         dword ptr [eax+4],edx  ;AA.b;[ebp + 12] = 0x20
00D70DF4  mov         ecx,dword ptr [ebp-10h];AA.c 
00D70DF7  mov         dword ptr [eax+8],ecx  ;;[ebp + 16]
00D70DFA  mov         edx,dword ptr [ebp-0Ch]  ;AA.d
00D70DFD  mov         dword ptr [eax+0Ch],edx  ;;[ebp + 20]
00D70E00  mov         eax,dword ptr [ebp+8] ;[ebp+8] 也就是TestA ebp+FFFFFF28h也就是
                        ;也就是TestA ebp-D8,

这就跟上边联系起来了,虽然TestA()里边什么也没有定义,也可以的出来栈空间还是分配了具体的空间,所以这里建议大家不要轻易返回大空间对象。接下来我们看下arm64的做法是否一致的

arm64

C++
struct ABCED
{
        int a;
        int b;
        int c;
        int d;
};
ABCED TestABC()
{
        ABCED aa;
        aa.a = 1;
        aa.b = 32;
        return aa;
}
void TestA()
{
        TestABC();
        return;
}

TestA

Assembly language
0x100003c6c <+0>:  sub    sp, sp, #0x20
0x100003c70 <+4>:  stp    x29, x30, [sp, #0x10]
0x100003c74 <+8>:  add    x29, sp, #0x10
0x100003c78 <+12>: bl     0x100003c48               ; TestABC at main.mm:20
0x100003c7c <+16>: str    x0, [sp];返回值ABCED.a, ABCED.b
0x100003c80 <+20>: str    x1, [sp, #0x8];返回值ABCED.c, ABCED.d
0x100003c84 <+24>: ldp    x29, x30, [sp, #0x10]
0x100003c88 <+28>: add    sp, sp, #0x20;恢复栈
0x100003c8c <+32>: ret   
 

TestABC

Assembly language
 0x100003c48 <+0>:  sub    sp, sp, #0x10
0x100003c4c <+4>:  mov    w8, #0x1
0x100003c50 <+8>:  str    w8, [sp];1 保存sp + 0
0x100003c54 <+12>: mov    w8, #0x20
0x100003c58 <+16>: str    w8, [sp, #0x4]; 32保存在sp + 4
0x100003c5c <+20>: ldr    x0, [sp];把 ABCED.a, ABCED.b 保存x0
0x100003c60 <+24>: ldr    x1, [sp, #0x8];;把 ABCED.c, ABCED.c 保存x1
0x100003c64 <+28>: add    sp, sp, #0x10 ;函数栈返回
0x100003c68 <+32>: ret   
 

arm64汇编同样也可以看的出来,在TestA并没有分配对象空间,但是汇编代码上看,确实给其返回分配了空间,所以同样建议不要返回大空间对象,如果需要传递可以传递指针

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值