汇编较C++而言更为底层,虽然二者并无伯仲之分,但可以从汇编的角度更好的理解C++中的一些细节,同时也可以对C++进行反汇编了解汇编。
笔者在写文章时,开发工具用的是Microsoft Visual Studio 2012,系统类型是64为操作系统。
首先开门见山,看一个很简单的表达式热热身
int a = 1,b = 2;
a = a + b;声明了两个变量a和b,将a和b相加并将结果保存在a中。我们查看它的反汇编代码
int a = 1,b = 2;
008A4C3E mov dword ptr [a],1
008A4C45 mov dword ptr [b],2
a = a + b;
008A4C4C mov eax,dword ptr [a]
008A4C4F add eax,dword ptr [b]
008A4C52 mov dword ptr [a],eax 对于
int a = 1,b = 2;汇编语言的处理是将数值1和2分别存储到内存位置a和b中
a = a + b;在加法操作中用到了eax寄存器,因为在汇编语言中,内存为值不能向内存位置直接赋值,只能通过寄存器这个中间人将数据存储过去。闲话少说,首先,将内存位置a中的值存储到eax寄存器中,之后将内存位置b中的值和eax寄存器中的值相加并将结果存储会eax寄存器,最后将eax寄存器中的值存储到内存位置a中。
不知道大家感觉如何,反正我对于从这种视角看C++感觉挺有意思的。
下面我们看看可能是困扰很多C++初学者的自增问题
int a = 0;
int b = a++;
b = ++a;我们来反汇编它
int a = 0;
00F54C3E mov dword ptr [a],0
int b = a++;
00F54C45 mov eax,dword ptr [a]
00F54C48 mov dword ptr [b],eax
00F54C4B mov ecx,dword ptr [a]
00F54C4E add ecx,1
00F54C51 mov dword ptr [a],ecx
b = ++a;
00F54C54 mov eax,dword ptr [a]
00F54C57 add eax,1
00F54C5A mov dword ptr [a],eax
00F54C5D mov ecx,dword ptr [a]
00F54C60 mov dword ptr [b],ecx 对于声明并初始化a为0的过程不必赘述,首先我们看第一条表达式
int b = a++;我们按照顺序一条一条的读反汇编后的5条指令
第一步,内存地址a的值被存储在寄存器eax中。
第二步,寄存器eax中的值被存储在内存地址为b的位置上。
第三步,将内存地址a的值存储在ecx寄存器中。
第四步,将ecx寄存器中的值加1并且将结果存放回ecx寄存器中。
最后,将ecx寄存器中的值存放回内存地址a的位置上。
从上述过程,大家已经看到了,变量a的值先是赋给b,之后a再自加1。有些读者可能会疑惑为什么第四步不直接把eax寄存器中的值加1而非要将a重新放到ecx中一次,再对ecx加1?这里反汇编主要考虑的是不对寄存器造成内容上的冲突,CPU内部寄存器很多,有查看eax寄存器中的值是不是我刚才存放的,倒不如重新放到新的寄存器中进行计算来的方便。毕竟人家是机器,不能和我们发达的人脑相比。
接下来我们看第二条表达式
b = ++a;同样我们还是一条一条得看,不过这次,我们和第一条表达式的反汇编结果进行找不同
我们看到第一步和最后一步都是一样的,分别是将a放入eax寄存器中和将ecx寄存器中的结果放到b中。
中间的步骤顺序发生了改变,首先,eax寄存器中存储的变量a的值加1并存回eax寄存器中,然后,eax寄存器中的值被存储到内存位置a中,最后,ecx寄存器作为中间的存储a的值。
这条语句,变量a先自加,然后将结果赋值给变量b。前置和后置自增操作符也曾经困扰过刚接触编程的笔者,就和当年学英语分不清楚positive和negative哪一个是积极的一样。
今天先写到这里,如有不足之处请各位多加品评。
3万+

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



