GCC -S 选项 (生成汇编文件)
编译器的核心任务是把 C 程序翻译成机器的汇编语言 (assembly language)。汇编语言是人类可以阅读的编程语言,也是相当接近实际机器码的语言。由此导致每种 CPU 架构都有不同的汇编语言。
GCC 是一个适合多种 CPU 架构的编译器,不会把 C 程序语句直接翻译成目标机器的汇编语言,而是在输入语言和输出汇编语言之间,利用一个中间语言,称为 Register Transfer Language (RTL,寄存器传输语言)。借助于这个抽象层,在任何背景下,编译器可以选择最经济的方式对给定的操作编码。
在交互文件中针对目标机器的抽象描述,为编译器重新定向到新架构提供了一个结构化的方式。从 GCC 用户角度来看,我们可以忽略这个中间步骤。
通常情况下,GCC 把汇编语言输出存储到临时文件中,并且在汇编器执行完后立刻删除它们。但是可以使用 -S
选项,让编译程序在生成汇编语言输出之后立刻停止。
如果没有指定输出文件名,那么采用 -S
选项的 GCC 编译过程会为每个被编译的输入文件生成以 .s
作为后缀的汇编语言文件。
$ gcc -S function_printf.c
$ gcc -S hello_world.c
strong@foreverstrong:~/ForeverStrong/hello_world$ gcc -S hello_world.c
hello_world.c: In function ‘main’:
hello_world.c:15:5: warning: implicit declaration of function ‘function_printf’ [-Wimplicit-function-declaration]
function_printf();
^
strong@foreverstrong:~/ForeverStrong/hello_world$
strong@foreverstrong:~/ForeverStrong/hello_world$
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 20
drwxrwxr-x 2 strong strong 4096 Sep 4 21:32 ./
drwxrwxr-x 6 strong strong 4096 Sep 4 20:16 ../
-rw-rw-r-- 1 strong strong 452 Sep 4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong 503 Sep 4 20:18 hello_world.c
-rw-rw-r-- 1 strong strong 504 Sep 4 21:32 hello_world.s
strong@foreverstrong:~/ForeverStrong/hello_world$
strong@foreverstrong:~/ForeverStrong/hello_world$ gcc -S function_printf.c
strong@foreverstrong:~/ForeverStrong/hello_world$
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 24
drwxrwxr-x 2 strong strong 4096 Sep 4 21:32 ./
drwxrwxr-x 6 strong strong 4096 Sep 4 20:16 ../
-rw-rw-r-- 1 strong strong 452 Sep 4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong 517 Sep 4 21:32 function_printf.s
-rw-rw-r-- 1 strong strong 503 Sep 4 20:18 hello_world.c
-rw-rw-r-- 1 strong strong 504 Sep 4 21:32 hello_world.s
strong@foreverstrong:~/ForeverStrong/hello_world$
编译器预处理 *.c
,将其翻译成汇编语言,并将结果存储在 *.s
文件中。
如果想把 C 语言变量的名称作为汇编语言语句中的注释,可以加上 -fverbose-asm
选项:
$ gcc -S -fverbose-asm function_printf.c
$ gcc -S -fverbose-asm hello_world.c
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 16
drwxrwxr-x 2 strong strong 4096 Sep 4 21:33 ./
drwxrwxr-x 6 strong strong 4096 Sep 4 20:16 ../
-rw-rw-r-- 1 strong strong 452 Sep 4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong 503 Sep 4 20:18 hello_world.c
strong@foreverstrong:~/ForeverStrong/hello_world$
strong@foreverstrong:~/ForeverStrong/hello_world$ gcc -S -fverbose-asm hello_world.c
hello_world.c: In function ‘main’:
hello_world.c:15:5: warning: implicit declaration of function ‘function_printf’ [-Wimplicit-function-declaration]
function_printf();
^
strong@foreverstrong:~/ForeverStrong/hello_world$
strong@foreverstrong:~/ForeverStrong/hello_world$ gcc -S -fverbose-asm function_printf.c
strong@foreverstrong:~/ForeverStrong/hello_world$
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 24
drwxrwxr-x 2 strong strong 4096 Sep 4 21:33 ./
drwxrwxr-x 6 strong strong 4096 Sep 4 20:16 ../
-rw-rw-r-- 1 strong strong 452 Sep 4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong 2723 Sep 4 21:33 function_printf.s
-rw-rw-r-- 1 strong strong 503 Sep 4 20:18 hello_world.c
-rw-rw-r-- 1 strong strong 2721 Sep 4 21:33 hello_world.s
strong@foreverstrong:~/ForeverStrong/hello_world$
strong@foreverstrong:~/ForeverStrong/hello_world$ cat function_printf.s
.file "function_printf.c"
# GNU C11 (Ubuntu 5.4.0-6ubuntu1~16.04.9) version 5.4.0 20160609 (x86_64-linux-gnu)
# compiled by GNU C version 5.4.0 20160609, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3
# GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
# options passed: -imultiarch x86_64-linux-gnu function_printf.c
# -mtune=generic -march=x86-64 -fverbose-asm -fstack-protector-strong
# -Wformat -Wformat-security
# options enabled: -faggressive-loop-optimizations
# -fasynchronous-unwind-tables -fauto-inc-dec -fchkp-check-incomplete-type
# -fchkp-check-read -fchkp-check-write -fchkp-instrument-calls
# -fchkp-narrow-bounds -fchkp-optimize -fchkp-store-bounds
# -fchkp-use-static-bounds -fchkp-use-static-const-bounds
# -fchkp-use-wrappers -fcommon -fdelete-null-pointer-checks
# -fdwarf2-cfi-asm -fearly-inlining -feliminate-unused-debug-types
# -ffunction-cse -fgcse-lm -fgnu-runtime -fgnu-unique -fident
# -finline-atomics -fira-hoist-pressure -fira-share-save-slots
# -fira-share-spill-slots -fivopts -fkeep-static-consts
# -fleading-underscore -flifetime-dse -flto-odr-type-merging -fmath-errno
# -fmerge-debug-strings -fpeephole -fprefetch-loop-arrays
# -freg-struct-return -fsched-critical-path-heuristic
# -fsched-dep-count-heuristic -fsched-group-heuristic -fsched-interblock
# -fsched-last-insn-heuristic -fsched-rank-heuristic -fsched-spec
# -fsched-spec-insn-heuristic -fsched-stalled-insns-dep -fschedule-fusion
# -fsemantic-interposition -fshow-column -fsigned-zeros
# -fsplit-ivs-in-unroller -fstack-protector-strong -fstdarg-opt
# -fstrict-volatile-bitfields -fsync-libcalls -ftrapping-math
# -ftree-coalesce-vars -ftree-cselim -ftree-forwprop -ftree-loop-if-convert
# -ftree-loop-im -ftree-loop-ivcanon -ftree-loop-optimize
# -ftree-parallelize-loops= -ftree-phiprop -ftree-reassoc -ftree-scev-cprop
# -funit-at-a-time -funwind-tables -fverbose-asm -fzero-initialized-in-bss
# -m128bit-long-double -m64 -m80387 -malign-stringops
# -mavx256-split-unaligned-load -mavx256-split-unaligned-store
# -mfancy-math-387 -mfp-ret-in-387 -mfxsr -mglibc -mieee-fp
# -mlong-double-80 -mmmx -mno-sse4 -mpush-args -mred-zone -msse -msse2
# -mtls-direct-seg-refs -mvzeroupper
.section .rodata
.LC0:
.string "!!!Hello Printf!!!"
.text
.globl function_printf
.type function_printf, @function
function_printf:
.LFB0:
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
movl $.LC0, %edi #,
call puts #
nop
popq %rbp #
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size function_printf, .-function_printf
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
strong@foreverstrong:~/ForeverStrong/hello_world$
strong@foreverstrong:~/ForeverStrong/hello_world$ cat hello_world.s
.file "hello_world.c"
# GNU C11 (Ubuntu 5.4.0-6ubuntu1~16.04.9) version 5.4.0 20160609 (x86_64-linux-gnu)
# compiled by GNU C version 5.4.0 20160609, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3
# GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
# options passed: -imultiarch x86_64-linux-gnu hello_world.c
# -mtune=generic -march=x86-64 -fverbose-asm -fstack-protector-strong
# -Wformat -Wformat-security
# options enabled: -faggressive-loop-optimizations
# -fasynchronous-unwind-tables -fauto-inc-dec -fchkp-check-incomplete-type
# -fchkp-check-read -fchkp-check-write -fchkp-instrument-calls
# -fchkp-narrow-bounds -fchkp-optimize -fchkp-store-bounds
# -fchkp-use-static-bounds -fchkp-use-static-const-bounds
# -fchkp-use-wrappers -fcommon -fdelete-null-pointer-checks
# -fdwarf2-cfi-asm -fearly-inlining -feliminate-unused-debug-types
# -ffunction-cse -fgcse-lm -fgnu-runtime -fgnu-unique -fident
# -finline-atomics -fira-hoist-pressure -fira-share-save-slots
# -fira-share-spill-slots -fivopts -fkeep-static-consts
# -fleading-underscore -flifetime-dse -flto-odr-type-merging -fmath-errno
# -fmerge-debug-strings -fpeephole -fprefetch-loop-arrays
# -freg-struct-return -fsched-critical-path-heuristic
# -fsched-dep-count-heuristic -fsched-group-heuristic -fsched-interblock
# -fsched-last-insn-heuristic -fsched-rank-heuristic -fsched-spec
# -fsched-spec-insn-heuristic -fsched-stalled-insns-dep -fschedule-fusion
# -fsemantic-interposition -fshow-column -fsigned-zeros
# -fsplit-ivs-in-unroller -fstack-protector-strong -fstdarg-opt
# -fstrict-volatile-bitfields -fsync-libcalls -ftrapping-math
# -ftree-coalesce-vars -ftree-cselim -ftree-forwprop -ftree-loop-if-convert
# -ftree-loop-im -ftree-loop-ivcanon -ftree-loop-optimize
# -ftree-parallelize-loops= -ftree-phiprop -ftree-reassoc -ftree-scev-cprop
# -funit-at-a-time -funwind-tables -fverbose-asm -fzero-initialized-in-bss
# -m128bit-long-double -m64 -m80387 -malign-stringops
# -mavx256-split-unaligned-load -mavx256-split-unaligned-store
# -mfancy-math-387 -mfp-ret-in-387 -mfxsr -mglibc -mieee-fp
# -mlong-double-80 -mmmx -mno-sse4 -mpush-args -mred-zone -msse -msse2
# -mtls-direct-seg-refs -mvzeroupper
.section .rodata
.LC0:
.string "!!!Hello World!!!"
.text
.globl main
.type main, @function
main:
.LFB2:
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
movl $0, %eax #,
call function_printf #
movl $.LC0, %edi #,
call puts #
movl $0, %eax #, D.2811
popq %rbp #
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE2:
.size main, .-main
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
strong@foreverstrong:~/ForeverStrong/hello_world$