我们所写源文件变成可执行程序是需要经过一系列的过程的,也就是我们所说的编译链接,下面简单介绍编译链接原理

编译链接的几个步骤如下图所示:

预编译了NV_RESTORE后协调器不会组网 预编译 链接_重定位


1.预编译阶段主要工作为:

(1)#include  递归展开头文件

(2)#define  宏定义替换

(3)删除注释

(4)添加行符号文件标识

(5)保留#pragma(交给编译器处理)

.c/.cpp文件经过预编译处理生成.i文件

2.编译

基本可以分为以下几步:

(1)词法分析

(2)语法分析

(3)语义分析

(4)代码优化

在检查无误

编译主要将代码转成汇编代码,并且在这个步骤做了两件很重要的工作,<1>编译器在每个文件中保存一个函数地址符表,该表中存储着当前文件内包含的各个函数地址。<2>因为这一步要生成汇编代码,即一条一条的指令,而调用函数的代码会被编译成call指令,call指令后面跟的时jmp指令的汇编代码地址,而jmp指令后面跟着的才是“被调用的函数编译成汇编代码的第一条指令”的地址,但是call指令后面补充地址的工作是在链接时做的事情。

 

 

 

 

 

 

 

.i文件经过编译生成.s文件

3.汇编

在汇编阶段主要是将指令代码翻译汇编成二进制文件(.o文件)。

汇编后的.o文件时可重定位的二进制文件

4.链接

编译器将生成的多个.o文件来链接到一起生成一个可执行的.exe文件

链接的时机

 (1)编译时,就是源代码被编译成机器代码时(静态链接器负责);

 (2)加载时,也就是程序被加载到内存时(加载器负责);

(3)运行时,有应用程序来实施(动态链接器负责);

链接部分所要做的工作大致可以分为以下几点:

<1>合并段和符号表

<2>符号的解析

<3>分配地址和空间

<4>符号重定位

也可以从静态链接与动态链接两部分了解链接:

(1)静态链接:

链接器将函数的代码从其所在地(目标文件或静态链接库中)拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。

为创建可执行的.exe文件,链接器必须要完成的主要任务:

<1>符号解析:把目标文件中符号的定义和引用联系起来;

<2>重定位:把符号定义和内存地址对应起来,然后修改所有对符号的引用。

(2)动态链接

  在此种方式下,函数的定义在动态链接库或共享对象的目标文件中。在编译的链接阶段,动态链接库只提供符号表和其他少量信息用于保证所有符号引用都有定义,保证编译顺利通过。动态链接器(ld-linux.so)链接程序在运行过程中根据记录的共享对象的符号定义来动态加载共享库,然后完成重定位。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码  。