你如何从 gcc 的 C/C++ 源代码中获得汇编输出?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/137038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:08:15  来源:igfitidea点击:

How do you get assembler output from C/C++ source in gcc?

c++cdebugginggccassembly

提问by Doug T.

How does one do this?

如何做到这一点?

If I want to analyze how something is getting compiled, how would I get the emitted assembly code?

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

回答by Andrew Edgecombe

Use the -Soption to gcc (or g++).

使用-Sgcc(或 g++)选项。

gcc -S helloworld.c

This will run the preprocessor (cpp) over helloworld.c, perform the initial compilation and then stop before the assembler is run.

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

By default this will output a file helloworld.s. The output file can be still be set by using the -ooption.

默认情况下,这将输出一个文件helloworld.s。仍然可以使用该-o选项设置输出文件。

gcc -S -o my_asm_output.s helloworld.c

Of course this only works if you have the original source. An alternative if you only have the resultant object file is to use objdump, by setting the --disassembleoption (or -dfor the abbreviated form).

当然,这仅在您拥有原始来源时才有效。如果您只有结果目标文件,另一种方法是使用objdump, 通过设置--disassemble选项(或-d缩写形式)。

objdump -S --disassemble helloworld > helloworld.dump

This option works best if debugging option is enabled for the object file (-gat compilation time) and the file hasn't been stripped.

如果为目标文件启用了调试选项(-g在编译时)并且文件没有被剥离,则此选项最有效。

Running file helloworldwill give you some indication as to the level of detail that you will get by using objdump.

运行file helloworld将向您提供有关使用 objdump 获得的详细程度的一些指示。

回答by PhirePhly

This will generate assembly code with the C code + line numbers interweaved, to more easily see which lines generate what code:

这将生成 C 代码 + 行号交织的汇编代码,以便更轻松地查看哪些行生成了哪些代码:

# create assembler code:
g++ -S -fverbose-asm -g -O2 test.cc -o test.s
# create asm interlaced with source lines:
as -alhnd test.s > test.lst

Found in Algorithms for programmers, page 3 (which is the overall 15th page of the PDF).

可在Algorithms forPrograms 中找到,第 3 页(这是 PDF 的第 15 页)。

回答by Cr McDonough

The following command line is from Christian Garbin's blog

以下命令行来自Christian Garbin 的博客

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

I ran G++ from a DOS window on Win-XP, against a routine that contains an implicit cast

我从 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'

The output is asssembled generated code iterspersed with the original C++ code (the C++ code is shown as comments in the generated asm stream)

输出是组装生成的代码,散布着原始的 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 8,%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 
g++ -S main.cpp
,-16(%ebp)

回答by Doug T.

Use the -S switch

使用 -S 开关

gcc -S main.c

or also with gcc

或者也用 gcc

#!/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)//o or
        s/($reg,)$ptr(\[[^\[\]]+\])//o or
        s/$ptr/lc /oe;
    }
    if($prev =~ /\t(repz )?ret / and
       $_ =~ /\tnop |\txchg *ax,ax$/) {
       # drop this line
    } else {
       print $prev;
       $prev = $_;
    }
}
print $prev;
close FH;

Also see this

也看到这个

回答by Dark Shikari

If what you want to see depends on the linking of the output, then objdump on the output object file/executable may also be useful in addition to the aforementioned gcc -S. Here's a very useful script by Loren Merritt that converts the default objdump syntax into the more readable nasm syntax:

如果您想查看的内容取决于输出的链接,那么除了前面提到的 gcc -S 之外,输出目标文件/可执行文件上的 objdump 也可能有用。这是 Loren Merritt 的一个非常有用的脚本,它将默认的 objdump 语法转换为更易读的 nasm 语法:

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

I suspect this can also be used on the output of gcc -S.

我怀疑这也可以用于 gcc -S 的输出。

回答by Dan Lenski

As everyone has pointed out, use the -Soption to GCC. I would also like to add that the results may vary (wildly!) depending on whether or not you add optimization options (-O0for none, -O2for agressive optimization).

正如每个人都指出的那样,使用-SGCC 选项。我还想补充一点,根据您是否添加优化选项(-O0对于无,-O2对于激进优化),结果可能会有所不同(非常!)。

On RISC architectures in particular, the compiler will often transform the code almost beyond recognition in doing optimization. It's impressive and fascinating to look at the results!

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

回答by METADATA

Well, as everyone said, use -S option. If you use -save-temps option, you can also get preprocessed file(.i), assembly file(.s) and object file(*.o). (get each of them by using -E, -S, and -c.)

好吧,正如大家所说,使用 -S 选项。如果使用 -save-temps 选项,还可以获得预处理文件 ( .i)、汇编文件 (.s) 和目标文件 (*.o)。(通过使用 -E、-S 和 -c 来获取它们中的每一个。)

回答by mcandre

If you're looking for LLVM assembly:

如果您正在寻找 LLVM 程序集:

##代码##

回答by Antonin GAVREL

I don't see this possibility among answers, probably because the question is from 2008, but in 2018 you can use Matt Goldbolt's online website https://godbolt.org

我在答案中看不到这种可能性,可能是因为问题来自 2008 年,但在 2018 年,您可以使用 Matt Goldbolt 的在线网站https://godbolt.org

You can also locally git clone and run his project https://github.com/mattgodbolt/compiler-explorer

你也可以在本地 git clone 并运行他的项目https://github.com/mattgodbolt/compiler-explorer

回答by Chris Jefferson

As mentioned before, look at the -S flag.

如前所述,查看 -S 标志。

It's also worth looking at the '-fdump-tree' family of flags, in particular '-fdump-tree-all', which lets you see some of gcc's intermediate forms. These can often be more readable than assembler (at least to me), and let you see how optimisation passes perform.

还值得查看“-fdump-tree”系列标志,特别是“-fdump-tree-all”,它可以让您看到一些 gcc 的中间形式。这些通常比汇编程序更具可读性(至少对我而言),并让您了解优化过程的执行情况。