Chinaunix首页 | 论坛 | 博客
  • 博客访问: 822821
  • 博文数量: 92
  • 博客积分: 1498
  • 博客等级: 上尉
  • 技术积分: 993
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-18 18:31
文章分类

全部博文(92)

文章存档

2013年(2)

2012年(3)

2011年(3)

2010年(61)

2009年(23)

分类: LINUX

2010-07-23 12:39:41

那天遇到了一个问题,王聪学长建议使用反汇编查看GCC的行为,上网看了看这方面的知识,毕竟自己汇编很菜,
就找到了了这样一篇文章,发现竟然是小组以前的文章,可是小组以前的网站这个域名不能
用了,所以保存下这篇文章,顺便推介下我们西邮linux兴趣小组的最新域名: 。欢迎大
家访问,由于是新建设的网站,瑕疵之处在所难免,所以请大家给出建议,好了,扯远了。。来看我转载的这篇文章吧:
document.body.oncopy = function () { if (window.clipboardData) { setTimeout(function () { var text = clipboardData.getData("text"); if (text && text.length > 300) { text = text + "\r\n\n本文来自CSDN博客,转载请标明出处:" + location.href; clipboardData.setData("text", text); } }, 100); } } function StorePage() { d = document; t = d.selection ? (d.selection.type != 'None' ? d.selection.createRange().text : '') : (d.getSelection ? d.getSelection() : ''); void (keyit = window.open('' + escape(d.title) + '&u=' + escape(d.location.href) + '&c=' + escape(t), 'keyit', 'scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes')); keyit.focus int i = 3;

printf(”%d\n”, i++ * ++i + i– * –i);

在吉林大学的视频c教程中, 上式值为18.她的解法是前缀优先于后缀,所以就是3 * 4 + 3 * 2。在gcc中得到的结果是25。

这种行为是标准未定义的。

可以通过反汇编来查看gcc的行为。如下,我们看看调用printf之前gcc是如何操作i。

80483b5: c7 45 f8 03 00 00 00 movl $0×3,0xfffffff8(%ebp)

给i赋值3。

80483bc: 83 45 f8 01 addl $0×1,0xfffffff8(%ebp)

加1。i==4

80483c0: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
80483c3: 89 c2 mov %eax,%edx
80483c5: 0f af 55 f8 imul 0xfffffff8(%ebp),%edx

计算此时的i*i。 16

80483c9: 83 6d f8 01 subl $0×1,0xfffffff8(%ebp)

把i减1,即i==3。

80483cd: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
80483d0: 0f af 45 f8 imul 0xfffffff8(%ebp),%eax

计算i*i,即9。

80483d4: 8d 04 02 lea (%edx,%eax,1),%eax

把上面两个乘的结果加起来,放入%eax。

80483d7: 83 45 f8 01 addl $0×1,0xfffffff8(%ebp)
80483db: 83 6d f8 01 subl $0×1,0xfffffff8(%ebp)

把i加1,再减1。

80483df: 89 44 24 04 mov %eax,0×4(%esp)

%eax就是最后结果,即25

80483e3: c7 04 24 d0 84 04 08 movl $0×80484d0,(%esp)
80483ea: e8 c9 fe ff ff call 80482b8

另外,如果你把gcc的优化级别调高一些,你会发现结果也是18。
如果你把i类型改成volatile int,结果是24。(3 * 4 + 4 * 3)

这个问题的关键是看编译器怎么处理寄存器和内存之间的关系,已经超出了
标准所规定的范围。实际中这种代码是应该避免的。


阅读(1221) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~