怎么做到这一点?
如果我想分析如何编译某些内容,我将如何获得发出的汇编代码?
使用-S
gcc(或g ++)选项.
gcc -S helloworld.c
这将在helloworld.c上运行预处理器(cpp),执行初始编译,然后在运行汇编程序之前停止.
默认情况下,这将输出一个文件helloworld.s
.仍然可以使用该-o
选项设置输出文件.
gcc -S -o my_asm_output.s helloworld.c
当然,只有拥有原始资源才能使用.如果您只使用生成的目标文件,则可以objdump
通过设置--disassemble
选项(或-d
缩写形式)来使用.
objdump -S --disassemble helloworld > helloworld.dump
如果为目标文件启用了调试选项,则此选项最有效(-g
在编译时)并且文件尚未被剥离,.
运行file helloworld
将为您提供使用objdump获得的详细程度的一些指示.
这将生成asm代码,其中C代码+行号交织在一起,以便更容易地看到哪些行生成了什么代码.
# create assembler code: c++ -S -fverbose-asm -g -O2 test.cc -o test.s # create asm interlaced with source lines: as -alhnd test.s > test.lst
在程序员的算法中找到,第3页(这是PDF的整体第15页).
以下命令行来自Christian Garbin的博客
g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
我在Win-XP的DOS窗口中运行G ++,对着包含隐式转换的例程
c:\gpp_code>g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt horton_ex2_05.cpp: In function `int main()': horton_ex2_05.cpp:92: warning: assignment to `int' from `double'
输出是用原始C++代码分配的生成代码(C++代码在生成的asm流中显示为注释)
16:horton_ex2_05.cpp **** using std::setw; 17:horton_ex2_05.cpp **** 18:horton_ex2_05.cpp **** void disp_Time_Line (void); 19:horton_ex2_05.cpp **** 20:horton_ex2_05.cpp **** int main(void) 21:horton_ex2_05.cpp **** { 164 %ebp 165 subl $128,%esp ?GAS LISTING C:\DOCUME~1\CRAIGM~1\LOCALS~1\Temp\ccx52rCc.s 166 0128 55 call ___main 167 0129 89E5 .stabn 68,0,21,LM2-_main 168 012b 81EC8000 LM2: 168 0000 169 0131 E8000000 LBB2: 169 00 170 .stabn 68,0,25,LM3-_main 171 LM3: 172 movl $0,-16(%ebp)
使用-S开关
g++ -S main.cpp
或者与gcc
gcc -S main.c
也看到这个
如果你想看到的东西取决于输出的链接,那么除了前面提到的gcc -S之外,对输出目标文件/可执行文件的objdump也可能是有用的.这是Loren Merritt的一个非常有用的脚本,它将默认的objdump语法转换为更易读的nasm语法:
#!/usr/bin/perl -w $ptr='(BYTE|WORD|DWORD|QWORD|XMMWORD) PTR '; $reg='(?:[er]?(?:[abcd]x|[sd]i|[sb]p)|[abcd][hl]|r1?[0-589][dwb]?|mm[0-7]|xmm1?[0-9])'; open FH, '-|', '/usr/bin/objdump', '-w', '-M', 'intel', @ARGV or die; $prev = ""; while(){ if(/$ptr/o) { s/$ptr(\[[^\[\]]+\],$reg)/$2/o or s/($reg,)$ptr(\[[^\[\]]+\])/$1$3/o or s/$ptr/lc $1/oe; } if($prev =~ /\t(repz )?ret / and $_ =~ /\tnop |\txchg *ax,ax$/) { # drop this line } else { print $prev; $prev = $_; } } print $prev; close FH;
我怀疑这也可以用在gcc -S的输出上.
好吧,正如大家所说,使用-S选项.如果使用-save-temps选项,还可以获得预处理文件(.i),汇编文件( .s)和目标文件(*.o).(使用-E,-S和-c获取每个.)
正如大家所指出的,使用-S
GCC选项.我还想补充一点,结果可能会有所不同(非常!),具体取决于您是否添加优化选项(-O0
对于没有优化选项-O2
).
特别是在RISC体系结构中,编译器通常会在进行优化时将代码转换为几乎无法识别.看结果令人印象深刻,令人着迷!
如前所述,请查看-S标志.
它还值得查看'-fdump-tree'标志系列,特别是'-fdump-tree-all',它可以让你看到一些gcc的中间形式.这些通常比汇编程序更具可读性(至少对我而言),并让您了解优化通过的执行方式.
如果您正在寻找LLVM组装:
llvm-gcc -emit-llvm -S hello.c
使用-S选项:
gcc -S program.c
我没有在答案中看到这种可能性,可能是因为问题是从2008年开始,但在2018年你可以使用Matt Goldbolt的在线网站https://godbolt.org
你也可以在本地git克隆并运行他的项目https://github.com/mattgodbolt/compiler-explorer