编译阶段:
编译器cc1将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序。汇编语言程序中的每条语句都以一种标准的文本格式确切地描述了一条低级机器语言指令。汇编语言的有用之处在于它为不同高级语言的不同编译器提供了通用的输出语言。
编译过程就是把预处理完的文件进行一系列词法分析,语法分析,语义分析及优化后生产相应的汇编代码文件,这个过程往往是整个程序构建核心部分,也是比较复杂的部分。
操作如下:
lihui@LastWish ~ $ gcc -S hello.i -o hello.s
现在在gcc版本,都把预处理和编译两个步骤合成了一个步骤,使用一个叫cc1的程序就可以完成这两个步骤,可以直接通过调用下面命令生成hello.s:
lihui@LastWish ~ $ /usr/lib/gcc/x86_64-pc-cygwin/4.8.3/cc1 hello.c
bswap_16 bswap_32 bswap_64 gnu_dev_major gnu_dev_minor gnu_dev_makedev __sgetc_r main
Analyzing compilation unit
Performing interprocedural optimizations
<*free_lang_data> <visibility> <early_local_cleanups> <*free_inline_summary> <emutls> <whole-program>Assembling functions:
main
Execution times (seconds)
phase setup : 0.01 (100%) usr 0.00 ( 0%) sys 0.01 (20%) wall 1100 kB (52%) ggc
phase parsing : 0.00 ( 0%) usr 0.03 (100%) sys 0.04 (71%) wall 954 kB (45%) ggc
preprocessing : 0.00 ( 0%) usr 0.02 (52%) sys 0.02 (47%) wall 401 kB (19%) ggc
parser (global) : 0.00 ( 0%) usr 0.01 (48%) sys 0.01 (14%) wall 481 kB (23%) ggc
TOTAL
我这里用的是cyginw,所以如果直接用的linux系统可对应找到cc1这个程序
其实还有一种命令也可以一步完成:
liang@LastWish ~ $ gcc -S hello.c -o hello.s
可见实际上gcc这个命令只是这些后台程序的包装,它会根据不同的参数要求去调用预处理编译程序cc1,汇编器as,链接器ld
hello.s一共27行汇编代码,有兴趣的可以去研究下:
lihui@LastWish ~ $ cat hello.s
.file “hello.c”
.def __main; .scl 2; .type 32; .endef
.section .rdata,”dr”
.LC0:
.ascii “Hello World\0”
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
call __main
leaq .LC0(%rip), %rcx
call puts
movl $0, %eax
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.ident “GCC: (GNU) 4.8.3”
.def puts; .scl 2; .type 32; .endef