如何做到这一点呢?
如果我想分析某些东西是如何编译的,我该如何获得发出的程序集代码?
如何做到这一点呢?
如果我想分析某些东西是如何编译的,我该如何获得发出的程序集代码?
当前回答
以下命令行来自Christian Garbin的博客:
g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
我从Windows XP上的DOS窗口运行g++,针对的是一个包含隐式强制转换的例程
cd 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++代码在生成的汇编语言流中显示为注释)。
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标志。
'-fdump-tree'标志家族也值得一看,特别是-fdump-tree-all,它可以让您看到GCC的一些中间形式。这些程序通常比汇编程序更具可读性(至少对我来说),并让您了解优化传递的执行情况。
我在答案中没有看到这种可能性,可能是因为这个问题来自2008年,但在2018年,你可以使用马特·戈德博尔特的在线网站https://godbolt.org
你也可以在本地克隆git并运行他的项目https://github.com/mattgodbolt/compiler-explorer
这将生成C代码+行号交织的汇编代码,以便更容易地查看哪些行生成了什么代码(-S -fverbose-asm -g -O2):
# 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
在第3页(PDF的第15页)中找到了它。
以下命令行来自Christian Garbin的博客:
g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
我从Windows XP上的DOS窗口运行g++,针对的是一个包含隐式强制转换的例程
cd 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++代码在生成的汇编语言流中显示为注释)。
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)
对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个占位符,而不是链接的可执行文件。