1、基本过程
1) 编写源代码
2) 编译
3) 链接
4) 装载
5) 执行
2、编译阶段
2.1 预处理阶段
2.2 语言分析阶段
2.3 汇编阶段
编译器会将标准的语言集合转换成特定CPU指令集的语言集合。不同的CPU包含不同的功能性需求,通常包含不同的指令集、寄存器和中断,所以不同的处理器要有不同的编译器对其支持。对于x86处理器体系结构来说,编译器支持两种指令格式,汇编代码会遵循其中一种:
2.4 优化阶段
当由源代码文件生成最初版本的汇编代码后,优化过程就开始了,这可以将程序的寄存器使用率最小化。此外,通过分析能够预测出实际上不需要执行的部分代码,并将其删去
2.5 代码生成阶段
生成编译输出目标的阶段,其中每一个目标文件对应一个编译单元。汇编指令(用可读的ASCII码编写)会在此阶段转换成对应机器指令(操作码)的二进制值,并写入目标文件的特定位置
2.6 编译过程的局限性
绝大多数情况下,将源代码翻译成目标文件的过程十分简单:将代码行翻译成特定处理平台运行的机器代码指令,或者为初始化变量预留空间并对这些变量初始化,或者为初始化变量预留空间并用0填充等。
但这个过程会导致一些问题:虽然源代码被分成多个源代码文件存放,但要组成一个程序,那么他们之间必然存在一定的关联。这些单独存放的代码一般会通过下面方式之一来建立联系:
3、链接
3.1 重定位
链接过程的第一个阶段仅仅进行拼接,其过程是将分散在单独目标文件中不同类型的节拼接到程序内存映射节中。为了完成该任务,需要将之前预留的空间,也就是节中从0开始的地址范围转换成最终程序内存映射中更具体的地址范围。
3.2 解析引用
需要在链接阶段对引用进行解析,此时链接器需要:
链接过程的最终结果是二进制可执行文件,其结构布局遵循特定目标平台的可执行文件格式。
无论实际格式有什么区别,可执行文件总会包含几个合成的节(.text、.data、.bss节以及其他特殊的节),这些节是通过拼接单独的目标文件得到的。
尤其是,为了解析各个编译单元之间的引用,确保不同部分之间的函数调用与变量访问准确有效,生成代码节(.text)时,不能仅仅简单的拼接目标文件中的节,还需要对链接器进行修改。
main函数看起来是整个程序执行的起点,但却不是程序启动后真正首先执行的代码。
有一个很重要的细节,可执行文件并不完全是通过编译项目源代码文件生成的,实际上,用于启动程序的一部分非常重要的代码片段是在链接阶段才添加到程序内存映射中的。
链接器通常将这部分代码存放在程序内存映射的起始处,有两种不同形式:
程序声明周期
原文:https://www.cnblogs.com/UniqueSquirrel/p/10614873.html