注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

点点滴滴

感悟人生,享受精彩。

 
 
 

日志

 
 

VC++中使用Disassembly查看代码  

2010-01-11 12:43:39|  分类: c/c++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

最近在恶补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)。反正,不要这么用就可以避免了。

  评论这张
 
阅读(1524)| 评论(1)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017