程序编译四个过程:
前言:
- 经过扫描,语法分析,语义分析,源代码优化,代码生成和目标代码优化,编译器忙活了这么多个步骤以后,源代码终于可以被编译成了目标代码。但是这个目标代码有一个问题:index和array的地址还没有确定。
- 如果我们要把目标代码使用汇编器编译成能够执行的指令,那么index和array的地址应该从哪里得到呢还有and so on?事实上,定义其他模块的全局变量和函数在最终运行时的绝对地址都是要在最终链接的时候才能确定。
- 所以现代编译器可以将一个源代码文件编译成一个未链接的目标文件,然后由链接器最终确定这些目标文件链接起来形成可执行文件。
预处理(Prepressing)
源代码和相关的头文件被预编译器cpp预编译为一个 .i 文件(#define ,#include,#if,删除注释行)
编译(Compilation)
将预处理之后的文件进行一系列词法分析,语法分析,语义分析及优化后生产相应的汇编代码文件
汇编(Assembly)
将汇编代码转化为机器可以执行的机器代码,例如使用gcc命令从C源代码文件开始,经过预编译,编译和汇编直接输出目标文件(Object File)(还没有经过链接的过程)
链接(Linking):
目标文件和库一起链接形成最中的可执行文件
- 目标文件的特点
1. 各个段没有具体的起始地址,只有段大小信息
2. 各个标识符没有实际地址,只有段中的相对地址
3. 段和标识符的实际地址需要链接器具体确定 - 链接器的工作:
- 将各个文件和库文件整合为最终的可执行程序
- 合并各个目标文件中的段
- 确定各个段和段之间的标识符的最终地址(重定位)
- _start函数
程序加载后,_start函数是第一个被调用执行的函数(_start函数入口地址就是代码段的起始位置)
_star