从代码到机器码
0 前言
本文讲讲编译的总体过程。 参考程序员自我修养那本书。
整个过程分别是预处理(Prepressing)、编译(Compilation)、汇编(Assembly)和链接(Linking)
1 流程阐述
1.1 预处理
预编译过程主要处理那些源代码文件中的以“#”开始的预编译指令。比如“#include”、“#define”等,主要处理规则如下:
- 将所有的“#define”删除,并且展开所有的宏定义。
- 处理所有条件预编译指令,比如“#if”、“#ifdef”、“#elif”、“#else”、“#endif”。
- 处理“#include”预编译指令,将被包含的文件插入到该预编译指令的位置。注意,这个过程是递归进行的,也就是说被包含的文件可能还包含其他文件。
- 删除所有的注释“//”和“/* */”。
- 添加行号和文件名标识,比如#2“hello.c”2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号。
- 保留所有的#pragma编译器指令,因为编译器须要使用它们。
1.2 编译
具体参考我这个帖子
编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后生产相应的汇编代码文件,这个过程往往是我们所说的整个程序构建的核心部分,也是最复杂的部分之一。
代码经过扫描器词法分析拆成多个token,然后语法分析生成语法树,语义分析进一步修改语法树,从而生成一个顺序的中间语言代码
之后进行编译后端:目标代码生成与优化,最后得到一个汇编代码文件
1.3 汇编
汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令。此时得到了obj文件
1.4 链接
将不同的obj文件和库文件链接起来,进行地址空间分配,符号决议和重定位。