计算机系统要素--第六章,01-HACK汇编编译器模块介绍


HACK汇编编译器分成四个模块:
语法分析器(Parser):对输入文件进行语法分析
编码(Code):提供所有汇编命令对应的二进制代码
符号表(Symbol Table):处理符号
主程序:驱动整个编译过程

语法分析器(Parser)

Parser: 将汇编命令分解为其所表达的内存含义(域和符号)。
封装对输入代码的访问操作。功能包括:读取汇编语言命令并对其进行解析:提供“方便访问汇编命令成分(域和符号)”的方案;去掉所有空格和注释。

程序 参数 返回值 功能
构造函数/
初始化函数
输入文件/
输入流
打开输入文件/输入流,为语法解析作准备
hasMoreCommands Boolean 输入当中还有更多命令吗
advance 从输入中读取下一条命令,将其当作“当前命令”,仅当hasMoreCommands()为真时,才能调用本程序。最初始的时候,没有“当前命令”
commandType A_COMMAND,
C_COMMAND,
L_COMMAND
返回当前命令的类型:
A_COMMAND:
当@Xxx中的Xxx是符号或十进制数字时
C_COMMAND
用于dest=comp;jump
L_COMMAND(实际上是伪命令)
当(Xxx)中的Xxx是符号时
symbol 字符串 返回形如@Xxx或(Xxx)的当前命令的符号或十进制值,仅当commandType()是A_COMMAND或L_COMMAND是才能调用
dest 字符串 返回当前C-指令的dest助记符(具有8种可能的形式)
仅当commandType()是C_COMMAND时才能调用
comp 字符串 返回当前C-指令的comp助记符(具有28种可能的形式),仅当commandType()是C_COMMAND时才能调用
jump 字符串 返回当前C-指令的jump助记符(具有8种可能的形式),仅当commandType()是C_COMMAND时才能调用

编码(Code)

将Hack汇编语言助记符翻译成二进制码。

程序 参数 返回值 功能
dest 助记符(字符串) 3bits 返回dest助记符的二进制码
comp 助记符(字符串 7bits 返回comp助记符的二进制码
jump 助记符(字符串 3bits 返回jump助记符的二进制码

无符号程序的汇编编译器

Parser和Code模块实现较为简单,可以先实现,而符号表的处理较为复杂,可以放到第二阶段再进行。
在第一阶段约定:输入的Prog.asm程序不包含符号,因此:(a)在所有地址命令@Xxx中,Xxx常数是十进制数而不是符号;(b)输入文件不包含标记命令即(Xxx)命令。
实现:

  1. 打开Prog.hack的输出文件
  2. 处理汇编指令文件Prog.asm
  3. 对C指令,将翻译后的指令域的二进制码连接到一个单一的16-位字上,将16-位字写入Prog.hack文件
  4. 对A-指令@Xxx,将语法分析器返回的二进制常数翻译成对应的二进制表示,然后将得到的16-位字写入Prog.hack文件。

符号表(Symbol Table)

翻译中需要为指令中可能包含的符号确定实际的地址。汇编编译器使用符号表(symbol table)来完成这个任务,符号表用来建立和维持符号与其地址之间的关联。哈希表(hash table)是建立映射的经典数据结构之一。
SymbolTable: 在符号标签(symbolic labels)和数字地址之间建立关联。

程序 参数 返回值 功能
Constructor 创建空的符号表
addEntry symbol(字符串),
address(int)
将(symbol,address)配对加入符号表
contains symbol(字符串) Boolean 符号表是否包含了指定的symbol
GetAddress symbol(字符串) int 返回与symbol关联的地址

有符号程序的汇编编译器

汇编程序允许符号在定义之前使用(即goto命令的目的地)。此功能为汇编程序员福音,却使编译器开发变得困难。解决方法之一是,编写“两遍(two-pass)”编译器,从头到尾读取两次代码。
第一遍构建符号表,第二遍用每个符号相关的含义(数字地址)替换该符号,并产生最后的二进制码。
符号表中应该包含并处理Hack语言中的所有三种符号:预定义符号(predefined symbols)标签(labels)变量(variables)

  1. 初始化 用所有预定义符号和它们预分配的RAM地址对符号进行初始化。
  2. 第一遍 用数字记录ROM地址–当前命令最终加载的目标地址。每遇到一条指令都自动加1,遇到标签伪指令或注释时不发生变化。
    遇到伪指令时,在符号表中加上一个新条目来将Xxx与最终用于存储程序中下一条指令的ROM地址关联起来。在这个阶段程序中所有标记和它们的ROM地址被加入到符号表中。程序的变量放在第二阶段处理。
  3. 第二遍 对每一行进行语法分析。@Xxx指令中Xxx是符号时,在符号表中查找Xxx。如果在符号表中没有找到该符号,说明它是变量。这时在符号表中添加(Xxx,n),这里n代表下一个可使用的RAM地址。分配的RAM地址是紧邻预定义符号地址之后的连续数字。

猜你喜欢

转载自blog.csdn.net/qq_17065591/article/details/108719649
今日推荐