在编译代码时我们通常使用 gcc hello.c -o hello 即将hello.c文件编译成hello可执行文件。那么这其中编译器做了哪些工作?
从最简单的例子入手hello.c:
#include <stdio.h>
int main(){
printf("hello\n");
return 0;
}
《深入理解计算机系统》一书中给出编译器详细的工作流程图:
预处理
gcc -E hello.c -o hello.i
-E参数是告知编译器只执行预处理工作,不执行后续编译工作。
-E Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard output.
预处理主要处理“#”开头的语句,具体包括如下过程:
- 将#define删除并展开所有宏定义。
- 处理所有条件预编译命令,例如“#if、#ifdef、#endif、#else、#elif”
- 处理#include命令,将被包含文件插入到命令处,这是一递归的过程,
- 保留所有#pragma编译器命令。
//短短的一个hello经过预处理后达到了800多行
845 extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __lea f__)) ;
846
847
848 extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __lea f__));
849 # 943 "/usr/include/stdio.h" 3 4
850
851 # 8 "hello.c" 2
852
853 int main()
854 {
855 printf("hello\n");
856 return 0;
857 }
编译
gcc -s hello.i -o hello.s
(或 /usr/lib/gcc/i686-linux-gnu/4.9/cc1 hello.c)
编译过程是把预处理完的文件进行词法、语法、语义分析及优化后产生汇编代码文件
(ccl所在路径和版本与具体系统有关)
//编译后产生的汇编代码文件
1 .file "hello.c"
2 .section .rodata
3 .LC0:
4 .string "hello"
5 .text
6 .globl main
7 .type main, @function
8 main:
9 .LFB0:
10 .cfi_startproc
11 leal 4(%esp), %ecx
12 .cfi_def_cfa 1, 0
13 andl $-16, %esp
14 pushl -4(%ecx)
15 pushl %ebp
16 .cfi_escape 0x10,0x5,0x2,0x75,0
17 movl %esp, %ebp
18 pushl %ecx
19 .cfi_escape 0xf,0x3,0x75,0x7c,0x6
20 subl $4, %esp
21 subl $12, %esp
22 pushl $.LC0
23 call puts
汇编
gcc -c hello.s -o hello.o
(或 as hello.s –o hello.co )
该阶段汇编器(as)将 hello.s 翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序(relocatable object program)的格式,并将结果保存在目标文件 hello.o 中。hello.o 文件是一个二进制文件(前面预处理和编译产生的都是可识别的文本文件),它的字节编码是机器语言指令而不是字符。
如果用vim打开,会发现全是看不懂的乱码,原因就在一此。
链接
ld -static crt1.o crti.o crtbeginT.o hello.o -start-group -lgcc -lgcc_eh -lc-end-group crtend.o crtn.o (省略了文件的路径名)此处涉及到很多东西,暂时没弄懂
hello程序调用了 printf 函数,printf 函数存在于一个名为 printf.o 的单独的预编译好了的目标文件中,而这个文件必须以某种方式合并到我们的 hello.o 程序中。链接器(ld)就负责处理这种合并。结果就得到 hello 文件,它是一个可执行目标文件。
#have a good day
版权声明:本文为davie1love原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。