« 上一篇下一篇 »

代码生成器中的目标程序

构造一个能够产生高质量机器代码的代码生成器的难度受到目标机器指令体系结构的极大影响。最常见的目标机体系结构是RISC(精简指令集计算机)、CISC(复杂指令集计算机)和基于堆桟的结构。

RISC机通常有很多寄存器、三地址指令、简单的寻址方式和一个相对简单的指令集体系结构。相反,CISC机通常具有较少寄存器、两地址指令、多种寻址方式、多种类型的寄存器、可变长度的指令和具有副作用的指令。

在基于栈的机器中,运算是通过把运算分量压人一个栈,然后再对栈顶的运算分量进行运算而完成的。为了获得高性能,栈顶元素通常保存在寄存器中。因为人们觉得堆栈组织的限制太多,并且需要太多的交换和拷贝操作,所以基于堆栈的机器几乎已经消失了。

但是,基于堆桟的体系结构随着Java虚拟机(JVM)的出现又复活了。JVM是一个Java字节码的软件解释器。字节码是由Java编译器生成的一种中间语言。这个解释器提供了跨平台的软件兼容性。这是Java成功的一个重要因素。

解释执行会引起很高的性能损失,有时可能达到10倍的数量级。为了克服这个问题,人们创造了即时(Just-In-Time, JIT) Java编译器。这些即时编译器在运行时刻把字节码翻译成目标机上的本地硬件指令集。另一个提高Java程序性能的方法是建立一个编译器,把Java程序直接编译成目标机器指令,彻底绕过字节码。

输出一个使用绝对地址的机器语言程序的优点是程序可以放在内存中的某个固定位置上,并立即执行。程序可以很快地进行编译和执行。

输出可重定位的机器语言程序(通常称为目标模块,object module)可以使各个子程序能够被分别编译。一组可重定位的目标模块可以被一个链接加载器链接到一起并加载运行。如果我们要生成可重定位的目标模块,我们就必须为链接和加载付出代价。但是这样做可以使我们得到很多的灵活性。我们可以把子程序分开编译,并能够从一个目标模块中调用其他已经编译好的程序。如果B标机没有自动处理重定位,编译器就必须向加载器提供明确的重定位信息,以便把分开编译的程序模块链接起来。

输出一个汇编程序使代码生成过程变得稍微容易一些。我们可以生成符号指令,并使用汇编器的宏机制来帮助生成代码。这么做的代价是代码生成之后还需要增加一个汇编步骤。

在本章中,我们将使用一个非常简单的类RISC计算机作为目标机。我们在这个机器上加人了一些类CISC的寻址方式。这样我们就可以讨论CISC机器的代码生成技术了。为了增加可读性,我们把汇编代码用作目标语言。只要变量地址可以通过偏移量和存放于符号表中的其他信 息计算出来,代码生成器就可以为源程序中的名字生成可重定位地址或绝对地址。这和生成符号地址一样,都是很简单的事情。

« 上一篇下一篇 »