c - 在打开优化的情况下读取汇编代码

标签 c gcc assembly optimization

我尝试比较使用和不使用 -O3 选项的编译器的输出,但我无法理解优化代码的工作原理。

这是 C 代码:

#include <stdio.h>
#include <limits.h>

int main(int argc, char *argv[]) {
    int a = 3;
    int b = argc;

    while (b) {
        ++a;
        --b;
    }

    printf("%d\n", a);

    return 0;
}

这是未经优化的 objdump 输出。看起来很简单:

000000000040052d <main>:
    #include <stdio.h>
    #include <limits.h>

int main(int argc, char *argv[]) {
  40052d:       55                      push   %rbp
  40052e:       48 89 e5                mov    %rsp,%rbp
  400531:       48 83 ec 20             sub    $0x20,%rsp
  400535:       89 7d ec                mov    %edi,-0x14(%rbp)
  400538:       48 89 75 e0             mov    %rsi,-0x20(%rbp)
    int a = 3;
  40053c:       c7 45 f8 03 00 00 00    movl   $0x3,-0x8(%rbp)
    int b = argc;
  400543:       8b 45 ec                mov    -0x14(%rbp),%eax
  400546:       89 45 fc                mov    %eax,-0x4(%rbp)

    while (b) {
  400549:       eb 08                   jmp    400553 <main+0x26>
        ++a;
  40054b:       83 45 f8 01             addl   $0x1,-0x8(%rbp)
        --b;
  40054f:       83 6d fc 01             subl   $0x1,-0x4(%rbp)

int main(int argc, char *argv[]) {
    int a = 3;
    int b = argc;

    while (b) {
  400553:       83 7d fc 00             cmpl   $0x0,-0x4(%rbp)
  400557:       75 f2                   jne    40054b <main+0x1e>
        ++a;
        --b;
    }

    printf("%d\n", a);
  400559:       8b 45 f8                mov    -0x8(%rbp),%eax
  40055c:       89 c6                   mov    %eax,%esi
  40055e:       bf 04 06 40 00          mov    $0x400604,%edi
  400563:       b8 00 00 00 00          mov    $0x0,%eax
  400568:       e8 a3 fe ff ff          callq  400410 <printf@plt>

    return 0;
  40056d:       b8 00 00 00 00          mov    $0x0,%eax
}

但是在向 gcc 添加 -O3 选项后我得到了这个:

0000000000400470 <main>:
#include <stdio.h>
#include <limits.h>

int main(int argc, char *argv[]) {
  400470:       8d 47 03                lea    0x3(%rdi),%eax
  400473:       48 83 ec 08             sub    $0x8,%rsp
  400477:       ba 03 00 00 00          mov    $0x3,%edx
  40047c:       85 ff                   test   %edi,%edi
}

__fortify_function int
printf (const char *__restrict __fmt, ...)
{
  return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());
  40047e:       be 14 06 40 00          mov    $0x400614,%esi
  400483:       bf 01 00 00 00          mov    $0x1,%edi
  400488:       0f 45 d0                cmovne %eax,%edx
  40048b:       31 c0                   xor    %eax,%eax
  40048d:       e8 ce ff ff ff          callq  400460 <__printf_chk@plt>
    }

    printf("%d\n", a);

    return 0;
}
  400492:       31 c0                   xor    %eax,%eax
  400494:       48 83 c4 08             add    $0x8,%rsp
  400498:       c3                      retq

除了使用堆栈进行操作之外,我看不到任何跳转或任何有效的添加、子指令。有人可以向我解释一下吗?

谢谢

最佳答案

您的代码已优化为 printf("%d\n", 3 + argc),因为 gcc 可以弄清楚循环的作用。

3+argc是第一个lea 0x3(%rdi),%eax .


实际上,gcc 并没有完全解决循环问题:

test/cmov 的东西似乎正在做:

int a = 3;
if (argc != 0)
    a = argc + 3;

又名

int a = argc ? 3 + argc : 3;

关于c - 在打开优化的情况下读取汇编代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39023342/

相关文章:

linux - assembly 中的倒车阵列故障

assembly - endbr64 指令实际上做了什么?

c - float 的重复递增

c - OpenMP 循环上的段错误(核心转储)

python - 如何链接 libpython.a 以便运行时链接器可以找到 libpython.a 中的所有符号?

c++ - Clang 与 GCC : Friend-ing a global function via qualified/unqualified names

c++ - "Error in the program"谁能清除这个错误..? (Linux 帧缓冲区程序)

c - 为什么这些 continue 语句在我的循环中不起作用?

gcc - 以非编译器特定的方式更改 Fortran 中的目录

assembly - 8086 汇编中文本用户界面的字符大小错误