- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
第十章 编译系统和运行系统
通常,除了编译器外,我们还需要一些其它工具的帮助,才能得到可执行的目标程序,这些工具包括预处理器、汇编器和连接器等。对于Fortran、Pascal和C来说,这些工具都较简单或明显。了解这些工具有助于我们掌握从源程序到可执行目标程序的实际处理过程,这些知识对于参与大型软件系统的开发是很有用的。本章介绍C语言编译系统。
另外,目标代码运行时,还需要一些工具的支撑,如动态连接程序、无用单元收集程序等,这些工具的集合称为运行系统。本章还介绍Java语言的运行系统及其无用单元收集程序。
10.1 C语言的编译系统
除了编译器外,我们还需要一些其它的工具来建立一个可执行的目标程序。本节以GNU C编译系统(简称GCC系统)为例,来说明程序设计语言编译系统的一般工作过程。
一个C源程序可以分成若干个模块,存储在不同的文件中。C编译系统对这些源文件分别进行预处理、编译和汇编、形成可重定位的目标文件;然后再利用连接器将这些目标文件和必要的库文件连接成一个可执行的目标文件,即具有绝对地址的机器代码。这一过程可用图10.1描绘。
大多数编译系统提供一个驱动程序来调用语言的预处理器、编译器、汇编器、连接器,以支持用户完成从源程序到可执行程序的翻译。在GCC系统中,驱动程序的名字是gcc(或cc)。
下面我们结合一个C语言的程序实例来讨论GCC系统的工作步骤。图10.2中的程序由两个文件main.c和swap.c组成,为便于引用中间的语句,我们增加了行号。在Unix(还有Linux)环境下,键入如下命令可以得到该程序的可执行文件swap:
gcc –v –o swap main.c swap.c
这里,使用选项–v可以输出该编译系统各步骤执行的命令和执行结果,选项–o紧跟着的字符串指示生成的可执行文件的名字。
10.1.1 预处理器
gcc首先调用预处理器cpp,将源程序文件翻译成一个ASCII中间文件,它是经修改后的源程序。图10.3是main.c经预处理后生成的中间文件main.i。
预处理器产生编译器的输入,它实现以下功能:
(1)文件包含 预处理器可以把源程序文件中的包含声明(#include)扩展为程序正文。例如,当源程序文件中含有语句
#include stdio.h
时,预处理器会在系统标准路径下搜索stdio.h,再用文件stdio.h中的内容来代替这个语句。
(2)宏展开 C程序中可以使用#define来定义宏,一个宏定义给出一段C代码的缩写。预处理器将源程序文件中出现的、对宏的引用展开成相应的宏定义,这一过程称为宏展开。例如,main.c的第(7)行为宏A的定义,第(12)行中的A是对该宏的引用。在预处理后产生的main.i中,宏A的定义转换成一个空行,对宏A的引用则展开成buf[0]。
(3)条件编译 预处理器根据#if和#ifdef等编译命令及其后的条件,将源程序中的某部分包含进来或排除在外。通常把排除在外的语句转换成空行。
显然,实现一个这样的预处理器并不困难。
有些语言的预处理器用于增强老的语言,使之包含现代的控制结构和数据类型。从增强语言到老语言的翻译由这样的预处理器完成。
10.1.2 汇编器
GCC系统的编译器cc1产生汇编代码, main.i被编译成的ASCII汇编文件main.s见图10.4。这些汇编代码由汇编器进一步处理。
最简单的汇编器对输入进行两遍扫描。在第一遍,汇编器扫描输入,将表示存储单元的所有标识符都存入符号表,并分配地址。在第二遍,汇编器再次扫描输入,把每个操作码翻译成机器语言中代表那个操作的位串,并把代表存储单元的每个标识符翻译成符号表中为这个标识符分配的地址。
如果一个汇编代码文件中有外部符号的引用,如果汇编器生成的是可重定位的目标文件,那么汇编器的工作将变得略微复杂。在10.1.4节,当我们知道了目标文件的格式后,要实现一个汇编器并不是一件困难的事情。另外,一遍扫描完成汇编代码到可重定位目标代码的翻译也是完全可能的。
在GCC编译系统中,要想得到源程序被编译成的汇编代码,只要加编译选项(S就可以。例如,用
gcc (S main.c
我们可以得到汇编文件main.s。使用汇编器as
as (o main.o main.s
我们可以将main.s汇编成可重定位目标文件main.o。
10.1.3 连接器
我们已经知道,汇编器或编译器输出的机器代码称为目标模块或目标文件,它有两种形式:
(1)
(2)3)共享目标文件 它是一种特殊的可重定位目标文件。我们可以在装入程序或运行程序时,动态地装入共享目标文件到内存并将它和程序连接。
技术上,一个目标模块是一个字节序列,而一个目标文件则是一个以文件形式存储在外部存储器上的目标
文档评论(0)