程序员的自我修养

2016-12-13  本文已影响0人  mark20

编译和连接

1. 预处理(Prepressing)

2. 编译(Compilation)

编译就是把预处理完的文件进行一系列的词法分析、语法分析、语义分析及优化后生产相应的汇编代码文件。

gcc 这个命令只是后台程序的包装,它会根据不同的参数要求去调用预编译编译程序cc1、汇编器as、链接器来ld。

3. 汇编(Assembly)

将汇编代码转变成机器可以执行的指令

4. 链接(Linking)

  1. 词法分析
    首先源代码程序被输入到扫描器(scanner),它运用一种类似有限状态机(Finite State Machine)的算法将源代码的字符序列分割成一系列的记号(Token)
  2. 语法分析
    语法分析器(Grammar Parser)将对由扫描器产生的记号进行语法分析,产生语法树(Syntax Tree),整个过程采用长下文无关语法(Context-free Grammar)的分析手段。语法树就是以表达式(Expression)为及节点的树。
  3. 语义分析
    语义分析器(Semantic Analyer) 来完成。所能分析的语义是静态语义(Static Semantic),通常包括声明和类型的匹配、类型的转换。
  4. 中间语言生成
    源码级优化器(Source Code Optimizer)将整个语法树转换成中间代码(Intermediate Code)
  5. 目标代码的生成与优化
    源代码级优化器产生中间代码标志着下面的过程都属于编辑器后端,主要包括的代码生成器(Code Generator)目标优化器(Target Code Optimizer)。代码生成器将中间代码转换目标机器码。
  6. 链接
    链接的主要过程包括:地址和空间分配(Adress and Storage Allocation)符号决议(symbol resolution)重定向(Relocation)等步骤。

目标文件是什么样的

目标文件的内容至少有编译后的机器指令代码,数据。还有链接时所需要的信息,如符号表,调试信息,字符串等。

自定义段

GCC提供了一个扩展机制,使得程序员可以指定变量所处的段:

_attribute_((section("FOO"))) int global = 42;
_attribute_((section("Bar"))) void foo ( )
{
}

我们在全局变量或者函数之前加上“_attribute_((section("name")))”属性就可以把相应的变量或者函数放到以“name”作为段名的段中。

ELF文件结构描述

ELF文件结构图

ELF Header
.text
.data
.bss
other sections...
Section header table
String Tables
Symbol Tables
...

静态链接

1.空间与地址分配

主要有两种方式:按序叠加和相似段合并。按序叠加会造成内存空间大量的内部碎片。所以一个更实际的方法是将相同性质的段合并在一起,叫做相似段合并。比如将所有输入文件的“.text”段合并到输出文件的“.text”段。使用这相思段合并方法的链接器一般都采用一种叫两步链接(Two-pass Linking)的方法,也就说整个过程分两步。

  1. 空间与地址分配
  2. 符号解析与重定位

装载与动态链接

上一篇下一篇

猜你喜欢

热点阅读