跳转至

LC-3

LC-3 指令集架构 (ISA) 完整说明

1. 概述

LC-3 是一种为教学目的而设计的 16 位冯·诺依曼结构的计算机架构。其 ISA 简洁但功能完备,包含了现代计算机的核心概念,如寻址模式、条件执行、中断等,是学习计算机组成和体系结构的理想模型。

LC-3

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 支持以下寻址模式:

  1. 立即数 (Immediate): 操作数直接包含在指令中(例如 ADD R1, R2, #5)。
  2. 寄存器 (Register): 操作数位于寄存器中(例如 ADD R1, R2, R3)。
  3. PC 相对 (PC-relative): 指令提供一个偏移量 (offset),有效地址是当前 PC 值加上符号扩展后的偏移量。用于 LD, ST, LEA, BR, JSR 等指令。
  4. 间接 (Indirect): 指令提供一个偏移量,该偏移量指向一个内存地址,而这个内存地址中存储的是最终的操作数。用于 LDI, STI
  5. 基址偏移 (Base+Offset): 指令提供一个基址寄存器 (Base Register) 和一个偏移量 (offset),有效地址是基址寄存器的内容加上符号扩展后的偏移量。用于 LDR, STR
  6. 寄存器间接 (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, SR2ADD DR, SR1, imm5
    • 操作: DR = SR1 + SR2DR = SR1 + SignExt(imm5)
    • 说明: 将两个数相加,结果存入 DR。设置条件码 (CC)。
  • AND

    • 格式: AND DR, SR1, SR2AND DR, SR1, imm5
    • 操作: DR = SR1 AND SR2DR = 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)
    • 说明: 条件分支指令。BRnzpBR 是无条件分支。
  • JMP (Jump) / RET (Return)

    • 格式: JMP BaseRRET
    • 操作: PC = BaseR (RET 等价于 JMP R7)
    • 说明: 跳转到 BaseR 寄存器中存储的地址。用于从子程序返回。
  • JSR / JSRR (Jump to Subroutine)

    • 格式: JSR PCoffset11JSRR 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. 汇编语言语法与约定

  1. 指令 (Instructions): 使用操作码的助记符,如 ADD, AND, BR
  2. 伪操作 (Assembler Directives/Pseudo-Ops):
    • .ORIG <address>: 指定程序在内存中的起始地址(例如 .ORIG x3000)。
    • .END: 标记程序结束。
    • .FILL <value>: 分配一个内存字并用指定值初始化。
    • .BLKW <n>: 分配 n 个连续的内存字(Block of Words)。
    • .STRINGZ "chars": 分配连续的字,用字符串的 ASCII 码初始化,并在末尾自动添加终止符 (x00)。
  3. 标签 (Labels): 用于标记代码或数据的位置,方便引用(例如 LOOP, PROMPT)。汇编器会将其转换为对应的 PC 偏移量。
  4. 注释 (Comments): 以分号 ; 开始,直至行尾。
  5. 数字表示:
    • 十进制: #10
    • 十六进制: xAxAFF
    • 二进制: b1010
  6. 操作数顺序: 目标寄存器通常在最左边。

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)的坚实基础,因为它包含了所有核心概念,而避免了商业架构中的历史包袱和复杂性。