2008-09-26 129 views
274

如何做到这一点?如何从gcc的C/C++源代码获得汇编程序输出?

如果我想分析一些东西是如何编译的,我将如何获得发出的汇编代码?

+6

有关**使asm输出可读**的提示,另请参阅:[如何从GCC/clang程序集输出中删除“noise”](http://stackoverflow.com/questions/38552116/how-从gcc-clang-assembly-output中删除噪音) – 2016-07-26 04:30:06

回答

308

使用gcc(或g ++)的-S选项。

gcc -S helloworld.c 

这将运行在helloworld.c预处理器(CPP),执行初始编译,然后运行汇编器之前停止。

默认情况下,这将输出文件helloworld.s。输出文件仍可通过使用-o选项进行设置。

gcc -S -o my_asm_output.s helloworld.c 

当然,这只有在您有原始来源时才有效。 如果只有生成的目标文件,则通过设置--disassemble选项(或-d的缩写形式),使用objdump

objdump -S --disassemble helloworld > helloworld.dump 

如果调试选项是目标文件(-g在编译时)启用,该文件并没有被剥夺,此选项效果最佳。

运行file helloworld会给你一些关于你将通过使用objdump获得的详细程度的指示。

+3

虽然这是正确的,但我发现Cr McDonough的答案更有用。 – 2013-11-03 02:13:02

+3

另外一个用途:objdump -M intel -S --disassemble helloworld> helloworld.dump以intel语法获得对象转储,与linux上的nasm兼容。 – touchStone 2015-03-11 11:58:33

19

使用-s开关

g++ -S main.cpp 

,或者也用gcc

gcc -S main.c 

另见this

+6

查看常见问题解答:“问问题并回答你自己的编程问题也很好”。问题是现在,StackOverflow将Q&A作为其他资源的资源。 – 2008-09-26 00:50:10

+0

也许别人会走过来,给你一个更好的答案给你一个惊喜,虽然我的时间可能有点冗长...... – PhirePhly 2008-09-26 03:01:34

+0

甚至有答案是你自己的问题按钮。 – 2013-08-24 20:05:28

4

使用-s选项:

gcc -S program.c 
13

如果你想看取决于输出的链接,那么除了前面提到的gcc -S之外,输出对象文件/可执行文件上的objdump也可能是有用的。这里是由罗兰梅里特一个非常有用的脚本,默认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的输出使用。

+1

不过,这个脚本是一个肮脏的黑客,它不完全转换语法。例如。 `mov eax,ds:0x804b794`不是很NASMish。另外,它有时只是去除有用的信息:`movzx eax,[edx + 0x1]`让读者猜测内存操作数是'byte'还是'word'。 – Ruslan 2017-10-07 22:00:01

+0

要首先在NASM语法中进行反汇编,请使用[Agner Fog's`objconv`](http://agner.org/optimize/#objconv)。你可以通过输出file =`/ dev/stdout`将它反汇编到标准输出中,这样你就可以输入`less`来查看。还有`ndisasm`,但它只是分解平面二进制文件,并不知道目标文件(ELF/PE)。 – 2017-10-07 22:12:51

7

大家都指出,使用GCC的-S选项。我还想补充一点,根据是否添加优化选项(none为-O0,积极优化为-O2),结果可能会有所不同(疯狂!)。

特别是在RISC体系结构中,编译器经常会在进行优化时将代码转换成几乎无法识别的地方。看看结果令人印象深刻,令人着迷!

143

这将生成带有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 

Algorithms for programmers发现,第4页。

6

正如前面提到的,看看-S标志。

也值得一看'-fdump-tree'系列的标志,尤其是'-fdump-tree-all',它可以让你看到一些gcc的中间形式。这些通常比汇编更具可读性(至少对我来说),并让您看到优化传递是如何执行的。

1

使用“-S”作为选项。它显示终端中的组件输出。

6

如果您正在寻找LLVM汇编:

llvm-gcc -emit-llvm -S hello.c 
7

好了,大家都表示,使用-s选项。 如果使用-save-temps选项,还可以获取预处理文件(.i),程序集文件(。)和目标文件(* .o)。 (通过使用-E,-S和-C得到它们。)

38

下面的命令行是从Christian Garbin's blog

g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt 

我跑G ++从在Win-XP DOS窗口,针对包含隐式转换

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' 

输出asssembled生成的代码iterspersed与原来的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) 
0

Output of these commnads

下面是看/打印任何C程序的汇编代码上的Windows

控制台/终端/命令提示的步骤:

  1. 写类似的代码块一个C代码编辑器,一个C程序,并用一种​​推广保存它的.c

  2. 编译并运行它。

  3. 一旦成功运行,进入文件夹,您安装GCC编译器和给

    下面的命令来获得“.C”文件

    ℃的“.S”文件: \ GCC> GCC -S C文件的完整路径ENTER

    一个实例命令(如在我的情况)

    C:\ GCC> GCC -SD:\ Aa_C_Certified \ alternate_letters.c

    此输出原始 '.C' 的 '.S' 文件文件

4。在此之后,输入以下命令

℃; \ GCC> CPP filename.s ENTER

示例命令(如在我的情况)

℃; \ GCC> CPP alternate_letters.s

这将打印/输出C程序的整个汇编语言代码。

相关问题