免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2526 | 回复: 4

for循环次数不同,编译器生成的代码就不同,为何? [复制链接]

论坛徽章:
0
发表于 2012-05-24 09:25 |显示全部楼层
10可用积分
本帖最后由 donet8 于 2012-05-24 09:26 编辑

我用VC10写了几行小程序,编译release版

  1. int main(void){
  2.     int i=0;
  3.     for(int c=0;c<11;++c){//循环11次,因为10次以下循环本身会被优化掉。
  4.         i+=c;
  5.     }
  6.     printf("%d\n",i);
  7.     return 0;
  8. }
复制代码
发现for循环反汇编代码是这样的:

  1.     for(int c=0;c<11;++c){
  2. 0040101E  cmp         eax,0Bh  
  3. 00401021  jge         main+25h (401025h)  
  4.         i+=c;
  5. 00401023  mov         esi,eax  
  6. 00401025  add         ecx,edx  
  7. 00401027  add         ecx,esi  
  8.     }
复制代码
然后我修改一下循环的次数从11改成12,发现生成的反汇编代码变复杂了:

  1.     for(int c=0;c<12;++c){
  2. 00401004  xor         eax,eax  
  3. 00401006  xor         esi,esi  
  4. 00401008  xor         edx,edx  
  5. 0040100A  xor         ecx,ecx  
  6. 0040100C  lea         esp,[esp]  
  7.         i+=c;
  8. 00401010  add         edi,eax  
  9. 00401012  lea         ecx,[ecx+eax+1]  
  10. 00401016  lea         edx,[edx+eax+2]  
  11. 0040101A  lea         esi,[esi+eax+3]  
  12. 0040101E  add         eax,4  
  13. 00401021  cmp         eax,0Ch  
  14. 00401024  jl          main+10h (401010h)  
  15.     }
复制代码
现在i+=c这条语句的代码怎么变得这么复杂? 这是什么样的优化技术么?
我发现c=16的时候,代码和c=12是一样的。
并且,c=13的时候,代码和c=11是一样的。

而c=15的时候,生成的代码又是另一种:

  1.     for(int c=0;c<15;++c){
  2. 00401003  xor         eax,eax  
  3. 00401005  xor         edx,edx  
  4. 00401007  xor         ecx,ecx  
  5. 00401009  lea         esp,[esp]  
  6.         i+=c;
  7. 00401010  add         esi,eax  
  8. 00401012  lea         ecx,[ecx+eax+1]  
  9. 00401016  lea         edx,[edx+eax+2]  
  10. 0040101A  add         eax,3  
  11. 0040101D  cmp         eax,0Fh  
  12. 00401020  jl          main+10h (401010h)  
  13.     }
复制代码
这到底是怎么一回事? 我猜想是编译器的某种优化技术,但是不知道具体是什么技术。
各位高人能解释一下么?

最佳答案

查看完整内容

我也没仔细看汇编,不过:0040101E add eax,4 00401021 cmp eax,0Ch 0Ch不就是12么,每次加4,循环3次在循环次数15的时候:0040101A add eax,3 0040101D cmp eax,0Fh0Fh不就是15么,每次加3,循环5次

论坛徽章:
323
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
发表于 2012-05-24 09:25 |显示全部楼层
donet8 发表于 2012-05-24 11:20
我怎么觉得不对呢?
每次加4的话,是不是应该add ecx,4; 技术寄存器应该是ecx不是eax啊。


我也没仔细看汇编,不过:

0040101E  add         eax,4  
00401021  cmp         eax,0Ch  

0Ch不就是12么,每次加4,循环3次

在循环次数15的时候:

0040101A  add         eax,3  
0040101D  cmp         eax,0Fh

0Fh不就是15么,每次加3,循环5次

论坛徽章:
323
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
发表于 2012-05-24 09:29 |显示全部楼层
次数能被4整除时,似乎循环展开了,每次加4,减少循环次数

论坛徽章:
0
发表于 2012-05-24 11:20 |显示全部楼层
hellioncu 发表于 2012-05-24 09:29
次数能被4整除时,似乎循环展开了,每次加4,减少循环次数


我怎么觉得不对呢?
每次加4的话,是不是应该add ecx,4; 技术寄存器应该是ecx不是eax啊。

再者,每次计算完了以后,计算的中间结果保存在几个不同的寄存器中,可是谁这些寄存器的内容如何影响了最终的计算结果呢? 我没看出来这几个寄存器中的值被用到了。

谢谢!

论坛徽章:
0
发表于 2012-05-24 11:52 |显示全部楼层
gcc -O2直接编译出循环的结果:
mov    $0x37,%edx
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP