自己动手构造编译系统:编译、汇编与链接导读

Preface前  言

本书适合谁读

本书是一本描述编译系统实现的书籍。这里使用“编译系统”一词,主要是为了与市面上描述编译器实现的书籍进行区分。本书描述的编译系统不仅包含编译器的实现,还包括汇编器、链接器的实现,以及机器指令与可执行文件格式的知识。因此,本书使用“编译系统”一词作为编译器、汇编器和链接器的统称。

本书的目的是希望读者能通过阅读本书清晰地认识编译系统的工作流程,并能自己尝试构造一个完整的编译系统。为了使读者更容易理解和学习编译系统的构造方法,本书将描述的重点放在编译系统的关键流程上,并对工业化编译系统的实现做了适当的简化。如果读者对编译系统实现的内幕感兴趣,或者想自己动手实现一个编译系统的话,本书将非常适合你阅读。

阅读本书,你会发现书中的内容与传统的编译原理教材以及描述编译器实现的书籍有所不同。本书除了描述一个编译器的具体实现外,还描述了一般书籍较少涉及的汇编器和链接器的具体实现。而且本书并非“纸上谈兵”,在讲述每个功能模块时,书中都会结合具体实现代码来阐述模块功能的实现。通过本书读者将会学习如何使用有限自动机构造词法分析器,如何将文法分析算法应用到语法分析过程,如何使用数据流分析进行中间代码的优化,如何生成合法的汇编代码,如何产生二进制指令信息,如何在链接器内进行符号解析和重定位,如何生成目标文件和可执行文件等。

本书的宗旨是为意欲了解或亲自实现编译系统的读者提供指导和帮助。尤其是计算机专业的读者,通过自己动手写出一个编译系统,能加强读者对计算机系统从软件层次到硬件层次的理解。同时,深入挖掘技术幕后的秘密也是对专业兴趣的一种良好培养。GCC本身是一套非常完善的工业化编译系统(虽然我们习惯上称它为编译器),然而单凭个人之力无法做到像GCC这样完善,而且很多时候是没有必要做出一个工程化的编译器的。本书试图帮助读者深入理解编译的过程,并能按照书中的指导实现一个能正常工作的编译器。在自己亲自动手实现一个编译系统的过程中,读者获得的不仅仅是软件开发的经历。在开发编译系统的过程中,读者还会学习很多与底层相关的知识,而这些知识在一般的专业教材中很少涉及。

如果读者想了解计算机程序底层工作的奥秘,本书能够解答你内心的疑惑。如果读者想自定义一种高级语言,并希望使该语言的程序在计算机上正常运行,本书能帮助你较快地达到目的。如果读者想从实现一个编译器的过程中,加强对编译系统工作流程的理解,并尝试深入研究GCC源码,本书也能为你提供很多有价值的参考。

基础知识储备

本书尽可能地不要求读者有太多的基础知识准备,但是编译理论属于计算机学科比较深层次的知识领域,难免对读者的知识储备有所要求。本书的编译系统是基于Linux x86平台实现的,因此要求读者对Linux环境的C/C++编程有所了解。另外,理解汇编器的实现内容需要读者对x86的汇编指令编程比较熟悉。本书不会描述过多编译原理教材中涉及的内容,所以要求读者具备编译原理的基础知识。不过读者不必过于担心,本书会按照循序渐进的方式描述编译系统的实现,在具体的章节中会将编译系统实现的每个细节以及所需的知识阐述清楚。

本书内容组织

本书共7章,各章的主要内容分别如下。

第1章代码背后

从程序设计开始,追溯代码背后的细节,引出编译系统的概念。

第2章编译系统设计

按照编译系统的工作流程,介绍本书编译系统的设计结构。

第3章编译器构造

描述如何使用有限自动机识别自定义高级语言的词法记号,如何使用文法分析算法识别程序的语法模块,如何对高级语言上下文相关信息进行语义合法性检查,如何使用语法制导翻译进行代码生成,以及编译器工作时符号信息的管理等。

第4章编译优化

介绍中间代码的设计和生成,如何利用数据流分析实现中间代码优化,如何对变量进行寄存器分配,目标代码生成阶段如何使用窥孔优化器对目标代码进行优化。

第5章二进制表示

描述Intel x86指令的基本格式,并将AT&T汇编与Intel汇编进行对比。描述ELF文件的基本格式,介绍ELF文件的组织和操作方法。

第6章汇编器构造

描述汇编器词法分析和语法分析的实现,介绍汇编器如何提取目标文件的主要表信息,并描述x86二进制指令的输出方法。

第7章链接器构造

介绍如何为可重定位目标文件的段进行地址空间分配,描述链接器符号解析的流程,以及符号地址的计算方法,并介绍重定位在链接器中的实现。

随书源码

本书实现的编译系统代码已经托管到github,源码可以使用GCC 5.2.0编译通过。代码的github地址是https://github.com/fanzhidongyzby/cit。代码分支x86实现了基于Intel x86体系结构的编译器、汇编器和链接器,编译系统生成的目标文件和可执行文件都是Linux下标准的ELF文件格式。代码分支arm实现了基于ARM体系结构的编译器,目前支持生成ARM 7的汇编代码。

目  录?Contents

前言

第1章 代码背后

1.1 从编程聊起

1.2 历史渊源

1.3 GCC的工作流程

1.3.1 预编译

1.3.2 编译

1.3.3 汇编

1.3.4 链接

1.4 设计自己的编译系统

1.5 本章小结

第2章 编译系统设计

2.1 编译程序的设计

2.1.1 词法分析

2.1.2 语法分析

2.1.3 符号表管理

2.1.4 语义分析

2.1.5 代码生成

2.1.6 编译优化

2.2 x86指令格式

2.3 ELF文件格式

2.4 汇编程序的设计

2.4.1 汇编词法、语法分析

2.4.2 表信息生成

2.4.3 指令生成

2.5 链接程序的设计 

2.5.1 地址空间分配

2.5.2 符号解析

2.5.3 重定位

2.6 本章小结

第3章 编译器构造

3.1 词法分析

3.1.1 扫描器

3.1.2 词法记号

3.1.3 有限自动机

3.1.4 解析器

3.1.5 错误处理

3.2 语法分析

3.2.1 文法定义

3.2.2 递归下降子程序

3.2.3 错误处理

3.3 符号表管理

3.3.1 符号表数据结构

3.3.2 作用域管理

3.3.3 变量管理

3.3.4 函数管理

3.4 语义分析

3.4.1 声明与定义语义检查

3.4.2 表达式语义检查

3.4.3 语句语义检查

3.4.4 错误处理

3.5 代码生成

3.5.1 中间代码设计

3.5.2 程序运行时存储

3.5.3 函数定义与return语句翻译

3.5.4 表达式翻译

3.5.5 复合语句与break、continue

语句翻译

3.5.6 目标代码生成

3.5.7 数据段生成

3.6 本章小结

第4章 编译优化

4.1 数据流分析

4.1.1 流图

4.1.2 数据流分析框架

4.2 中间代码优化

4.2.1 常量传播

4.2.2 复写传播

4.2.3 死代码消除

4.3 寄存器分配

4.3.1 图着色算法

4.3.2 变量栈帧偏移计算

4.4 窥孔优化

4.5 本章小结

第5章 二进制表示

5.1 x86指令

5.1.1 指令前缀

5.1.2 操作码

5.1.3 ModR/M字段

5.1.4 SIB字段

5.1.5 偏移

5.1.6 立即数

5.1.7 AT&T汇编格式

5.2 ELF文件

5.2.1 文件头

5.2.2 段表

5.2.3 程序头表

5.2.4 符号表

5.2.5 重定位表

5.2.6 串表

5.3 本章小结

第6章 汇编器构造

6.1 词法分析

6.1.1 词法记号

6.1.2 有限自动机

6.2 语法分析

6.2.1 汇编语言程序

6.2.2 数据定义

6.2.3 指令

6.3 符号表管理

6.3.1 数据结构

6.3.2 符号管理

6.4 表信息生成

6.4.1 段表信息

6.4.2 符号表信息

6.4.3 重定位表信息

6.5 指令生成

6.5.1 双操作数指令

6.5.2 单操作数指令

6.5.3 零操作数指令

6.6 目标文件生成

6.7 本章小结

第7章 链接器构造

7.1 信息收集

7.1.1 目标文件信息

7.1.2 段数据信息

7.1.3 符号引用信息

7.2 地址空间分配

7.3 符号解析

7.3.1 符号引用验证

7.3.2 符号地址解析

7.4 重定位

7.5 程序入口点与运行时库

7.6 可执行文件生成

7.7 本章小结

参考文献  

时间: 2024-10-02 00:33:24

自己动手构造编译系统:编译、汇编与链接导读的相关文章

自己动手构造编译系统:编译、汇编与链接

"自己动手系列" 自己动手构造编译系统 编译.汇编与链接 范志东  张琼声  著 图书在版编目(CIP)数据 自己动手构造编译系统:编译.汇编与链接 / 范志东,张琼声著. -北京:机械工业出版社,2016.7 (自己动手系列) ISBN 978-7-111-54355-8 I. 自- II. ①范- ②张- III. 编译器 IV. TP314 中国版本图书馆CIP数据核字(2016)第163077号 自己动手构造编译系统:编译.汇编与链接 出版发行:机械工业出版社(北京市西城区百万

自己动手构造编译系统:编译、汇编与链接1.3 GCC的工作流程

1.3  GCC的工作流程       在着手构造编译系统之前,需要先介绍编译系统应该做的事情,而最具参考价值的资料就是主流编译器的实现.GNU的GCC编译器是工业化编译器的代表,因此我们先了解GCC都在做什么. 我们写一个最简单的"HelloWorld"程序,代码存储在源文件hello.c中,源文件内容如下: #include<stdio.h> int main() {      printf("Hello World!");      return

自己动手构造编译系统:编译、汇编与链接2.6 本章小结

2.6  本章小结      本章介绍了编译系统的设计,并按照编译.汇编和链接的顺序阐述了它们的内部实现.同时,也介绍了x86指令和ELF文件结构等与操作系统及硬件相关的知识. 通过以上的描述,可以了解高级语言如何被一步步转化为汇编语言,以及词法分析.语法分析.语义分析.符号表和代码生成作为编译器的主要模块,其内部是如何实现的.汇编器在把汇编语言程序转化为二进制机器代码时,做了怎样的工作:汇编器的词法和语法分析与编译器有何不同:汇编器如何生成二进制指令和目标文件的信息.链接器在处理目标文件时是如

自己动手构造编译系统:编译、汇编与链接2.1 编译程序的设计

第2章 编译系统设计 麻雀虽小,五脏俱全. --<围城>    一个完善的工业化编译系统是非常复杂的,为了清晰地描述它的结构,理解编译系统的基本流程,不得不对它进行"大刀阔斧"地删减.这为自 己动手实现一个简单但基本功能完整的编译系统提供了可能.虽然本书设计的是简化后的编译系统,但保留了编译系统的关键流程.正所 谓"麻雀虽小,五脏俱全",本章从全局的角度描述了编译系统的基本结构,并按照编译.汇编和链接的流程来介绍其设计. 2.1  编译程序的设计 编译器

自己动手构造编译系统:编译、汇编与链接1.2 历史渊源

1.2  历史渊源    历史上很多新鲜事物的出现都不是偶然的,计算机学科的技术和知识如此,编译系统也不例外,它的产生来源于编程工作的需求.编程本质上是人与计算机交流,人们使用计算机解决问题,必须把问题转化为计算机所能理解的方式.当问题规模逐渐增大时,编程的劳动量自然会变得繁重.编译系统的出现在一定程度上降低了编程的难度和复杂度. 在计算机刚刚诞生的年代,人们只能通过二进制机器指令指挥计算机工作,计算机程序是依靠人工拨动计算机控制面板上的开关被输入到计算机内部的.后来人们想到使用穿孔卡片来代替原

自己动手构造编译系统:编译、汇编与链接1.3.2 编译

1.3.2  编译      接下来GCC对hello.i进行编译,命令如下: $gcc –S hello.i –o hello.s 编译后产生的汇编文件hello.s内容如下:      .file                "hello.c"      .section           .rodata .LC0:      .string  "Hello World!"      .text .globl main      .type        m

自己动手构造编译系统:编译、汇编与链接1.3.3 汇编

1.3.3  汇编             接着,GCC使用汇编器对hello.s进行汇编,命令如下: $gcc –c hello.s –o hello.o 生成的目标文件hello.o,Linux下称之为可重定位目标文件.目标文件无法使用文本编辑器直接查看,但是我们可以使用GCC自带的工具objdump命令分析它的内容,命令格式如下: $objdump –sd hello.o 输出目标文件的主要段的内容与反汇编代码如下: hello.o:     file format elf32-i386

自己动手构造编译系统:编译、汇编与链接2.4.1 汇编词法、语法分析

2.4.1  汇编词法.语法分析      汇编语言有独立的词法记号,对于汇编词法的分析,只需要构造相应的词法有限自动机就可以了.举一个简单的例子: mov eax,[ebp-8] 该指令有8个词法记号,它们分别是:'mov''eax'逗号'[''ebp''–''8'和']'.汇编器的词法分析器将词法记号送到语法分析器用于识别汇编语言的语法模块.同样,我们需要构造汇编语言语法分析器,在这里可以提前看一下上述汇编指令的抽象语法树,如图2-13所示.   图2-13  汇编指令抽象语法子树 图2-1

自己动手构造编译系统:编译、汇编与链接2.5.2 符号解析

2.5.2  符号解析     如果说地址空间分配是为段指定地址的话,那么符号解析就是为段内的符号指定地址.对于一个汇编文件来说,它内部使用的符号分为两类:一类来自自身定义的符号,称为内部符号.内部符号在其段内的偏移是确定的,当段的起始地址指定完毕后,内部符号的地址按照如下方式计算: 符号地址 = 符号所在段基址 + 符号所在段内偏移 另一类来自其他文件定义的符号,本地文件只是使用该符号,这类符号称为外部符号.外部符号地址在本地文件内是无法确定的,但是外部符号总定义在其他文件中.外部符号相对于定