编译链接原理

现在天天用VS做项目开发,其实从源代码到生成一个可执行文件,中间经历了许多步骤,往往我们容易忽略,因为VS IDE帮我们做了编译与链接两个阶段的工作,而编译与链接阶段的合称Build, 而这两个阶段最容易发生错误,所以就得了解它的原理,帮助我们改bug.为什么要把源文件生成可执行文件呢?因为机器只识别0/1代码,而源文件在磁盘上存储,要运行源文件就必须将源文件转化为机器识别的二进制文件,并将转化后的文件载入到内存中才能运行。

程序的运行过程分为编译阶段与链接阶段,而编译阶段又分为预编译,编译,汇编。

 1.预编译(生成.i文件)

1>宏替换(删除#define,并展开所有宏定义)

2>递归展开头文件(处理#include预编译指令,将包含的文件插入到预编译指令的位置)

3>删除预编译指令(处理所有条件预编译指令,如#if #endif #else)

4>删除注释 (//  /**/)

5>添加行号和标识

6>保留#progma

2.编译(生成.s文件)

1.词法分析:int 2a = 12;  //这种是错误的,定义变量只能以字母,下划线开头

2.语法分析: int a = 7; delete a;     //在编译阶段会识别到delete后面必须是指针

3.语义分析:结合上下文

4.代码优化

3.汇编(生成.o文件,可重定位的二进制文件)

将指令码翻译成二进制指令

在汇编完成后还有以下事情未处理:

1.弱符号位置未进行处理,2.虚拟地址以及虚拟位移未进行处理 3.符号表中的外部符号未进行处理

编译阶段:

编译经过预编译,编译,汇编处理后生成一个.o文件(以Linux为例),编译器编译源代码的文件叫做目标文件,目标文件就是编译后未进行链接的那些中间件(.o文件Linux,.obj文件 Windows),它跟可执行文件的结构和内容相似,从结构上来说,目标文件已经编译后的可执行文件,只是没有经过链接,里面的符号位置没有被调整。

目标文件有编译后的机器指令代码和数据。除了这些外,目标文件还包含了链接所需的一些信息,例如:符号表,调试信息,字符串。一般目标文件将这些信息按照属性不同按段进行存储。程序源代码编译后的机器指令一般放在代码段里,即.text中,全局变量和局部静态变量经常放在数据段,即.data中,未初始化的全局变量和局部静态变量放在.bss段中。

.bss段

未经初始化的全局变量和局部静态变量,但.bss段只是为未初始化的全局变量与局部静态变量预留位置而已,它并没有内容,所以在文件中也不占空间,这里引入了强弱符号的概念:

强符号:已经初始化的全局变量

弱符号:未初始化的全局变量

强弱符号使用规则:

1.两强符号:重定义错误

2.一强一弱符号:选择强符号

3.两弱符号:选择字节数较大的

 

链接阶段:

在编译完成后生成.o目标文件,就进入 到链接阶段。对于链接器来说,就是讲几个.o文件合成一个.exe文件,链接后的文件存储和目标文件的文件存储一样,都是将不同的信息属性存放到对应的段中,唯一不同的是,可执行二进制文件会对符号进行解析,调整一些地址。

链接阶段需要做的有:

1.符号表和段合并

2.符号解析:在符号引用的地方找到符号定义的地方

3.分配地址和空间

4.符号的重定位:处理虚假偏移量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值