VC++中使用Disassembly查看代码

VC++中使用Disassembly查看代码

      最近在恶补C/C++的基础知识。一直以来,遇到一些与编译器相关的小程序时,我往往都迷惑不解,每每思索都不得要领。最近一个同学告诉我用反汇编来查看编译的代码,什么都会变得清楚明朗。

 

从一个例子引起的问题:

 

 

int k = 1;

printf("%d/n",(++k)+(++k));

   这个例子是我一个朋友发给我的,他告诉我他一直都想不通为什么在VC6.0下面会输出6。我接过例子的时候也以为结果是5,至少我在GNU Gcc下面编译运行是5。可是VC6.0下面输出却是6。

   这回,我编译后用debug调试,打开disassembly查看汇编代码。的确,一看汇编后,什么事情都变得明朗。

 

25: int k = 1;

0040D799 mov dword ptr [ebp-10h],1

26:

27: printf("%d/n",(++k)+(++k));

0040D7A0 mov edx,dword ptr [ebp-10h]

0040D7A3 add edx,1

0040D7A6 mov dword ptr [ebp-10h],edx

0040D7A9 mov eax,dword ptr [ebp-10h]

0040D7AC add eax,1

0040D7AF mov dword ptr [ebp-10h],eax

0040D7B2 mov ecx,dword ptr [ebp-10h]

0040D7B5 add ecx,dword ptr [ebp-10h]

0040D7B8 push ecx

0040D7B9 push offset string "%d/n" (00422f9c)

0040D7BE call printf (0040d6e0)

    ebp是运行时堆栈的栈低指针。ebp-10h地址上存放了k的值([ebp-10h]表示ebp-10h地址上的内容),运行int k = 1;后,[ebp-10h]的值是1。

    接着运行printf("%d/n",(++k)+(++k));语句。printf()实际上是库函数,在调用printf()函数前,需要先计算(++k)+(++k)的值,然后把该值压到栈顶,以传送给printf()的形参。

    关键还是(++k)+(++k)的计算问题。

    C语言中只有四个运算存在规定的求值顺序:&&、||、?:和,(注意:此处的,是逗号操作符,并非函数参数列表的分隔符,)。

   由于()的优先级作用,会先计算++k,但是并没有规定两边(++k)的求值顺序。所以,有可能是左边的++k先求值,也有可能是+右边的++k先求值。但无论如何,两次的++k之后,k的值是3 。然而,为何计算结果为什么不是2 + 3 或者是 3 + 2 呢?这似乎与求值顺序无关。

   但是,编译器似乎没有预计得到,计算其中一边的表达式算影响到另一边的表达式的结果。所以,编译器认为两边的++k是相等的。

   mov edx,dword ptr [ebp-10h] //把k的值放到edx寄存器中

   add edx,1  //计算++k

   mov dword ptr [ebp-10h],edx   //再把++k的结果放回ebp-10h地址中,此时k=2

   mov eax,dword ptr [ebp-10h]  //把k值复制到eax寄存器中

   add eax,1  //计算++k

   mov dword ptr [ebp-10h],eax  //再把++k的结果放回ebp-10h地址中,此时k=3

   mov ecx,dword ptr [ebp-10h]  //把k值复制到ecx中

   add ecx,dword ptr [ebp-10h]  //计算k+k的值

   push ecx //将k+k的值压栈,以传送给printf的形参

   听说,这个现象叫做存储器别名使用(memory aliasing)。反正,不要这么用就可以避免了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值