lc-3 处理器的指令格式表

发布于 2025-01-01 08:00 更新于 2026-07-01 22:07 3277 字 17 min read

学期末尤其繁忙,不是考试就是小组作业,终于有时间写出这篇文章。话不多说,让我们开始吧 在介绍LC 3 处理器前,我们需要先回顾指令集体系结构(Instruction Set Architecture, ISA),其作为计算机系统中软硬件交互的核心界面,定义了处理器可执行指令的集合、寄存器组织结构、内

学期末尤其繁忙,不是考试就是小组作业,终于有时间写出这篇文章。话不多说,让我们开始吧

在介绍 LC-3 处理器前,我们需要先回顾指令集体系结构(Instruction Set Architecture, ISA),其作为计算机系统中软硬件交互的核心界面,定义了处理器可执行指令的集合、寄存器组织结构、内存访问方式以及中断处理机制等基础硬件特性。

LC3 简介

LC-3 有 16 条指令,每条指令有 16 个字符,也就意味着它有2162^{16}个地址空间,它还有 8 个寄存器(Register)。每个寄存器以 3 位二进制字符进行编号。

以下是这 16 条指令,以 15 到 12 位不同的操作符进行区分,此外操作符 1101 的指令并没有使用,所以其实只有 15 条指令

fengmian12.1
fengmian12.1

LC-3 指令格式表

操作指令

LC-3 有三种操作指令:ADD, AND, NOT

ADD 和 AND 需要两个操作数,NOT 只需要一个源操作数。下面这条操作指令将 R5 寄存器中的值进行 NOT 运算,然后存入 R3 寄存器。第 5 到第 0 位是未使用的位,以 1 进行填充。

DR 代表目标寄存器(Destination Register),是将操作结果存储到该寄存器中,SR 代表源寄存器(Source Register)

ADD 指令

ADD 指令的操作码为 0001,它将两个操作数相加,结果存入目标寄存器 DR。ADD 支持两种寻址模式,由第 5 位决定:

  • 寄存器模式(bit[5] = 0):两个源操作数均来自寄存器。bit[2
    ] 指定 SR2,bit[8
    ] 指定 SR1,bit[4
    ] 固定填充 00。
  • 立即数模式(bit[5] = 1):第二个操作数为 5 位有符号立即数(imm5),需要先进行符号扩展至 16 位后再与 SR1 相加。
寄存器模式:  0001  DR  SR1  0  00  SR2
立即数模式:  0001  DR  SR1  1  imm5

举个例子:0001 011 010 1 00101 表示 R2 = R2 + 5。将 R2(SR1,也是 DR)与符号扩展后的立即数 5 相加,结果存回 R2。

ADD 指令会根据计算结果自动更新条件码(Condition Code, CC):结果为正则 N=0 Z=0 P=1,结果为负则 N=1 Z=0 P=0,结果为零则 N=0 Z=1 P=0。

AND 指令

AND 指令的操作码为 0101,与 ADD 结构完全一致,同样支持两种寻址模式,区别仅在于执行按位与(bitwise AND)而非加法:

寄存器模式:  0101  DR  SR1  0  00  SR2
立即数模式:  0101  DR  SR1  1  imm5

同样会根据结果更新条件码。立即数模式常用于位掩码操作,例如 0101 011 010 1 00011 表示 R2 = R2 AND 3,可用来提取 R2 的低 2 位。

NOT 指令

NOT 指令的操作码为 1001,它是唯一一条只有一个源操作数的操作指令。对 SR 的值按位取反后存入 DR,低 6 位以 1 填充:

NOT:  1001  DR  SR  111111

举个例子:1001 011 101 111111 表示 R3 = NOT(R5),对 R5 按位取反后存入 R3。

NOT 同样会根据结果更新条件码。利用 NOT 和 ADD 组合,可以实现减法操作:先对减数取反,再加 1(二进制补码),然后与被减数相加。

数据搬移指令

数据搬移指令负责在寄存器和内存之间传输数据,是 LC-3 中指令数量最多的一类,共 7 条。根据寻址方式的不同,可分为三类:PC 相对寻址(LD、ST、LEA、LDI、STI)、基址偏移寻址(LDR、STR)和立即数加载(LEA 严格来说加载的是地址而非内存数据)。

LD 指令(Load)

操作码 0010,将内存中某个地址的值加载到目标寄存器 DR。地址计算方式:将 9 位有符号偏移量(PCoffset9)符号扩展至 16 位,然后与递增后的 PC 相加得到目标地址。

LD:  0010  DR  PCoffset9

举个例子:0010 011 000000101 表示 R3 = M[PC + 5],将 PC+5 地址处的值加载到 R3。

