Linux 编译、连接原理

这篇博客是讲述计算机是如何将人类所编写的高级语言(字符语言)转换成自己所认识的二进制语言,对程序运行的。

一、预编译 (将.c文件转换为.i文件) 

1.#define  进行宏替换    例如#define max 10  对全文中的所有出现max的地方替换成数字10

2.处理 #if #elseif # endif 等所有预处理指令

3.#include递归展开头文件  因为#include文件里含有其他的文件,这些文件中可能还会包括其他的文件,所以需要进行递归展开

4.删除注释  例如将 // /**/ 等注释符包含的内容进行删除

5.添加行号和文件标识   对每个文件每行语句进行标号,以及添加#hello.c,#fun.c等文件标识,便于编译器编译显示错误时产生行号以及行号信息。

6.保留#pragma   例如 # pragma once 为头文件只编译一次的预处理指令,在预编译期需要保留,因为在编译期需要使用这个指令来进行编译。

二、编译 (将.i文件生成.s文件)

1.词法分析  (一个单词)

词法分析对一个单词进行分析,例如

arr[i] = (i + 4) * 2;
当源代码程序被输入到扫描器(Scanner),扫描器的任务就是运用一种类似于 有限状态机(Finite State Machine)的算法将源代码字符序列分割成一系类的记号(Token)。比如上面那行代码,总共包含了15个非空字符,经过扫面以后,产生了13个记号,入下表所示。

词法分析产生的记号一般可以分为以下几类:关键字、标识符、字面量(包含数字、字符串等)和特殊符号(如加号、等号)。在识别记号的同时,扫面器也完成了其他工作。比如将标识符放到符号表,将数字、字符串常量存放到文字表等,以备后面的步骤使用。
 

2.语法分析(一句话)

语法分析就是由语法分析器(Grammar Parser)将对由扫描器产生的记号进行语法分析,从而产生语法树(Syntax Tree)。整个分析过程采用了上下文无关语法(Context-free Grammar)的分析手段。由语法分析器生成的语法树就是表达式(Expression)为结点的树。
 

3.语义分析(结合上下文)

语义分析,由语义分析器(Semantic Analyzer)来完成。编译器所能分析的语义是静态语义(Static Semantic),所谓的静态语义是指在编译期间可以确定的语义,与之对应的动态语义(Dynamic Semantic)就是只有在运行期间才能确定的语义。

4代码优化

5.生成汇编语言

三、汇编 (将.s文件生成.o文件)

将汇编语言生成可重入二进制语言,即机器语言,每条语句一条汇编指令。

四、链接( 将.o文件生成.exe文件)

链接的主要内容就是把各个模块之间相互引用的部分都处理好,是的各个模块之间能够正确地衔接。链接阶段是最后的阶段,它也有四个步骤:

1.合并段和符号表  每个.o文件都有自己的段和符号表,链接的一步就是把各个.o文件的段和符号表合并。

2.符号解析

3.分配地址空间

4.符号重定位

在连接的过程中,对其他定义在目标文件中的函数调用的指令需要重新被调整,对使用其他定义在其他目标文件的变量来说,也存在同样的的问题。让我们结合具体的CPU指令来了解这个过程。假设我们有个全局变量叫var ,它在目标文件A里。我们在目标文件B里面要访问这个全局变量,比如我们在目标文件B里有这么一条指令:

mov    $0x2a, var
这条指令就是给var这个变量赋值0x2a,相当于C语言里面的语句var = 42;。然后我们编译目标文件B,得到这条指令机器码。

由于在编译目标文件B的时候,编译器并不知道变量var的目标地址,所以编译器在没法确定地址的情况下,将这条mov指令的目标地址设置为0,等待连接器将目标文件A和B连接起来的时候在将其修正。我们假设A和B链接后,变量var的地址确定下来为0x1000,那么链接器将会把这个指令的目标地址修改成0x10000。这个修改地址的过程也叫做重定位(Relocation),每个要被修正的地方叫一个重定位入口(Relocation Entry)。
 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值