LC-3
LC-3 指令集架构 (ISA) 完整说明
1. 概述
LC-3 是一种为教学目的而设计的 16 位冯·诺依曼结构的计算机架构。其 ISA 简洁但功能完备,包含了现代计算机的核心概念,如寻址模式、条件执行、中断等,是学习计算机组成和体系结构的理想模型。
2. 基本规格
- 字长 (Word Size): 16 位
- 内存地址空间 (Memory Address Space): \(2^{16}\) = 65,536 个位置,每个位置包含一个 16 位的字。
- 寄存器文件 (Register File): 8 个 16 位通用寄存器 (R0 - R7)。
- 程序计数器 (PC): 一个 16 位寄存器,存放下一条要执行指令的地址。
- 条件码 (Condition Codes, CC): 三个 1 位寄存器:N (Negative), Z (Zero), P (Positive)。它们根据最近一次写入寄存器的指令结果进行更新,用于条件分支判断。
3. 指令格式
所有 LC-3 指令都是 16 位长,操作码 (Opcode) 固定占据高 4 位 (bits [15:12])。指令格式根据操作码的不同分为几种类型。
指令类型 | Opcode (bits [15:12]) | 其余位功能 |
---|---|---|
ADD | 0001 | 寄存器、寄存器、立即数/寄存器 |
AND | 0101 | 寄存器、寄存器、立即数/寄存器 |
BR | 0000 | 条件码标志、PC 偏移量 |
JMP/RET | 1100 | 寄存器/返回 |
JSR/JSRR | 0100 | 链接标志、PC 偏移量/寄存器 |
LD | 0010 | 寄存器、PC 偏移量 |
LDI | 1010 | 寄存器、PC 偏移量 |
LDR | 0110 | 寄存器、基址寄存器、偏移量 |
LEA | 1110 | 寄存器、PC 偏移量 |
NOT | 1001 | 寄存器、寄存器 |
RTI | 1000 | (特权指令) |
ST | 0011 | 寄存器、PC 偏移量 |
STI | 1011 | 寄存器、PC 偏移量 |
STR | 0111 | 寄存器、基址寄存器、偏移量 |
TRAP | 1111 | 陷阱向量 |
4. 寻址模式 (Addressing Modes)
LC-3 支持以下寻址模式:
- 立即数 (Immediate): 操作数直接包含在指令中(例如
ADD R1, R2, #5
)。 - 寄存器 (Register): 操作数位于寄存器中(例如
ADD R1, R2, R3
)。 - PC 相对 (PC-relative): 指令提供一个偏移量 (offset),有效地址是当前 PC 值加上符号扩展后的偏移量。用于
LD
,ST
,LEA
,BR
,JSR
等指令。 - 间接 (Indirect): 指令提供一个偏移量,该偏移量指向一个内存地址,而这个内存地址中存储的是最终的操作数。用于
LDI
,STI
。 - 基址偏移 (Base+Offset): 指令提供一个基址寄存器 (Base Register) 和一个偏移量 (offset),有效地址是基址寄存器的内容加上符号扩展后的偏移量。用于
LDR
,STR
。 - 寄存器间接 (Register Indirect): 操作数的地址位于寄存器中。这是基址偏移模式中偏移量为 0 的特殊情况(例如
JMP R2
)。
5. 指令集详解
操作数说明:
* DR
: 目标寄存器 (Destination Register)
* SR
, SR1
, SR2
: 源寄存器 (Source Register)
* imm5
: 5 位立即数,符号扩展至 16 位
* offset6
, offset9
, offset11
: 6, 9, 11 位偏移量,符号扩展至 16 位
* PCoffset9
: PC + SignExt(offset9)
* BaseR
: 基址寄存器
1. 算术与逻辑指令
-
ADD
- 格式:
ADD DR, SR1, SR2
或ADD DR, SR1, imm5
- 操作:
DR = SR1 + SR2
或DR = SR1 + SignExt(imm5)
- 说明: 将两个数相加,结果存入 DR。设置条件码 (CC)。
- 格式:
-
AND
- 格式:
AND DR, SR1, SR2
或AND DR, SR1, imm5
- 操作:
DR = SR1 AND SR2
或DR = SR1 AND SignExt(imm5)
- 说明: 按位与操作,结果存入 DR。设置条件码 (CC)。
- 格式:
-
NOT
- 格式:
NOT DR, SR
- 操作:
DR = NOT(SR)
- 说明: 按位取反操作,结果存入 DR。设置条件码 (CC)。
- 格式:
2. 数据移动指令
-
LD (Load)
- 格式:
LD DR, PCoffset9
- 操作:
DR = mem[PC + SignExt(offset9)]
- 说明: 从内存(PC 相对寻址)加载数据到寄存器。设置条件码 (CC)。
- 格式:
-
LDI (Load Indirect)
- 格式:
LDI DR, PCoffset9
- 操作:
DR = mem[mem[PC + SignExt(offset9)]]
- 说明: 间接加载。先找到指针,再通过指针找到数据。设置条件码 (CC)。
- 格式:
-
LDR (Load Base+Offset)
- 格式:
LDR DR, BaseR, offset6
- 操作:
DR = mem[BaseR + SignExt(offset6)]
- 说明: 从内存(基址+偏移寻址)加载数据。设置条件码 (CC)。
- 格式:
-
LEA (Load Effective Address)
- 格式:
LEA DR, PCoffset9
- 操作:
DR = PC + SignExt(offset9)
- 说明: 将计算出的有效地址(而非该地址的内容)加载到寄存器。不设置条件码。
- 格式:
-
ST (Store)
- 格式:
ST SR, PCoffset9
- 操作:
mem[PC + SignExt(offset9)] = SR
- 说明: 将寄存器的值存储到内存(PC 相对寻址)。
- 格式:
-
STI (Store Indirect)
- 格式:
STI SR, PCoffset9
- 操作:
mem[mem[PC + SignExt(offset9)]] = SR
- 说明: 间接存储。将数据存储到指针所指向的地址。
- 格式:
-
STR (Store Base+Offset)
- 格式:
STR SR, BaseR, offset6
- 操作:
mem[BaseR + SignExt(offset6)] = SR
- 说明: 将寄存器的值存储到内存(基址+偏移寻址)。
- 格式:
3. 控制流指令
-
BR (Branch)
- 格式:
BRn / BRz / BRp / BRnz / BRnp / BRzp / BRnzp offset9
- 操作: 如果条件码 (N, Z, P) 与指令中的标志匹配,则
PC = PC + SignExt(offset9)
- 说明: 条件分支指令。
BRnzp
或BR
是无条件分支。
- 格式:
-
JMP (Jump) / RET (Return)
- 格式:
JMP BaseR
或RET
- 操作:
PC = BaseR
(RET
等价于JMP R7
) - 说明: 跳转到 BaseR 寄存器中存储的地址。用于从子程序返回。
- 格式:
-
JSR / JSRR (Jump to Subroutine)
- 格式:
JSR PCoffset11
或JSRR BaseR
- 操作:
R7 = PC
; 然后PC = PC + SignExt(offset11)
或PC = BaseR
- 说明: 跳转到子程序,并将返回地址 (PC) 保存在 R7 中。
JSR
是 PC 相对,JSRR
是寄存器间接。
- 格式:
-
RTI (Return from Interrupt)
- 格式:
RTI
- 操作: 从中断处理程序返回(特权指令,在用户模式下执行会触发异常)。
- 格式:
-
TRAP (System Call)
- 格式:
TRAP trapvect8
- 操作:
R7 = PC
;PC = mem[ZExt(trapvect8)]
- 说明: 执行系统调用/陷阱例程。 trapvect8 指定了要执行的服务。
TRAP x20
(GETC): 从键盘读入一个字符,不回显。TRAP x21
(OUT): 输出一个字符。TRAP x22
(PUTS): 输出一个字符串。TRAP x23
(IN): 提示并读入一个字符,并回显。TRAP x24
(PUTSP): 输出一个字节字符串。TRAP x25
(HALT): 停止程序。
- 格式:
6. 汇编语言语法与约定
- 指令 (Instructions): 使用操作码的助记符,如
ADD
,AND
,BR
。 - 伪操作 (Assembler Directives/Pseudo-Ops):
.ORIG <address>
: 指定程序在内存中的起始地址(例如.ORIG x3000
)。.END
: 标记程序结束。.FILL <value>
: 分配一个内存字并用指定值初始化。.BLKW <n>
: 分配 n 个连续的内存字(Block of Words)。.STRINGZ "chars"
: 分配连续的字,用字符串的 ASCII 码初始化,并在末尾自动添加终止符 (x00
)。
- 标签 (Labels): 用于标记代码或数据的位置,方便引用(例如
LOOP
,PROMPT
)。汇编器会将其转换为对应的 PC 偏移量。 - 注释 (Comments): 以分号
;
开始,直至行尾。 - 数字表示:
- 十进制:
#10
- 十六进制:
xA
或xAFF
- 二进制:
b1010
- 十进制:
- 操作数顺序: 目标寄存器通常在最左边。
7. 完整编程示例
以下是一个简单的 LC-3 汇编程序,它读取两个数字并计算它们的和。
; 程序:计算两个数的和
; 起始地址: x3000
.ORIG x3000 ; 程序从 x3000 开始
; 初始化
AND R0, R0, #0 ; 清空 R0
AND R1, R1, #0 ; 清空 R1
AND R2, R2, #0 ; 清空 R2 (用于存储和)
; 提示用户输入第一个数字
LEA R0, PROMPT1 ; 加载提示信息1的地址到 R0
PUTS ; 输出字符串 (TRAP x22)
; 读取第一个数字
GETC ; 读取字符到 R0 (TRAP x20)
OUT ; 回显字符 (TRAP x21)
ADD R1, R0, #0 ; 将输入字符从 R0 复制到 R1
LD R0, NEWLINE ; 加载换行符
OUT ; 输出换行符
; 提示用户输入第二个数字
LEA R0, PROMPT2 ; 加载提示信息2的地址到 R0
PUTS ; 输出字符串
GETC ; 读取第二个字符到 R0
OUT ; 回显字符
ADD R2, R0, #0 ; 将第二个输入字符复制到 R2
LD R0, NEWLINE
OUT
; 计算并输出结果
ADD R0, R1, R2 ; 将两个字符的 ASCII 码相加
; 注意:这只是一个简单示例,实际中需要将 ASCII 码转换为数字并进行计算,然后再转换回 ASCII 输出。
; 此处为了简化,直接输出结果(可能不正确)。
; 输出结果提示
LEA R0, RESULT
PUTS
ADD R0, R1, R2 ; 将“和”放回 R0 准备输出
OUT ; 输出“和”的字符
HALT ; 停止程序 (TRAP x25)
; 数据区
PROMPT1 .STRINGZ "Enter first number: "
PROMPT2 .STRINGZ "Enter second number: "
RESULT .STRINGZ "The sum is: "
NEWLINE .FILL x0A ; ASCII 换行符 '\n'
.END ; 程序结束
8. 总结
LC-3 ISA 的精妙之处在于其简洁性与完备性的平衡。它用为数不多的指令清晰地展示了: * 数据处理: 通过 ADD, AND, NOT。 * 数据搬运: 通过 LD/ST 系列指令及其多种寻址模式。 * 程序控制: 通过 BR, JMP/RET, JSR/JSRR。 * 系统交互: 通过 TRAP 机制。
掌握 LC-3 是理解更复杂架构(如 x86, ARM)的坚实基础,因为它包含了所有核心概念,而避免了商业架构中的历史包袱和复杂性。