ST 指令(Store)

操作码 0011,将源寄存器 SR 的值存储到内存中。地址计算方式与 LD 完全相同——将 PCoffset9 符号扩展后与递增后的 PC 相加。

ST:  0011  SR  PCoffset9

注意:LD 和 ST 的寻址范围是 PC ± 256,这是因为 9 位有符号偏移量的范围是 -256 到 +255。

LDR 指令(Load Register)

操作码 0110,使用基址加偏移的方式计算地址:将 6 位有符号偏移量(offset6)符号扩展至 16 位,与基址寄存器 BaseR 的值相加。

LDR:  0110  DR  BaseR  offset6

举个例子:0110 011 010 000110 表示 R3 = M[R2 + 6],以 R2 为基址、偏移 6 来访问内存。

对比 LD:LD 以 PC 为基址(PC 相对寻址),适合访问全局变量和静态数据;LDR 以任意寄存器为基址,灵活度更高,适合访问数组元素和结构体成员。

STR 指令(Store Register)

操作码 0111,与 LDR 结构一致,区别在于将 SR 的值写入内存而非读取:

STR:  0111  SR  BaseR  offset6

LDI 指令(Load Indirect)

操作码 1010,间接寻址:先以 PC 相对寻址方式找到一个内存地址,再以该地址存储的值为最终地址,去读取数据加载到 DR。用 C 语言的指针概念来理解,就是双重解引用。

LDI:  1010  DR  PCoffset9

举个例子:1010 011 000001010,先计算 PC+10 处地址 A,再读取 M[A] 的值为地址 B,最终 R3 = M[B]。

STI 指令(Store Indirect)

操作码 1011,与 LDI 结构一致,区别在于将 SR 的值存储到通过间接寻址得到的目标地址中:

STI:  1011  SR  PCoffset9

LEA 指令(Load Effective Address)

操作码 1110,这条指令不访问内存,而是直接将计算出的地址(而非地址中的内容)加载到 DR。地址计算方式与 LD 相同:PCoffset9 符号扩展后与递增后的 PC 相加。

LEA:  1110  DR  PCoffset9

举个例子:1110 011 000000101 表示 R3 = PC + 5。注意:R3 得到的是地址值 PC+5,而非 M[PC+5] 的内容。

LEA 常用于获取某个数据区域或字符串的起始地址,然后配合 LDR/STR 遍历访问。

指令操作码格式寻址方式
LD00100010 DR PCoffset9PC 相对
ST00110011 SR PCoffset9PC 相对
LDR01100110 DR BaseR offset6基址偏移
STR01110111 SR BaseR offset6基址偏移
LDI10101010 DR PCoffset9间接
STI10111011 SR PCoffset9间接
LEA11101110 DR PCoffset9立即数(地址)

控制指令

控制指令负责改变程序的执行流程,包括条件分支、无条件跳转、子程序调用和系统陷阱等。

BR 指令(Branch)

操作码 0000,根据条件码 N、Z、P 的状态决定是否跳转。bit[11

] 分别为 n、z、p 标志位,当对应的条件码为 1 时,该条件被"选中";只有被选中且对应的 CC 位也为 1 时,跳转才会发生。

BR:  0000  n  z  p  PCoffset9
n z p助记符跳转条件
0 0 0—永不跳转(无操作)
1 1 1BR无条件跳转
1 0 0BRnN=1 时跳转(结果为负)
0 1 0BRzZ=1 时跳转(结果为零)
0 0 1BRpP=1 时跳转(结果为正)
1 1 0BRnzN=1 或 Z=1 时跳转
0 1 1BRzpZ=1 或 P=1 时跳转
1 0 1BRnpN=1 或 P=1 时跳转

若跳转发生,目标地址 = PC + sext(PCoffset9);若跳转不发生,程序顺序执行下一条指令。汇编器会将条件组合自动翻译为对应的助记符。

JMP 指令(Jump)

操作码 1100,无条件跳转到基址寄存器 BaseR 中存储的地址。bit[8

] 指定 BaseR,其余未使用位以 0 填充。

JMP:  1100  000  BaseR  000000

举个例子:1100 000 010 000000 表示 PC = R2,程序跳转到 R2 中存储的地址继续执行。

对比 BR:BR 的跳转目标是相对于 PC 的偏移且受条件码约束,而 JMP 的跳转目标来自寄存器,可以跳转到任意地址,更加灵活。

JSR 与 JSRR 指令(Jump to Subroutine)

操作码 0100,用于子程序调用。在执行跳转前,JSR/JSRR 会自动将返回地址(即当前 PC 的值,指向下一条指令)保存到 R7 寄存器中,以便子程序执行完毕后通过 RET 返回。

