分析c++代码的汇编代码,并且解释i++和++i在运行时的不同

3: int main() {
006A2010  push        ebp  
006A2011  mov         ebp,esp  
006A2013  sub         esp,0CCh  
006A2019  push        ebx  
006A201A  push        esi  
006A201B  push        edi  
006A201C  lea         edi,[ebp-0CCh]  
006A2022  mov         ecx,33h  
006A2027  mov         eax,0CCCCCCCCh  
006A202C  rep stos    dword ptr es:[edi]  
006A202E  mov         ecx,offset _05E82D75_大三下\大三下\test@cpp (06AE026h)  
006A2033  call        @__CheckForDebuggerJustMyCode@4 (06A1271h)  
     4: 	int i = 1;
006A2038  mov         dword ptr [i],1  
     5: 	i++;
006A203F  mov         eax,dword ptr [i]  
006A2042  add         eax,1  
006A2045  mov         dword ptr [i],eax  
     6: 	++i;
006A2048  mov         eax,dword ptr [i]  
006A204B  add         eax,1  
006A204E  mov         dword ptr [i],eax  
     7: 	return 1;
006A2051  mov         eax,1  
     8: }
006A2056  pop         edi  
006A2057  pop         esi  
006A2058  pop         ebx  
006A2059  add         esp,0CCh  
006A205F  cmp         ebp,esp  
006A2061  call        __RTC_CheckEsp (06A127Bh)  
006A2066  mov         esp,ebp  
006A2068  pop         ebp  
006A2069  ret  
--- 无源文件 -----------------------------------------------------------------------
006A206A  int         3  
006A206B  int         3  

  1. push ebp首先是执行一个函数的必要步骤,在堆栈里面放入ebp,这是调用main函数之前的堆栈的栈底地址,用来在main函数结束之后恢复堆栈用的。

  2. move ebp esp 然后把ebp=esp也就是把栈底放到现在的栈顶的地方来。

  3. sub esp,0CCh 把esp减去0CC由于栈地址是向低地址扩展的,所以我们是把栈空间扩展0cc个bit

  4. push ebx
    push esi
    push edi
    保存一些寄存器,这些是可以在main函数里面使用到的,所以我们先保存起来,到时候main函数结束了,我们就把它恢复起来。

  5. 006A201C lea edi,[ebp-0CCh]
    lea的意思是load effective address 把[ebp-0cch]里面的有效地址给了edi,也就是ebp-0cch赋值给了edi,需要注意的是edi作为一个特殊的 寄存器,在循环指令里面会递增,在循环指令里面ecx是默认的循环次数

  6. 006A2022 mov ecx,33h 设置循环次数33h是0cch的四分之一,因为我们的一次循环会赋值四个字节,也就是dword ptr双字

  7. 006A2027 mov eax,0CCCCCCCCh 这是我们循环里面需要赋的值也就是int 3中断的值,int3是一个指令int表示指令的名字,3是这条指令的参数,int 3这条指令就是一条中断的指令。

  8. 006A202C rep stos dword ptr es:[edi]
    这里比较难理解,rep是重复之后指令的指令
    stos是store into string指令,把eax的值放到地址为edi的内存上面去。接着edi会自增,ecx会减一,这样我们就可以把刚刚扩展堆栈的那些空内存赋值为int 3指令了,这样如果不小心运行到这就会中断。这里面dword ptr是双字指针的意思,代表着后面的这个东西是一个地址,es是段寄存器,[edi]是偏移量

  9. 006A202E mov ecx,offset _05E82D75_大三下\大三下\test@cpp (06AE026h) offset是取首地址的意思

  10. 006A2033 call @__CheckForDebuggerJustMyCode@4 (06A1271h) 不懂

  11. 4: 	int i = 1;
    

006A2038 mov dword ptr [i],1
5: i++;
006A203F mov eax,dword ptr [i]
006A2042 add eax,1
006A2045 mov dword ptr [i],eax
6: ++i;
006A2048 mov eax,dword ptr [i]
006A204B add eax,1
这里的i对应的代码是一样的

cout << i++;
0086203F  mov         eax,dword ptr [i]  
00862042  mov         dword ptr [ebp-0D0h],eax  
00862048  mov         ecx,dword ptr [i]  
0086204B  add         ecx,1  
0086204E  mov         dword ptr [i],ecx  
00862051  mov         esi,esp  
00862053  mov         edx,dword ptr [ebp-0D0h]  
00862059  push        edx  
0086205A  mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (086D0C8h)]  
00862060  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (086D0D0h)]  
00862066  cmp         esi,esp  
00862068  call        __RTC_CheckEsp (086127Bh)  
     7: 	cout << ++i;
0086206D  mov         eax,dword ptr [i]  
00862070  add         eax,1  
00862073  mov         dword ptr [i],eax  
00862076  mov         esi,esp  
00862078  mov         ecx,dword ptr [i]  
0086207B  push        ecx  
0086207C  mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (086D0C8h)]  
00862082  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (086D0D0h)]  
00862088  cmp         esi,esp  
0086208A  call        __RTC_CheckEsp (086127Bh)  
     8: 	return 1;

当我们把i输出的时候,我们发现,在将函数的变量压栈的时候,两者不一样,对于i++是吧从内存里面取出来的 值先放到栈里面,然后在把内存里面的值加一,然后函数调用的时候是拿栈里面的 值当做参数push进去栈的。

而++i是在把内存里面的值加一了之后就直接把该内存里面的值拿出来当做函数参数放到栈里面

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值