【问题标题】:How to disassemble a compiler generated code?如何反汇编编译器生成的代码?
【发布时间】:2014-05-29 14:23:27
【问题描述】:

我希望以编译器在指令重新调度后生成的相同顺序查看反汇编代码。顺便说一句,我正在使用 GDB,当我给出一个命令说 disas /m FunctionName 时,它会按照源代码的顺序给我反汇编代码。我正在尝试查看我的编译器(GCC 4.1)重新调度指令的有效性,并希望了解如何重新调度指令。 谢谢! ///////////////编辑////////////////////////// ///////// 看了一行代码的反汇编代码后:

double w_n =  (A_n[2] * x[0] + A_n[5] * y + A_n[8] * z + A_n[11])  ;

我可以看到它的 83 字节指令。但在展开 2 次迭代后:

double w_n[2] = { (A_n[2] * x[0] + A_n[5] * y + A_n[8] * z + A_n[11]), (A_n_2[2] * x[0] + A_n_2[5] * y + A_n_2[8] * z + A_n_2[11]) };

代码块为 226 字节。并且指令数量大幅增加。谁能告诉我为什么会这样?我还可以从 VTune 中看到,展开后退出的指令增加了。 我能想到的可能原因:编译器通过增加块大小获得了足够的机会来生成简单指令,从而最大限度地提高指令预取和解码器单元的吞吐量。

非常感谢任何帮助。谢谢!!

【问题讨论】:

标签: c++ debugging gdb computer-architecture intel-vtune


【解决方案1】:

如果编译器已经完成了重新调度,那么在 gdb 中反汇编时您确实应该看到这一点。

否则,您也许可以直接在命令行上使用objdump,这是我在 ELF 中查看代码的首选方式:

$ objdump --disassemble a.out | less

它根本不引用源代码,所以它应该真正显示二进制文件本身的内容。

【讨论】:

    【解决方案2】:

    在将代码编译成目标文件的步骤中,您也可以简单地告诉 GCC 驱动程序 (gcc) 您想要获取汇编代码:

    gcc -S -c file.c
    gcc -O2 -S -c file.c
    gcc -S -masm=intel -c file.c
    

    (后者生成 Intel 而不是 AT&T 语法汇编)

    您甚至可以稍后将该汇编代码扔给汇编器(例如gasm)以获取可以链接的目标文件。


    至于为什么代码更大,有很多原因。我们人类用来手动优化装配的启发式方法已经有一段时间不再适用了。一个大目标是流水线,另一个矢量化。总而言之,它是关于尽可能多地并行化,并且必须在任何给定时间尽可能少地从(已读取)缓存中失效,以加快执行速度。

    尽管这看起来有悖常理,但这可能会导致更大、更快的代码。

    【讨论】:

    • 非常感谢!你是对的。它的代码更大更快。但我只需要一个有效的证据来看看说明为什么会增加。还是一样的 Add, div, mul 操作。是什么让编译器为特定情况生成更多指令?
    • @Tiro_Coder:编译器可以针对一组 CPU 或单个 CPU。优化器的决定取决于什么对目标最有利。因此,如果您告诉编译器您只需要特定类型的 CPU,它将确保代码针对该场景进行了优化。此外,循环可以在配置文件引导优化等期间展开。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 2014-10-29
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    相关资源
    最近更新 更多