前言
咕
LC-3汇编
这一章节主要介绍LC-3的汇编语言,汇编语言可以提供一些便利的操作,更重要的是,用符号替代01,程序可读性提高。
汇编器:汇编器是将符号语言翻译为01的程序。除此之外,还提额外的操作支持(指库代码),可以实现数据的分配,初始化等等常见操作。
汇编语法
一条汇编语句包含以下几个部分:
- 标号:表示当前语句的内存地址,汇编器会直接将其翻译为地址。
- 操作:表示当前执行的操作,比如ADD
- 操作数:一般由寄存器表示,表示操作数存放在哪个寄存器中

值得注意的是,标号可以直接被汇编指令用作操作数,比如下面的 BRp LOOP LOOP是一个地址,可以直接被作为操作数。不用再手动计算PC+偏移的偏移了,非常方便。

伪操作
除了标号之外,汇编LC-3还提供了一些伪操作,这些操作其实是预制的汇编代码,相当于库函数,可以实现一些常用的繁琐操作。
伪操作以 . 字符开头。和指令一样,伪操作也有对应的操作数,下面给出伪操作的信息
| 伪操作 | 操作数 | 解释 |
|---|---|---|
| .ORIG | 地址 | 指定程序起始地址 (一般是x3000) |
| .END | 告诉编译器程序在此结束 但不是停止程序的意思 | |
| .BLKW | 数字n | 分配n个的内存单元空间 首地址是该行地址 |
| .FILL | 数字n | 分配一个内存单元的空间 并且赋值为n |
| .STRINGZ | 字符串 | 该地址作为字符串首地址 往后填充 末尾自动填充\0 |
TRAP指令
TRAP指令可以触发中断。进入到指定的中断程序。比如 TRAP x23 就是读取输入一个字符。其中x23地址处存储的是中断服务函数的入口地址。(这个是指针寻址)
下面给出所有的TRAP操作
| 符号 | 实际操作 | 解释 |
|---|---|---|
| GETC | TRAP x20 | 阻塞程序并等待键盘输入一个字符(无回显)到R0寄存器 (存ASCII码) |
| OUT | TRAP x21 | 输出一个R0中的ASCII码代表的字符 |
| PUTS | TRAP x22 | 输出R0中地址为起始的字符串,直到遇见\0 |
| IN | TRAP x23 | 输出提升,阻塞程序并等待键盘输入一个字符(有回显)到R0寄存器 (存ASCII码) |
| HALT | TRAP x25 | 终止程序 |
输入与输出
上面讲到方便的输入输出指令,可是他们是怎么实现的呢?本章就讲述LC-3的输入
输入输出寄存器
LC-3中,使用4个寄存器来和外界输入输出设备进行交互,他们分别是:
| 名称 | 地址 | 解释 |
|---|---|---|
| KBSR | 0xFE00 | 键盘状态寄存器:第15位为1则表示接收到新输入 |
| KBDR | 0xFE02 | 键盘数据寄存器:低八位保存键盘输入字符ASCII码 |
| DSR | 0xFE04 | 显示状态寄存器:第15位为1表示可以向显示器输出数据 |
| DDR | 0xFE06 | 显示数据寄存器:低八位的ASCII码写到屏幕上 |
输入获取机制
输入获取建立在对KBSR的存取上。硬件电路的操作分为三个步骤:
- 按下键盘,硬件电路将ASCII码放置到KBDR低8位
- 硬件电路将KBSR最高位置1,表示收到新输入
- 键盘被禁用
值得注意的是,使用轮询的方式来向KBSR查询是否有新输入,下面给出输入获取的软件轮询机制:
除此之外,如果要判断一个指向KBDR的数据存取,其数据是否来自键盘,我们可以查询KBSR的第15位,如果为1表示键盘接收到新输入,那么存取KBDR是好的,如果为0表示未有输入,那么此时KBDR的值是无效的。
下面是 LC-3 模拟器 TRAP x20 (读取一个字符)所调用的服务程序的源码:

输出机制
输出和输入类似,建立在对状态寄存器的读写上。当显示器准备就绪时,硬件电路将DSR第15位置1。
向显示器写数据,同样使用轮询机制,下面给出软件操作:
- 轮询DSR第15位是否为1,为1表示显示设备可用
- 将DDR低8位的数据输出,期间任何写入DDR的字符将被忽略

下面是 LC-3 模拟器中 TRAP x21 (即输出一个字符)调用的服务程序的源码:

汇编过程
这个感觉和c的有点像(计系2老师听了吐血 )
- 第一次扫描建立符号表
- 第二次扫描利用符号表的信息,生成对应的汇编代码
值得注意的是,有些比较离谱的操作会报错。比如 pc+offset 的寻址只有 9 位立即数,范围为 -128~127,如果寻址的范围超过,那么会报错。除此之外,标号的寻址和上述 pc+偏移 的情况相同。
