如何做到这一点呢?
如果我想分析某些东西是如何编译的,我该如何获得发出的程序集代码?
如何做到这一点呢?
如果我想分析某些东西是如何编译的,我该如何获得发出的程序集代码?
当前回答
对gcc(或g++)使用-S选项,可选使用-fverbose-asm,它在默认的-O0下工作得很好,将C名作为注释附加到asm操作数上。它在任何优化级别上的效果都不太好,您通常希望使用它来获得值得一看的asm。
gcc -S helloworld.c
这将在helloworld.c上运行预处理器(cpp),执行初始编译,然后在运行汇编程序之前停止。有关在这种情况下使用的有用编译器选项,请参阅如何从GCC/clang程序集输出中删除“噪声”?(或者在Matt Godbolt的在线编译器资源管理器上看看你的代码,它过滤掉指令和东西,并使用调试信息突出显示匹配源行和asm。)
默认情况下,这将输出文件helloworld.s。输出文件仍然可以通过使用-o选项来设置,包括-o -用于将管道的标准输出写入less。
gcc -S -o my_asm_output.s helloworld.c
当然,这只有在你有原始源代码的情况下才有效。 如果只有生成的对象文件,另一种选择是使用objdump,通过设置——disassemble选项(缩写形式为-d)。
objdump -S --disassemble helloworld > helloworld.dump
-S将源行与正常的反汇编输出交织在一起,因此如果为目标文件启用了调试选项(编译时为-g)并且文件没有被剥离,则此选项工作得最好。
运行文件helloworld将为您提供一些关于使用objdump将获得的详细级别的指示。
其他有用的objdump选项包括-rwC(用于显示符号重定位、禁用长机器代码换行和要求c++名称)。如果你不喜欢x86的AT&T语法,-Mintel。请参阅手册页。
例如objdump -drwC -Mintel -S foo。少一点。 -r对于.o来说非常重要,因为符号引用只有000 000 000 000个占位符,而不是链接的可执行文件。
其他回答
下面是一个使用GCC的C语言解决方案:
gcc -S program.c && gcc program.c -o output
这里的第一部分将程序的程序集输出存储在与程序相同的文件名中,但是通过更改扩展名.s,您可以将其作为任何普通文本文件打开。 这里的第二部分编译您的程序以供实际使用,并为您的程序生成具有指定文件名的可执行文件。
上面使用的program.c是程序的名称,输出是要生成的可执行文件的名称。
我在答案中没有看到这种可能性,可能是因为这个问题来自2008年,但在2018年,你可以使用马特·戈德博尔特的在线网站https://godbolt.org
你也可以在本地克隆git并运行他的项目https://github.com/mattgodbolt/compiler-explorer
对gcc(或g++)使用-S选项,可选使用-fverbose-asm,它在默认的-O0下工作得很好,将C名作为注释附加到asm操作数上。它在任何优化级别上的效果都不太好,您通常希望使用它来获得值得一看的asm。
gcc -S helloworld.c
这将在helloworld.c上运行预处理器(cpp),执行初始编译,然后在运行汇编程序之前停止。有关在这种情况下使用的有用编译器选项,请参阅如何从GCC/clang程序集输出中删除“噪声”?(或者在Matt Godbolt的在线编译器资源管理器上看看你的代码,它过滤掉指令和东西,并使用调试信息突出显示匹配源行和asm。)
默认情况下,这将输出文件helloworld.s。输出文件仍然可以通过使用-o选项来设置,包括-o -用于将管道的标准输出写入less。
gcc -S -o my_asm_output.s helloworld.c
当然,这只有在你有原始源代码的情况下才有效。 如果只有生成的对象文件,另一种选择是使用objdump,通过设置——disassemble选项(缩写形式为-d)。
objdump -S --disassemble helloworld > helloworld.dump
-S将源行与正常的反汇编输出交织在一起,因此如果为目标文件启用了调试选项(编译时为-g)并且文件没有被剥离,则此选项工作得最好。
运行文件helloworld将为您提供一些关于使用objdump将获得的详细级别的指示。
其他有用的objdump选项包括-rwC(用于显示符号重定位、禁用长机器代码换行和要求c++名称)。如果你不喜欢x86的AT&T语法,-Mintel。请参阅手册页。
例如objdump -drwC -Mintel -S foo。少一点。 -r对于.o来说非常重要,因为符号引用只有000 000 000 000个占位符,而不是链接的可执行文件。
最近我想知道a中每个函数的组装,我是这样做的:
gcc main.c // 'main.c' source file
gdb a.exe // 'gdb a.out' in Linux
广东发展银行:
disass main // Note here 'main' is a function
// Similarly, it can be done for other functions.
如果您希望看到的内容依赖于输出的链接,那么除了前面提到的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的输出上。