百科问答小站 logo
百科问答小站 font logo



C语言中, for 和 while 在汇编上有什么区别? 第1页

  

user avatar   zhu-wang-xiao-miao-o 网友的相关建议: 
      

看到有朋友提到《深入理解计算机系统结构》这本书了,我这边贴上一些学习资源供大家参考,和本题相关的内容在书中第三章,可以直接精准查阅。因为我只是按照前人的方法来自己去手动验证了一下生成汇编代码的结果,并没有谈及理论内容,所以我想提问者可能需要更系统和理论的支撑。

然后的话,我在回答最后把书中涉及到for和while的部分截图放上来了,不想下载的也可以直接看我的回答最后的附录。

1.英文版原书和配套资料(Computer Systems: A Programmer's Perspective(3rd))

2.中文版《深入理解计算机系统结构》(提取码wrzg)

关于本问题,我在Linux上做了一个测试程序:

首先写了下面的C代码文件test.c:

       #include <stdio.h>    int main() {          int i;          int j;          int sum = 0;            for (i = 0; i < 10; ++i) {                  sum += i;          }            j = 0;          while (j < 10) {                  sum += j;                  ++j;          }            return 0;  }       

接着编译一下:

gcc -o test test.c

然后使用objdump -d作为反汇编器得到汇编代码

objdump -d test> test.txt

打开test.txt看一下

       0000000000400474 <main>:    400474:   55                      push   %rbp    400475:   48 89 e5                mov    %rsp,%rbp    400478:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)    40047f:   c7 45 f4 00 00 00 00    movl   $0x0,-0xc(%rbp)    400486:   eb 0a                   jmp    400492 <main+0x1e>    400488:   8b 45 f4                mov    -0xc(%rbp),%eax    40048b:   01 45 fc                add    %eax,-0x4(%rbp)    40048e:   83 45 f4 01             addl   $0x1,-0xc(%rbp)    400492:   83 7d f4 09             cmpl   $0x9,-0xc(%rbp)    400496:   7e f0                   jle    400488 <main+0x14>    400498:   c7 45 f8 00 00 00 00    movl   $0x0,-0x8(%rbp)    40049f:   eb 0a                   jmp    4004ab <main+0x37>    4004a1:   8b 45 f8                mov    -0x8(%rbp),%eax    4004a4:   01 45 fc                add    %eax,-0x4(%rbp)    4004a7:   83 45 f8 01             addl   $0x1,-0x8(%rbp)    4004ab:   83 7d f8 09             cmpl   $0x9,-0x8(%rbp)    4004af:   7e f0                   jle    4004a1 <main+0x2d>    4004b1:   b8 00 00 00 00          mov    $0x0,%eax    4004b6:   c9                      leaveq     4004b7:   c3                      retq       4004b8:   90                      nop    4004b9:   90                      nop    4004ba:   90                      nop    4004bb:   90                      nop    4004bc:   90                      nop    4004bd:   90                      nop    4004be:   90                      nop    4004bf:   90                      nop      

可以看到

for循环的汇编代码如下:

       ...    40047f:   c7 45 f4 00 00 00 00    movl   $0x0,-0xc(%rbp)    400486:   eb 0a                   jmp    400492 <main+0x1e>    400488:   8b 45 f4                mov    -0xc(%rbp),%eax    40048b:   01 45 fc                add    %eax,-0x4(%rbp)    40048e:   83 45 f4 01             addl   $0x1,-0xc(%rbp)    400492:   83 7d f4 09             cmpl   $0x9,-0xc(%rbp)    400496:   7e f0                   jle    400488 <main+0x14>  ...      

while循环的汇编代码如下:

       ...    400498:   c7 45 f8 00 00 00 00    movl   $0x0,-0x8(%rbp)    40049f:   eb 0a                   jmp    4004ab <main+0x37>    4004a1:   8b 45 f8                mov    -0x8(%rbp),%eax    4004a4:   01 45 fc                add    %eax,-0x4(%rbp)    4004a7:   83 45 f8 01             addl   $0x1,-0x8(%rbp)    4004ab:   83 7d f8 09             cmpl   $0x9,-0x8(%rbp)    4004af:   7e f0                   jle    4004a1 <main+0x2d>  ...      

如你所见,这两个循环在程序集代码中遵循相同的结构,且操作数也都是相同的。

因此,对于在Linux上用GCC编译的C语言基本计数循环的默认优化来讲,while循环和for循环具有相同的性能。

当然,以上测试代码是比较简单的,在某些特殊情况下(例如动态条件等)可能某种循环结构的性能更好,或者因为编译器优化的方式不同而导致了不同的性能,这个还是需要具体问题来具体分析的。

按照书中的理论来说,GCC为for循环产生的优化可能是while循环优化的其中一种,这要取决于优化等级,我的理解是,这可能导致某些时候while和for循环的汇编码不相同,因为两者可能恰好采取不同的优化方式。

附《深入理解计算机系统》相关摘录:

以上,谢谢。




  

相关话题

  C语言中按%d打印char会不会把相邻内存的也print出来? 
  不小心敲了 rm -rf / 后反应是怎样的? 
  全栈工程师为什么会招黑? 
  程序员兄弟们生涯中写过最大的bug是什么? 
  计算机专业学什么语言好找工作? 
  大一被调剂到计算机,但对电脑根本不了解,就只会上上网聊聊天,连入门都算不上,现在应该怎样入门? 
  为什么对编程或软件工程感兴趣的女性极少呢? 
  如果一个程序员工作5年后还没成为大牛,是不是该考虑别的路子了? 
  有哪些IT人才懂的梗? 
  如何评价单片机大神郭天祥? 

前一个讨论
有哪些值得你推荐的百科全书?
下一个讨论
如何评价南开大学程明明老师的 DOCX 倡议(开放共享科研记录行动倡议)?





© 2024-05-20 - tinynew.org. All Rights Reserved.
© 2024-05-20 - tinynew.org. 保留所有权利