第二章(编译和链接)

来源:互联网 发布:pu校园软件 编辑:程序博客网 时间:2024/06/05 04:22

第二章属于第二部分,静态链接。先了解下程序运行的步骤。简单地C语言程序,一串代码是如何变成程序的输出呢?这其中经

历了4个步骤,预处理(Prepressing),编译(Compilation),汇编(Assembly),链接(Linking)。

预编译:

预编译就是预处理,所谓的预编译就是处理源程序中以“#”开头的指令,#include,#define等等,处理步骤如下:
1.删除所有#define,展开所有宏定义,处理#include递归进行,将被包含的文件插入该预编译指令的位置
2.处理#if,#ifdef,#elif,#else,#endif等所有的条件预编译指令
3.删除注释
4.保留#pragma编译器指令(#pragma指令能够设定编译器的状态或者指示编译器完成特定的一些动作,给出主机或操作系统专有特征)
5.添加行号和文件标识(如#2 “hello.c” 2,便于编译时编译器产生调试用的行号信息及用于易于变出编译错误的行)
Linux下的执行指令:
$gcc -E hello.c -o hello.i

 编译:

编译过程包括一系列的词法分析, 语法分析,语义分析以及优化后产生的相应汇编代码文件。这是程序构建的核心部分。现
版本GCC将预编译和编译步骤合为了一个步骤,使用cc1程序完成。
Linux下的执行命令:这个命令包括多个后台程序的包装,预编译编译程序cc1,汇编器as,链接器ld
$gcc -S hello.c -o hello.s

 汇编:

汇编器是将汇编代码转变成机器可以执行的指令(0101那些东西),每一个汇编语句几乎都对应一条机器语言(也就是说汇

编语言很高效,不过没人经常用汇编编)。

Linux下的执行指令:

$as hello.s -o hello.o

链接:

汇编器并非直接输出可执行文件而是输出了一个目标文件,链接器ld链接了大量的x.o文件,

编译器的作用:

编译器将高级语言翻译成了低级语言,编译过程分为了6步:扫描,语法分析,语义分析,源代码优化,代码生成,目标代码优化

编译器前端:

词法分析:

源代码输入到扫描器之后,扫描器运用简单地有限自动机算法(Finite State Machine)将源代码字符序列分割为一系
列的记号(Token),记号分为以下几类:关键字,标示符,字面量(数字,字符串等),特殊符号。

语法分析:

语法分析器(Grammar Parser)对由扫描器产生的记号进行语法分析,通过上下文无关语法(Context-free Grammar)的分
析手段,产生语法树。

语义分析:

语义分析由语义分析器(Semantic Analyzer)完成,编译器分析的是静态语义,其在编译期可以确定的语义,对应的动态语
义只有在运行期才能够确定。静态语义包括声明和类型的转换,动态语义如0作为除数这个错误只有在运行时才能够出现。

中间语言生成:

现代编译器会对源代码级别一个优化过程,源码级优化器(Source Code Optimizer)会对语义分析器得到的标识语义后
的语法树进行优化,得到优化后的语法树,然后将整个语法树转变为中间代码(Intermediate Code),即对语法树的顺
序表示,中间代码常见的有三地址代码(Tree-address Code)和P-代码(P-Code)。从中间代码开始分为了编译器两
个阶段,编译器前段产生机器无关的中间代码,编译器后端将中间代码转换成目标机器代码。好处就是跨平台的编译器可以使
用多平台单前端,多后端。

相应的不同阶段的语法树:

(上述的P-Code就是指伪代码,三地址码如t1=index+4),以上语法树对应的c语言源代码:

array[index]=(index +4 )*(2+6)

编译器后端:

编译器后端主要包括的是代码生成器(Code Generator)和目标代码优化器(Target Code Optimizer)代码生成器将中间

代码转换成目标机器代码,注意,是转换成目标机器代码,也就是10代码,举个例子(此例实际操作是在机器码级别的

,但是为了方便看懂是以汇编码来展示):


其优化在乘法指令用基址变址寻址lea指令完成,从而省却了一些代码

链接器:

当系统十分复杂时,我们把每个源代码模块独立编译,然后按顺序组装,这个过程就是链接。此过程包括了地址和空间
分配(Address and Storage Allocation),符号决议(Symbol Resolution),重定位(Relocation)。符号决议的名字有很
多,个人觉得记下那些英文名字对以后的英文书籍阅读有很大帮助,符号决议又可叫做符号绑定(Symbol Binding),
名称绑定(Name Binding),名称决议(Name Resolution),地址绑定(Address Binding),指令
绑定(Instruction Binding)。决议倾向于静态链接,绑定倾向于动态链接。简单的链接过程如上图(静态链接)。
至于动态链接,那是后话了。

重定位:

一、定义:重定位就是把程序的逻辑地址空间变换成内存中的实际物理地址空间的过程,也就是说在装入时对目标程序
中指令和数据的修改过程。他是实现多道程序在内存中同时运行的基础。重定位有两种,分别是动态重定位与静态重定位
  二、分类
  1、静态重定位:即在程序装入内存的过程中完成,是指在程序开始运行前,程序中的各个地址有关的项均已完成
重定位,地址变换通常是在装入时一次完成的,以后不再改变,故成为静态重定位。
  2、动态重定位:它不是在程序装入内存时完成的,而是CPU每次访问内存时 由动态地址变换机构(硬件)自动
进行把相对地址转换为绝对地址。动态重定位需要软件和硬件相互配合完成。
  三、时机
  将逻辑地址空间重定位到物理地址空间的时机有三种:
  1、程序编译连接时。
  2、程序装入内存时。
  3、程序执行时。
  四、扩展阅读:
  重定位是由操作系统安排的。
  在装入程序前,系统会计算未使用的内存,然后将程序装入,并记下开始地址。在执行有相对地址的指令时,会
将所有的地址加个刚才记下的开始地址,就叫重定位。
  重定位与EXE文件无关,它是程序装入时的一种方式。利用重定位可提高内存空间的使用率。
以上原版复制百度百科,觉得简要介绍的还不错。。。









原创粉丝点击