JSR 和 JSRR 由同一个操作码 0100 实现,通过 bit[11] 区分:

  • JSR(bit[11] = 1):使用 11 位 PC 相对偏移量,跳转范围为 PC ± 1024。
  • JSRR(bit[11] = 0):使用基址寄存器 BaseR 指定目标地址,bit[8
    ] 指定寄存器,其余位填充 0。
JSR:   0100  1  PCoffset11
JSRR:  0100  0  00  BaseR  000000

举个例子:0100 1 00000001001 先将当前 PC 保存到 R7,再跳转到 PC + 9。

注意:JSRR 的基址寄存器同样可以是 R7,但由于返回地址已经被写入 R7,若再以 R7 作为 BaseR 去跳转,会导致程序跳转回返回地址处(即自己),这种用法并不常见。

RET 指令(Return)

操作码 1100。实际上,RET 是 JMP R7 的别名——将 R7(保存了返回地址)的值加载到 PC,从而从子程序返回。

RET:  1100  000  111  000000

为什么是 R7?因为 JSR/JSRR 在跳转前已经把返回地址写入了 R7,所以 RET 只需一句 JMP R7 就能回到调用点。在 LC-3 汇编器中,RET 和 JMP R7 是完全等价的。

RTI 指令(Return from Interrupt)

操作码 1000,用于从中断服务程序返回。RTI 的行为较为特殊——它不会修改 PC 的值;当中断被触发时,处理器会将当前 PC 值压入系统栈,RTI 只是向处理器发出"中断处理完毕"的信号,由硬件恢复现场。

RTI:  1000  000000000000

在 LC-3 教学模型中,RTI 的具体行为取决于模拟器的实现,很多情况下它被简化处理。如果你用的是 LC-3 模拟器,建议查阅其文档确认 RTI 的精确行为。

TRAP 指令

操作码 1111,高 8 位为 11110000,低 8 位为 trapvect8,用于调用操作系统的服务例程。TRAP 与 JSR 类似:先将 PC 保存到 R7,然后跳转到由 trapvect8 指定的服务例程地址。

TRAP:  1111  0000  trapvect8

常见的 TRAP 服务例程(LC-3 操作系统内置):

trapvect8助记符功能
x20GETC从键盘读取一个字符(不回显),存入 R0[7
]
x21OUT输出 R0[7
] 中的字符到屏幕
x22PUTS输出以 R0 为起始地址的字符串(以 NUL 结尾)
x23IN提示输入一个字符,回显后存入 R0[7
]
x24PUTSP输出以 R0 为起始地址的打包字符串
x25HALT停止程序执行,打印停机信息

举个例子:1111 0000 00100001(即 TRAP x21),将 R0[7

] 中的字符输出到显示器上。

TRAP 是用户程序与 LC-3 操作系统之间的桥梁。你的程序不需要知道 OUT 服务例程具体放在内存的哪个位置,只需要通过 TRAP 指令加上对应的 trapvect8 即可调用。

指令操作码格式说明
BR00000000 n z p PCoffset9条件分支
JMP11001100 000 BaseR 000000无条件跳转
JSR01000100 1 PCoffset11子程序调用(PC 相对)
JSRR01000100 0 00 BaseR 000000子程序调用(寄存器)
RET11001100 000 111 000000从子程序返回(JMP R7)
RTI10001000 000000000000从中断返回
TRAP11111111 0000 trapvect8系统服务调用

总结

LC-3 总共定义了 16 条指令(操作码 1101 保留未使用,实际使用 15 条),按照功能可以分成三大类:

  • 操作指令(ADD、AND、NOT):执行算术和逻辑运算,结果存入寄存器,同时更新条件码。
  • 数据搬移指令(LD、ST、LDR、STR、LDI、STI、LEA):在寄存器和内存之间搬运数据,不同指令对应不同的寻址方式——PC 相对、基址偏移或间接寻址。
  • 控制指令(BR、JMP、JSR/JSRR、RET、RTI、TRAP):控制程序执行流程,实现条件分支、跳转、子程序调用和系统交互。

理解这些指令的二进制格式,是读懂 LC-3 机器码、手写汇编程序以及后续学习微架构设计和LC-3 数据通路的基础。建议对照指令格式表,多在 LC-3 模拟器上动手编写和调试几段程序,熟悉后你会发现这 16 条指令虽然简单,但已经能完成相当多有趣的事情了。

在学校压力还是很大的,各种事情使我脱不开身,而我又很喜欢游戏,这使我很少更新文章 QAQ,以后尽量多抽时间写点东西

喜欢的话,留下你的评论吧~