您的位置:首页 > 运维架构 > Linux

c++(vs上)与g++(linux下)对于++操作的汇编代码解读

2016-08-30 16:21 309 查看
先来看一个代码,估计很多同学都碰到过其中的某一个。

#include<stdio.h>
#include<iostream>
usingnamespacestd;
intmain()
{
inta=5;
printf("a++=%d\n",a++);

a=5;
printf("++a=%d\n",++a);

a=5;
printf("a+=a++=%d\n",a+=a++);
a=5;
printf("a+=(a++)=%d\n",a=a+(a++));

a=5;
printf("a+=++a=%d\n",a+=++a);
a=5;
printf("a+=(++a)=%d\n",a+=(++a));

a=5;
printf("++a+=a++=%d\n",++a+=a++);
a=5;
printf("(++a)+=(a++)=%d\n",(++a)+=(a++));

return1;
}


估计很多同学都饱受摧残(T-T)。

更坑的是,卧槽不同编译器下会有不用的结果。(╯°口°)╯(┴—┴

a.VS2013下的运行结果



b.g++下的运行结果



从结果可以看出,除了最开始两个书本上教的a++与++a是一致的(a++是先取a值然后再执行a=a+1,++a是先a=a+1,在取a的值)外,其他很多都不相同。

(゚Д゚≡゚д゚)!?这也能玩?

百思不得其姐,打开汇编代码一探究竟。
先来看下vs下的汇编(拍下脑子想下大一学的汇编):


/*vs2013*/
13:printf("a+=a++=%d\n",a+=a++);
011ECAC7moveax,dwordptr[a]    //把a的值放入eax寄存器中
011ECACAaddeax,dwordptr[a]    //把a的值加到eax中(eax=eax+a)
011ECACDmovdwordptr[a],eax    //把eax的值放入a,以上就是+=的操作
011ECAD0movecx,dwordptr[a]    //把a放入ecx寄存器中
011ECAD3movdwordptr[ebp-0D0h],ecx//直接打印了。。。--!也就是忽略了a++直接打印了
011ECAD9movedx,dwordptr[a]    //接下来就是执行a++,以及以下基础操作了。
011ECADCaddedx,1
011ECADFmovdwordptr[a],edx
011ECAE2movesi,esp
011ECAE4moveax,dwordptr[ebp-0D0h]
011ECAEApusheax
011ECAEBpush11F832Ch
011ECAF0calldwordptrds:[11FC1E4h]
011ECAF6addesp,8
011ECAF9cmpesi,esp
011ECAFBcall__RTC_CheckEsp(011E1631h)


简单的分析了,发现vs中a++的操作放在最后面执行。
再来瞧瞧g++的汇编代码:
g++下汇编和vs下汇编有很大不同,最大的一个是
vs:mova,b指将b->a
g++:mova,b指将a->b
(我改了下顺序,你就不能说我抄袭了吧😄)


/*g++4.8.2*/
13printf("a+=a++=%d\n",a+=a++);
0x08048602<+85>:mov0x1c(%esp),%eax  //将这行代码的变量也就是a给eax寄存器,
0x08048606<+89>:lea0x1(%eax),%edx   //表示将eax里的值+1赋值给edx寄存器,
0x08048609<+92>:mov%edx,0x1c(%esp)  //edx->a(此时a为6,eax为5)
0x0804860d<+96>:add%eax,0x1c(%esp)  //a=a+eax
0x08048611<+100>:mov0x1c(%esp),%eax //接下来就是调用打印的程序了
0x08048615<+104>:mov%eax,0x4(%esp)  
0x08048619<+108>:movl$0x8048814,(%esp)
0x08048620<+115>:call0x80484a0<printf@plt>


从汇编代码可以看出,g++编译时,把a++运算的a先放入一个寄存器eax,然后立马执行a=a+1,这时寄存器eax的值还是没有变的,然后再执行a=a+eax,所以结果为11.

通过汇编的理解,我们知道了机器到底是怎么做这些运算的,有兴趣的同学还可以把后面几个更复杂的式子用汇编代码敲敲,但是我选择以后编程的时候多加括号。(´・_・`)

如果要强行总结:那么vs编译时把a++这种操作放在最后进行,所以在分析时先忽略这个操作,最后再来。而g++则先把a拿到一个寄存器中准备以后用,然后立马执行a=a+1,真正用的时候还是用的寄存器里的值。


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: