反汇编查看gcc行为

From:http://www.xiyoulinux.cn/blog/?p=82

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 <printf@plt>

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

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

From: Xiyoulinux Google Group

 

你可能感兴趣的:(c,优化,汇编,gcc,Google,编译器)