GCC的优化选项,可以加速我们的程序,使程序执行效率更高。但是,倘若我们就是需要程序慢一点运行,但是优化却把我们的延时函数优化的没有了的时候,这种优化却不是我们想要的。有时候,我们需要事物差的一面。下边的代码是我的 main.c 程序。

  1. #include <stdio.h>
  2. void wait(unsigned long dly)
  3. {
  4. for(; dly> 0; dly--);
  5. }
  6. int main(void)
  7. {
  8. while(1){
  9. printf("hello!\n");
  10. wait(30000);
  11. }
  12. return 0;
  13. }

一、使用默认选项编译

1、编译

  1. gcc main.c -o main

2、查看汇编文件

生成反汇编代码:

  1. objdump -s -d main > main.txt

查看反汇编代码:

  1. 0000000000001149 <wait>:
  2. 1149: f3 0f 1e fa endbr64
  3. 114d: 55 push %rbp
  4. 114e: 48 89 e5 mov %rsp,%rbp
  5. 1151: 48 89 7d e8 mov %rdi,-0x18(%rbp)
  6. 1155: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
  7. 115c: eb 04 jmp 1162 <wait+0x19>
  8. 115e: 83 45 fc 01 addl $0x1,-0x4(%rbp)
  9. 1162: 48 83 7d e8 00 cmpq $0x0,-0x18(%rbp)
  10. 1167: 75 f5 jne 115e <wait+0x15>
  11. 1169: 48 83 6d e8 01 subq $0x1,-0x18(%rbp)
  12. 116e: 90 nop
  13. 116f: 5d pop %rbp
  14. 1170: c3 ret
  15. 0000000000001171 <main>:
  16. 1171: f3 0f 1e fa endbr64
  17. 1175: 55 push %rbp
  18. 1176: 48 89 e5 mov %rsp,%rbp
  19. 1179: 48 8d 05 84 0e 00 00 lea 0xe84(%rip),%rax # 2004 <_IO_stdin_used+0x4>
  20. 1180: 48 89 c7 mov %rax,%rdi
  21. 1183: e8 c8 fe ff ff call 1050 <puts@plt>
  22. 1188: bf 30 75 00 00 mov $0x7530,%edi
  23. 118d: e8 b7 ff ff ff call 1149 <wait>
  24. 1192: eb e5 jmp 1179 <main+0x8>

二、添加优化

现在,添加上选项(-O2),再来看一下汇编代码。

1、编译

  1. gcc -O2 main.c -o main

2、查看汇编代码

生成反汇编代码:

  1. objdump -s -d main > main.txt

查看汇编代码:

  1. ...
  2. 0000000000001060 <main>:
  3. 1060: f3 0f 1e fa endbr64
  4. 1064: 53 push %rbx
  5. 1065: 48 8d 1d 98 0f 00 00 lea 0xf98(%rip),%rbx # 2004 <_IO_stdin_used+0x4>
  6. 106c: 0f 1f 40 00 nopl 0x0(%rax)
  7. 1070: 48 89 df mov %rbx,%rdi
  8. 1073: e8 d8 ff ff ff call 1050 <puts@plt>
  9. 1078: eb f6 jmp 1070 <main+0x10>
  10. 107a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
  11. ...
  12. 0000000000001170 <wait>:
  13. 1170: f3 0f 1e fa endbr64
  14. 1174: c3 ret

可以看到,我们的延时函数完全被优化的没有了,那么我们的延时函数还有什么用。

三、问题分析

wait函数中的等待是一个空操作

  1. void wait(unsigned long dly)
  2. {
  3. while(dly)
  4. dly--;
  5. }
  6. void wait(unsigned long dly)
  7. {
  8. for(int i= dly; i > 0; i--);
  9. dly--;
  10. }

都会被优化掉。

加上关键字volatile就可以告诉编译器,不用优化,而是在内存中读取dly的值

  1. void wait(unsigned long dly)
  2. {
  3. while(volatile dly)
  4. dly--;
  5. }

参考资料