如何做到这一点呢?

如果我想分析某些东西是如何编译的,我该如何获得发出的程序集代码?


当前回答

使用“-S”作为选项。它在终端中显示程序集输出。

其他回答

我在答案中没有看到这种可能性,可能是因为这个问题来自2008年,但在2018年,你可以使用马特·戈德博尔特的在线网站https://godbolt.org

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

下面是一个使用GCC的C语言解决方案:

gcc -S program.c && gcc program.c -o output

这里的第一部分将程序的程序集输出存储在与程序相同的文件名中,但是通过更改扩展名.s,您可以将其作为任何普通文本文件打开。 这里的第二部分编译您的程序以供实际使用,并为您的程序生成具有指定文件名的可执行文件。

上面使用的program.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的输出上。

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

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

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

'-fdump-tree'标志家族也值得一看,特别是-fdump-tree-all,它可以让您看到GCC的一些中间形式。这些程序通常比汇编程序更具可读性(至少对我来说),并让您了解优化传递的执行情况。