每个C程序员都知道同一个for循环语句可以有两种写法:
A:for(i=0;i
B:for(i=cnt;i>0;i--){}
前几天,DEBUG的时候,发现采用A写法的代码反汇编出来有BUG.当时没有时间记录,环境也没有保存下来.今天尝试重现,又没来出现上次的问题...很奇怪.
很久很久以前也听说过这两种写法有区别,今天就顺便分析一下,也算没有白忙.
编译环境:mipsisa32-xlr-linux-gcc3.4.3
测试代码见附件:raw_socket.c
A反汇编之后的代码如下:
B反汇编之后的代码如下:
对A的分析:
401158:将i清零
40115c:将i的值加载到寄存器v0
401160:将cnt的值加载到寄存器v1
401164:比较v0是否小于v1即i是否小于cnt.如果i
401168:如果v0的值为0即i>cnt,则跳到4011a8地址执行,即跳出for循环
...
4011a0:跳到40115c重新开始for循环
4011a4:把v0即i的值写入内存.由于mips的流水行机制,在上一条语句真正跳转前,这条语句会被执行
对B的分析:
401158:将cnt的值加载到寄存器v0
40115c:将v0的值赋给i,即将cnt的值赋给i
401160:将i的值加载到寄存器v0(这一条有必要么?)
401164:如果v0的值小于等于0,即i<=0,则跳到4011a4处执行,即跳出for循环
...
40119c:跳到401160地址执行,重新开始for循环
4011a0:把v0即i的值写入内存.
通过上面的分析可以看出A要比B多一条语句:A的401160.每次for循环,A都要从内存中多加载一次cnt的值.
内存的读取一般远远小于CPU的执行速度.A的效率应该不如B高.
将同样的代码,在x86上编译,反汇编.
系统:Fedora17x86
编译器:gcc4.7.2
A写法的反汇编结果:
B写法的反汇编结果:
A写法同样多了对cnt内存的读取...