对于存储文件中的C程序转换为计算机上可运行程序的四个步骤:
- 首先将高级语言程序编译成汇编语言程序
- 然后用机器语言组装成目标模块
- 链接器将多个模块与库组合在一起以解析所有引用
- 加载器将机器代码放入合适的存储器位置以供处理器执行
为了加快转换过程,可以跳过或者将一些步骤合到一起。一些编译器直接生成目标模块,一些系统使用连接加载器执行最后两个步骤。为了识别文件类型,UNIX遵循文件的后缀约定:C源文件命名为x.c,汇编文件命名为x.s,目标文件命名为x.o,静态链接库程序为x.a,动态链接库路径为x.so,以及默认情况下,可执行文件称为a.out。
- 编译器
编译器将C程序转换为机器能理解的符号形式——汇编语言程序。高级语言程序比汇编语言使用更少的代码行,因此程序员的工作效率更高。
在1975年,许多操作系统和汇编器都是用汇编语言编写,因为那时的计算机内存很小而且编译器效率还很低下。如今每个DRAM芯片的内存容量增加了数百倍,从而减少了程序员对程序带大小的关注,今天的优化编译器几乎可以像汇编语言专家那样生成汇编语言,而且对大型程序的优化效果有时比人工优化更好。
- 汇编器
由于汇编语言是高层软件的接口,因此汇编器还可以处理机器指令的常见变体,就像这些变体是他自己的指令一样。硬件不需要实现这些指令;然而,他们在汇编语言中的出现简化了程序转换和编程。这类指令称为伪指令。
- 链接器
连接器的工作有三个步骤:
- 将代码和数据模块按符号特征放入内存。
- 2决定数据和指令标签的地址。
- 修正内部和外部引用
- 加载器
加载器遵循以下步骤:
- 读取可执行文件首部以确定正文段和数据段的大小。
- 为政委和数据创建足够大的地址空间。
- 将可执行文件中的指令和数据复制到内存中。
- 将主程序的参数复制到栈项。
- 初始化处理器寄存器并将栈指针指向第一个空闲位置。
- 跳转到启动例程,将参数复制到寄存器中并调用程序的主例程。当主例程返回时,启动历程通过exit系统调用终止程序。