And*_*mbe 389
使用-S
gcc(或g ++)选项.
gcc -S helloworld.c
Run Code Online (Sandbox Code Playgroud)
这将在helloworld.c上运行预处理器(cpp),执行初始编译,然后在运行汇编程序之前停止.
默认情况下,这将输出一个文件helloworld.s
.仍然可以使用该-o
选项设置输出文件.
gcc -S -o my_asm_output.s helloworld.c
Run Code Online (Sandbox Code Playgroud)
当然,只有拥有原始资源才能使用.如果您只使用生成的目标文件,则可以objdump
通过设置--disassemble
选项(或-d
缩写形式)来使用.
objdump -S --disassemble helloworld > helloworld.dump
Run Code Online (Sandbox Code Playgroud)
如果为目标文件启用了调试选项,则此选项最有效(-g
在编译时)并且文件尚未被剥离,.
运行file helloworld
将为您提供使用objdump获得的详细程度的一些指示.
Phi*_*hly 165
这将生成asm代码,其中C代码+行号交织在一起,以便更容易地看到哪些行生成了什么代码.
# 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
Run Code Online (Sandbox Code Playgroud)
在程序员的算法中找到,第3页(这是PDF的整体第15页).
小智 47
以下命令行来自Christian Garbin的博客
g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
Run Code Online (Sandbox Code Playgroud)
我在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'
Run Code Online (Sandbox Code Playgroud)
输出是用原始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)
Run Code Online (Sandbox Code Playgroud)
Dou*_* T. 24
使用-S开关
g++ -S main.cpp
Run Code Online (Sandbox Code Playgroud)
或者与gcc
gcc -S main.c
Run Code Online (Sandbox Code Playgroud)
也看到这个
Cir*_*四事件 15
-save-temps
这是在/sf/answers/1195810661/中提到的,但让我进一步举例说明。
这个选项的一大优点-S
是可以很容易地将它添加到任何构建脚本中,而不会对构建本身造成太多干扰。
当你这样做时:
gcc -save-temps -c -o main.o main.c
Run Code Online (Sandbox Code Playgroud)
主文件
#define INC 1
int myfunc(int i) {
return i + INC;
}
Run Code Online (Sandbox Code Playgroud)
现在,除了正常输出之外main.o
,当前工作目录还包含以下文件:
main.i
是一个奖励,包含预先处理的文件:
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "main.c"
int myfunc(int i) {
return i + 1;
}
Run Code Online (Sandbox Code Playgroud)
main.s
包含所需的生成程序集:
.file "main.c"
.text
.globl myfunc
.type myfunc, @function
myfunc:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
addl $1, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size myfunc, .-myfunc
.ident "GCC: (Ubuntu 8.3.0-6ubuntu1) 8.3.0"
.section .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)
如果要对大量文件执行此操作,请考虑改用:
-save-temps=obj
Run Code Online (Sandbox Code Playgroud)
它将中间文件保存到与-o
对象输出相同的目录而不是当前工作目录,从而避免潜在的基名冲突。
这个选项的另一个很酷的事情是如果你添加-v
:
gcc -save-temps -c -o main.o -v main.c
Run Code Online (Sandbox Code Playgroud)
它实际上显示了正在使用的显式文件而不是丑陋的临时文件/tmp
,因此很容易确切地知道发生了什么,其中包括预处理/编译/组装步骤:
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu main.c -mtune=generic -march=x86-64 -fpch-preprocess -fstack-protector-strong -Wformat -Wformat-security -o main.i
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -fpreprocessed main.i -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase-strip main.o -version -fstack-protector-strong -Wformat -Wformat-security -o main.s
as -v --64 -o main.o main.s
Run Code Online (Sandbox Code Playgroud)
在 Ubuntu 19.04 amd64、GCC 8.3.0 中测试。
CMake 预定义目标
CMake 自动为预处理文件提供一个目标:
make help
Run Code Online (Sandbox Code Playgroud)
向我们展示了我们可以做到:
make main.s
Run Code Online (Sandbox Code Playgroud)
该目标运行:
Compiling C source to assembly CMakeFiles/main.dir/main.c.s
/usr/bin/cc -S /home/ciro/hello/main.c -o CMakeFiles/main.dir/main.c.s
Run Code Online (Sandbox Code Playgroud)
所以文件可以在 CMakeFiles/main.dir/main.c.s
在 cmake 3.16.1 上测试。
Dar*_*ari 12
如果你想看到的东西取决于输出的链接,那么除了前面提到的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;
Run Code Online (Sandbox Code Playgroud)
我怀疑这也可以用在gcc -S的输出上.
小智 8
这是使用 GCC 的 C 解决方案:
gcc -S program.c && gcc program.c -o output
Run Code Online (Sandbox Code Playgroud)
这里,第一部分将程序的汇编输出存储在与程序相同的文件名中,但使用更改后的.s扩展名,您可以将其作为任何普通文本文件打开。
这里的第二部分编译您的程序以供实际使用,并为您的程序生成具有指定文件名的可执行文件。
上面使用的program.c是您的程序的名称,输出是您要生成的可执行文件的名称。
正如大家所指出的,使用-S
GCC选项.我还想补充一点,结果可能会有所不同(非常!),具体取决于您是否添加优化选项(-O0
对于没有优化选项-O2
).
特别是在RISC体系结构中,编译器通常会在进行优化时将代码转换为几乎无法识别.看结果令人印象深刻,令人着迷!
如前所述,请查看-S标志.
它还值得查看'-fdump-tree'标志系列,特别是'-fdump-tree-all',它可以让你看到一些gcc的中间形式.这些通常比汇编程序更具可读性(至少对我而言),并让您了解优化通过的执行方式.
小智 6
来自:http : //www.delorie.com/djgpp/v2faq/faq8_20.html
gcc -c -g -Wa,-a,-ad [其他 GCC 选项] foo.c > foo.lst
替代 PhirePhly 的答案或者像大家说的那样使用 -S 。
我没有在答案中看到这种可能性,可能是因为问题是从2008年开始,但在2018年你可以使用Matt Goldbolt的在线网站https://godbolt.org
你也可以在本地git克隆并运行他的项目https://github.com/mattgodbolt/compiler-explorer
归档时间: |
|
查看次数: |
309130 次 |
最近记录: |