我希望看到反汇编代码的顺序与编译器在重新调度指令后生成的顺序相同。 b.t.w我正在使用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看到,展开后退出的指令已经增加。 可能的原因我可以想到:编译器获得了足够的机会,增加了块大小以生成简单的指令,从而最大化指令预取和解码器单元的吞吐量。
非常感谢任何帮助。谢谢!
答案 0 :(得分:4)
如果编译器完成了重新安排,你真的应该在gdb中反汇编时看到。
否则你可以直接在命令行使用objdump
,这是我在ELF中查看代码的首选方式:
$ objdump --disassemble a.out | less
根本没有引用来源,因此它应该真正显示二进制文件中的内容。
答案 1 :(得分:4)
在将代码编译为目标文件的步骤中,您还可以简单地告诉GCC驱动程序(gcc
)您要获取汇编代码:
gcc -S -c file.c
gcc -O2 -S -c file.c
gcc -S -masm=intel -c file.c
(后者生成Intel而不是AT& T语法汇编)
您甚至可以稍后在汇编程序(例如gasm
)处抛出汇编代码,以获取可链接的目标文件。
至于为什么代码更大,有很多原因。我们人类用来手工优化装配的启发式技术已经有一段时间了。一个很大的目标是流水线,另一个矢量化。总而言之,它是关于尽可能多地并行化并且必须在任何给定时间尽可能少地从(已经读取的)高速缓存中无效以便加速执行。
尽管看起来反直觉,但这可能会导致更大,更快的代码。