« 上一篇下一篇 »

目标代码中的地址

我们将说明如何使用静态和栈式内存分配为简单的过程调用和返回生成代码,以此将IR中的名字转换成为目标代码中的地址。我们描述了每个正在执行的程序是如何在它的逻辑地址空间上运行的。这个空间被划分成为四个代码及数据区域:

1)一个静态确定的代码区Code。这个区存放可执行的目标代码。目标代码的大小可以在编译时刻确定。

2)一个静态确定的静态数据区Static。这个区存放全局常量和编译器生成的其他数据。全局常量和编译器数据的大小也可以在编译时刻确定。

3)一个动态管理的堆区heap。这个区存放程序运行时刻分配和释放的数据对象。Heap的大小不能在编译时刻静态确定。

4)一个动态管理的桟区Stacfc。这个区存放过程的活动记录。活动记录会随着过程的调用和返回被创建和消除。和堆区一样,栈区的大小也不能在编译时刻确定。

静态分配

为了说明简化的过程调用和返回的代码生成,我们关注下面的三地址语句:

•call callee

•return

•halt

•action,这是代表其他三地址语句的占位符。

活动记录的大小和布局是由代码生成器通过存放于符号表中的名字的信息来确定的。我们将首先说明如何在过程调用时在一个活动记录中存放返回地址,以及如何在过程调用结束后把控制返回到这个地址。为方便起见,我们假设活动记录的第一个位置存放返回地址。

我们首先考虑实现最简单情况(即静态分配)时的代码。这里,中间代码中的call语句可以用包含两个目标机指令的序列来实现:

ST callee. static Area, Uhere + 20 BR callee. code Area

ST指令把返回地址保存到callee的活动记录的开始处,而BR把控制传递到被调用过程callee的目标代码上。属性callee. staticArea是一个常量,给出了callee的活动记录的开始处的地址,而属性callee. codeArea也是一个常量,指向运行时刻内存中Code区中被调用过程callee的第一个指令的地址。

ST指令中的运算分量#here +20是返回地址的文字表示,它是紧跟在BR指令之后的指令的地址。我们假设是当前指令的地址,而调用序列中的三个常量加上两个指令的长度为5个字,即20个字节。

过程代码的结尾处是一个返回到调用者过程的指令。但是没有调用者的第一个过程例外,它的最后一个指令是HALT。这个指令把控制返回给操作系统。一个return语句可以使用一个简单的跳转语句实现:

BR * callee. static Area

它把控制流转到保存在callee的活动记录开始位置的地址上。

« 上一篇下一篇 »