如何从gcc的C / C ++源代码获得汇编输出?
如何做到这一点?
如果我想分析一下如何编译,我将如何获得发出的汇编代码?
使用-S
选项gcc(或g ++)。
gcc -S helloworld.c
这将通过helloworld.c运行预处理器(cpp),执行初始编译,然后在汇编器运行之前停止。
默认情况下,这将输出一个文件helloworld.s
。 输出文件仍然可以通过使用-o
选项来设置。
gcc -S -o my_asm_output.s helloworld.c
当然,这只有当你有原始来源时才有效。 如果只有生成的目标文件,则另一种方法是使用objdump
,方法是设置--disassemble
选项(或简写forms的-d
)。
objdump -S --disassemble helloworld > helloworld.dump
如果对目标文件启用了debugging选项(编译时为-g
)并且文件没有被剥离,则此选项效果最佳。
正在运行的file helloworld
会给你一些关于你将通过使用objdump获得的详细程度的指示。
这将生成与交错的C代码+行号的asm,更容易地看到哪些行生成什么代码。
# 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
在程序员的algorithm中find,第4页。
以下命令行来自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 ++代码在生成的asmstream中显示为注释)
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(<FH>){ 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
选项来GCC。 我还想补充一点,根据是否添加优化选项,结果可能会有所不同( -O0
为none, -O2
为积极优化)。
特别是在RISC体系结构中,编译器经常会将代码转换成几乎无法识别的优化代码。 看结果令人印象深刻,令人着迷!
如前所述,看看-S标志。
同样值得一看的是“-fdump-tree”系列标志,尤其是“-fdump-tree-all”,它可以让你看到一些gcc的中间forms。 这些通常比汇编更具可读性(至less对我来说),并且让你看看如何执行优化。
如果您正在寻找LLVM组件:
llvm-gcc -emit-llvm -S hello.c
那么,正如大家所说,使用-S选项。 如果使用-save-temps选项,还可以获取预处理文件( .i),程序集文件( .s)和目标文件(* .o)。 (通过使用-E,-S和-c来获得它们中的每一个)
使用-S选项:
gcc -S program.c
来自: http : //www.delorie.com/djgpp/v2faq/faq8_20.html
gcc -c -g -Wa,-a,-ad [其他GCC选项] foo.c> foo.lst
替代PhirePhly的答案或者只是使用-S如大家所说。
使用“-S”作为选项。 它显示terminal中的组件输出。