当前位置: 首页 > news >正文

【ShuQiHere】️ ️ LC-3 指令集架构 (ISA) 全面解析

🖥️ LC-3 指令集架构 (ISA) 全面解析

提示:本文将详细介绍 LC-3 指令集的各类指令和寻址方式,提供丰富的解释和 实际应用的示例,并配以背景知识、表情符号和表格来增强理解。😊

目录

  1. LC-3 背景介绍
  2. 操作指令(Operate Instructions)
    • ADD(加法运算)
    • AND(按位与运算)
    • NOT(按位取反)
  3. 数据传输指令(Data Movement Instructions)
    • LD(直接加载)
    • LDI(间接加载)
    • LDR(基址加偏移量加载)
    • LEA(加载地址)
    • ST(直接存储)
    • STI(间接存储)
    • STR(基址加偏移量存储)
  4. 控制指令(Control Instructions)
    • BR(条件分支)
    • JMP(无条件跳转)
    • JSR/JSRR(子程序跳转)
    • RET(返回)
  5. 寻址方式(Addressing Modes)
    • 直接寻址
    • 间接寻址
    • 基址加偏移量寻址
    • PC 相对寻址
    • 立即数寻址
  6. 总结

1. LC-3 背景介绍 📚

LC-3(Little Computer 3)是一种用于教育目的的简单计算机架构,旨在帮助学生理解计算机系统的基本原理。它有:

  • 16 位架构:意味着它的寄存器和内存地址都是 16 位的。
  • 8 个通用寄存器:R0 到 R7。
  • 操作码(Opcode):每个指令都有一个 4 位的操作码,决定了指令的类型。

LC-3 的指令集主要分为 操作指令数据传输指令控制指令,并支持多种 寻址方式


LC-3 指令集概览

指令类别指令数量示例指令功能概述
操作指令3ADD, AND, NOT算术和逻辑运算
数据传输指令7LD, ST, LEA数据在寄存器和内存间移动
控制指令5BR, JMP, JSR控制程序执行流程
总计15

2. 操作指令(Operate Instructions)🛠️

操作指令用于对数据进行算术和逻辑运算。

操作指令一览表

指令操作码 (Opcode)功能格式示例描述
ADD0001加法运算ADD R1, R2, R3R1 = R2 + R3R1 = R2 + IMM5
AND0101按位与运算AND R1, R2, R3R1 = R2 AND R3R1 = R2 AND IMM5
NOT1001按位取反NOT R1, R2R1 = NOT R2

ADD(加法运算)➕

  • 操作码0001
  • 功能:对两个操作数进行加法,结果存储在目标寄存器中。
  • 格式
    • 寄存器模式ADD DR, SR1, SR2,其中 DR = SR1 + SR2
    • 立即数模式ADD DR, SR1, IMM5,其中 DR = SR1 + IMM5
实际应用示例:

示例 1:计算两个数的和

假设需要计算两个数 510 的和,并将结果存储在 R0 中。

        ; 假设 R1 = 5,R2 = 10AND R1, R1, #0     ; 清空 R1ADD R1, R1, #5     ; R1 = 5AND R2, R2, #0     ; 清空 R2ADD R2, R2, #10    ; R2 = 10ADD R0, R1, R2     ; R0 = R1 + R2 = 15

示例 2:累加数组元素

累加数组中前 3 个元素的值。

        LEA R3, ARRAY      ; R3 指向数组起始地址LDR R1, R3, #0     ; R1 = ARRAY[0]LDR R2, R3, #1     ; R2 = ARRAY[1]ADD R0, R1, R2     ; R0 = R1 + R2LDR R1, R3, #2     ; R1 = ARRAY[2]ADD R0, R0, R1     ; R0 = R0 + R1

数据段:

ARRAY   .FILL #5           ; ARRAY[0] = 5.FILL #10          ; ARRAY[1] = 10.FILL #15          ; ARRAY[2] = 15

AND(按位与运算)🔗

  • 操作码0101
  • 功能:对两个操作数执行按位与操作。
  • 格式
    • 寄存器模式AND DR, SR1, SR2,其中 DR = SR1 AND SR2
    • 立即数模式AND DR, SR1, IMM5,其中 DR = SR1 AND IMM5
实际应用示例:

示例 1:清除寄存器中的某些位

假设要清除 R1 中最低的 4 位。

        AND R1, R1, #0xF0  ; R1 = R1 AND 0xF0,清除最低 4 位

示例 2:检测某个位是否为 1

检测 R2 的第 3 位(从 0 开始计数)是否为 1。

        AND R1, R2, #0x08  ; R1 = R2 AND 0x08BRz BIT_IS_ZERO    ; 如果结果为零,说明第 3 位是 0; 如果不为零,说明第 3 位是 1
BIT_IS_ZERO:; 处理第 3 位为 0 的情况

NOT(按位取反)🔄

  • 操作码1001
  • 功能:对源寄存器的内容进行按位取反。
  • 格式NOT DR, SR,其中 DR = NOT SR
实际应用示例:

示例 1:计算一个数的补码

计算一个整数的补码(取反加一)。

        NOT R1, R0         ; R1 = NOT R0ADD R1, R1, #1     ; R1 = R1 + 1,得到 R0 的补码

示例 2:实现逻辑非操作

判断 R0 是否为零,如果为零,则将 R1 置为 1,否则置为 0。

        ADD R2, R0, #0     ; 设置条件码BRz IS_ZEROAND R1, R1, #0     ; R1 = 0BR END
IS_ZERO:AND R1, R1, #0     ; 清零 R1ADD R1, R1, #1     ; R1 = 1
END:

3. 数据传输指令(Data Movement Instructions)📥📤

这些指令用于在寄存器和内存之间移动数据。

数据传输指令一览表

指令操作码 (Opcode)功能格式示例描述
LD0010直接加载LD R1, LABEL将内存中 LABEL 位置的值加载到 R1
LDI1010间接加载LDI R1, LABELLABEL 地址存储的内容作为地址加载到 R1
LDR0110基址加偏移量加载LDR R1, R2, #6R1 加载地址 R2 + 6 处的数据
LEA1110加载地址LEA R1, LABELLABEL 地址加载到 R1(仅加载地址)
ST0011直接存储ST R1, LABELR1 的内容存储到 LABEL 指定的内存位置
STI1011间接存储STI R1, LABELR1 的内容存储到 LABEL 所指的地址中的地址
STR0111基址加偏移量存储STR R1, R2, #6R1 的内容存储到地址 R2 + 6

LD(直接加载)📦

  • 操作码0010
  • 功能:从内存的指定位置加载数据到寄存器。
  • 格式LD DR, LABEL
实际应用示例:

示例:加载全局变量的值

        LD R1, NUM         ; 将 NUM 的值加载到 R1; 进行一些操作ADD R1, R1, #1     ; R1 = R1 + 1

数据段:

NUM     .FILL #10          ; 定义 NUM,初始值为 10

LDI(间接加载)🪞

  • 操作码1010
  • 功能:从内存地址中存储的地址再加载数据到寄存器。
  • 格式LDI DR, LABEL
实际应用示例:

示例:通过指针访问变量

假设有一个指针 PTR,指向一个变量 NUM。

        LDI R1, PTR        ; R1 = Memory[Memory[PTR]]

数据段:

PTR     .FILL NUM          ; PTR 存储 NUM 的地址
NUM     .FILL #20          ; NUM 的值为 20

解释:

  1. Memory[PTR] 得到 NUM 的地址。
  2. Memory[Memory[PTR]] 得到 NUM 的值,即 20。

LDR(基址加偏移量加载)📐

  • 操作码0110
  • 功能:使用基址寄存器加上偏移量计算出内存地址,从该地址加载数据到寄存器。
  • 格式LDR DR, BaseR, offset6
实际应用示例:

示例:遍历数组

        LEA R2, ARRAY      ; R2 指向数组起始地址AND R3, R3, #0     ; R3 = 0(数组索引)
LOOP:   LDR R1, R2, #0     ; R1 = ARRAY[R3]; 对 R1 进行一些操作ADD R2, R2, #1     ; R2 = R2 + 1,移动到下一个元素ADD R3, R3, #1     ; R3 = R3 + 1ADD R4, R3, #-5    ; 检查是否遍历完 5 个元素BRnzp LOOP         ; 继续循环

数据段:

ARRAY   .FILL #1.FILL #2.FILL #3.FILL #4.FILL #5

LEA(加载地址)🗺️

  • 操作码1110
  • 功能:将一个标签的地址加载到寄存器中,不访问内存。
  • 格式LEA DR, LABEL
实际应用示例:

示例:指针操作

        LEA R1, MESSAGE    ; R1 = 地址 MESSAGE; 将 MESSAGE 的地址传递给子程序JSR PRINT_STRING

数据段:

MESSAGE .STRINGZ "Hello, World!"

ST(直接存储)💾

  • 操作码0011
  • 功能:将寄存器的内容存储到指定的内存位置。
  • 格式ST SR, LABEL
实际应用示例:

示例:保存计算结果

        ; 假设 R1 中有计算结果ST R1, RESULT      ; 将 R1 的值存储到 RESULT

数据段:

RESULT  .BLKW #1           ; 为 RESULT 分配一个内存空间

STI(间接存储)🪞

  • 操作码1011
  • 功能:将寄存器的内容存储到一个内存地址所指向的内存位置。
  • 格式STI SR, LABEL
实际应用示例:

示例:通过指针修改变量的值

        STI R1, PTR        ; Memory[Memory[PTR]] = R1

数据段:

PTR     .FILL VAR          ; PTR 存储 VAR 的地址
VAR     .FILL #0           ; VAR 初始值为 0

解释:

  • 将 R1 的值存储到 VAR 中。

STR(基址加偏移量存储)📐

  • 操作码0111
  • 功能:将寄存器的内容存储到由基址寄存器加偏移量计算出的内存地址。
  • 格式STR SR, BaseR, offset6
实际应用示例:

示例:修改数组中的元素

        LEA R2, ARRAY      ; R2 指向数组起始地址ADD R3, R2, #2     ; R3 指向 ARRAY[2]ADD R1, R1, #100   ; 假设 R1 = 100STR R1, R2, #2     ; ARRAY[2] = R1,即修改 ARRAY[2] 的值为 100

数据段:

ARRAY   .FILL #10.FILL #20.FILL #30.FILL #40.FILL #50

4. 控制指令(Control Instructions)🕹️

控制指令用于改变程序的执行流程,例如跳转和子程序调用。

控制指令一览表

指令操作码 (Opcode)功能格式示例描述
BR0000条件分支BRnzp LABEL根据条件跳转到 LABEL(负、零、正条件)
JMP1100无条件跳转JMP R3跳转到 R3 寄存器中的地址
JSR0100子程序跳转(立即数模式)JSR LABEL跳转到 LABEL 并保存返回地址
JSRR0100子程序跳转(寄存器模式)JSRR R3跳转到 R3 指定的地址并保存返回地址
RET1100返回RET从子程序返回,跳转到 R7 中的地址

BR(条件分支)🚦

  • 操作码0000
  • 功能:根据条件码(N、Z、P)决定是否跳转到指定的标签。
  • 格式BRnzp LABEL
实际应用示例:

示例:实现循环

        AND R1, R1, #0     ; R1 = 0
LOOP:   ADD R1, R1, #1     ; R1 = R1 + 1ADD R2, R1, #-10   ; 检查 R1 是否等于 10BRz  END_LOOP      ; 如果 R1 == 10,跳转到 END_LOOPBRnzp LOOP         ; 否则继续循环
END_LOOP:; 循环结束后的代码

解释:

  • 使用 BRz 判断条件,当结果为零时跳出循环。

JMP(无条件跳转)🏃‍♂️

  • 操作码1100
  • 功能:无条件跳转到寄存器中存储的地址。
  • 格式JMP BaseR
实际应用示例:

示例:实现跳转表

        ; 根据 R0 的值跳转到不同的处理例程LEA R1, JUMP_TABLEADD R1, R1, R0     ; R1 = 地址偏移LDR R2, R1, #0     ; R2 = 跳转地址JMP R2             ; 跳转到对应的处理例程JUMP_TABLE:.FILL CASE0.FILL CASE1.FILL CASE2CASE0:; 处理例程 0BRnzp END_CASES
CASE1:; 处理例程 1BRnzp END_CASES
CASE2:; 处理例程 2
END_CASES:; 后续代码

JSR/JSRR(子程序跳转)🔄

  • 操作码0100
  • 功能:调用子程序,并保存返回地址。
  • 格式
    • JSR(立即数模式)JSR LABEL
    • JSRR(寄存器模式)JSRR BaseR
实际应用示例:

示例:调用子程序

        ; 主程序JSR SUM_FUNCTION   ; 调用求和函数; 继续执行SUM_FUNCTION:; 子程序开始; 假设计算 R1 + R2,结果存储在 R0ADD R0, R1, R2RET                ; 返回主程序

解释:

  • JSR 会将返回地址(下一条指令的地址)存储在 R7 中。
  • 在子程序中,使用 RET 返回调用点。

RET(返回)🔙

  • 操作码1100
  • 功能:从子程序返回到调用位置。
  • 格式RET
实际应用示例:

示例:标准子程序返回

        ; 在子程序的末尾RET                ; 返回主程序

解释:

  • RET 等价于 JMP R7,跳转到存储在 R7 中的返回地址。

5. 寻址方式(Addressing Modes)🔍

LC-3 支持多种寻址方式,用于确定操作数或目标地址的位置。

寻址方式一览表

寻址方式适用指令描述示例
直接寻址LD, ST指令直接包含了有效地址,用于从指定内存位置加载或存储数据LD R1, LABEL
间接寻址LDI, STI指令包含的地址指向另一个内存位置,实际操作地址从该内存位置获取LDI R1, LABEL
基址加偏移量寻址LDR, STR使用基址寄存器值加上一个偏移量计算出有效地址LDR R1, R2, #6
PC 相对寻址LD, ST, BR使用当前 PC 值加上偏移量计算有效地址,适用于分支和数据加载BRnzp LABEL
立即数寻址ADD, AND使用指令中的一个立即数值进行操作,不涉及内存访问ADD R1, R2, #3

直接寻址 🎯

  • 适用指令LDST

  • 描述:指令直接包含了有效地址。

  • 示例

    LD R1, DATA ; R1 = Memory[DATA]
    
实际应用示例:

示例:访问全局变量

        LD R0, COUNTER     ; 加载 COUNTER 的值到 R0ADD R0, R0, #1     ; COUNTER = COUNTER + 1ST R0, COUNTER     ; 存储更新后的 COUNTER

数据段:

COUNTER .FILL #0           ; 计数器初始值为 0

间接寻址 🪞

  • 适用指令LDISTI

  • 描述:指令包含的地址指向一个内存位置,该位置存储实际的有效地址。

  • 示例

    LDI R1, PTR ; R1 = Memory[Memory[PTR]]
    
实际应用示例:

示例:通过指针数组访问数据

        LDI R0, PTR_ARRAY  ; R0 = Memory[Memory[PTR_ARRAY]]

数据段:

PTR_ARRAY .FILL DATA_ADDR  ; PTR_ARRAY 存储 DATA_ADDR 的地址
DATA_ADDR .FILL DATA       ; DATA_ADDR 存储 DATA 的地址
DATA      .FILL #42        ; DATA 的值为 42

基址加偏移量寻址 📐

  • 适用指令LDRSTR

  • 描述:使用基址寄存器的值加上偏移量来计算有效地址。

  • 示例

    LDR R1, R2, #4 ; R1 = Memory[R2 + 4]
    
实际应用示例:

示例:访问结构体成员

假设有一个结构体,其中成员的偏移量已知。

        ; R2 指向结构体的起始地址LDR R1, R2, #OFFSET_MEMBER ; 加载成员变量到 R1

假设:

  • OFFSET_MEMBER 为成员变量在结构体中的偏移量。

PC 相对寻址 🖥️

  • 适用指令LDSTBR

  • 描述:使用当前程序计数器(PC)的值加上偏移量来计算有效地址。

  • 示例

    BRnz LOOP ; 如果条件满足,跳转到 PC + offset
    
实际应用示例:

示例:实现程序循环

        LD R1, COUNTER     ; 加载计数器
LOOP:; 执行循环体ADD R1, R1, #-1    ; 计数器减 1ST R1, COUNTER     ; 存储计数器BRp LOOP           ; 如果 R1 > 0,继续循环

数据段:

COUNTER .FILL #10          ; 计数器初始值为 10

立即数寻址 🔢

  • 适用指令ADDAND

  • 描述:操作数是指令中直接提供的一个立即数。

  • 示例

    ADD R1, R2, #7 ; R1 = R2 + 7
    
实际应用示例:

示例:初始化寄存器

        AND R0, R0, #0     ; R0 = 0ADD R0, R0, #5     ; R0 = 5

6. 总结 📝

通过对 LC-3 指令集的深入解析和 实际示例 的演示,我们了解了:

  • 操作指令用于算术和逻辑运算,能够处理寄存器和立即数。
  • 数据传输指令用于在内存和寄存器之间移动数据,支持多种寻址方式。
  • 控制指令用于改变程序的执行流程,如条件分支、循环和子程序调用。
  • 多种寻址方式提供了灵活的内存访问手段,能够高效地访问和操作数据。

💡 提示:掌握 LC-3 指令集有助于理解更复杂的计算机架构和汇编语言。通过实际的代码示例,我们可以更好地理解每条指令的用法和作用。


常用 LC-3 寄存器表

寄存器功能描述
R0-R7通用寄存器,用于数据存储和操作
PC程序计数器,指向下一条将被执行的指令
IR指令寄存器,存储当前正在执行的指令
CC条件码寄存器,存储最近一次运算结果的状态(N、Z、P)
MAR内存地址寄存器,指定内存操作的地址
MDR内存数据寄存器,存储要写入或读取的数据

感谢您的阅读!希望这篇文章对您理解 LC-3 指令集有所帮助。🚀


http://www.mrgr.cn/news/67880.html

相关文章:

  • sql server 文件和文件组介绍
  • 第8章 利用CSS制作导航菜单作业
  • 《网络是怎样连接的》学习总结-第五章
  • 解决 Redis 报错:`(error) NOAUTH Authentication required`
  • qt QHttpMultiPart详解
  • 遥测终端机RTU产品如何选型和配置
  • Mysql、Dm8达梦数据库通过脚本导出指定库所有表的结构详情信息到
  • 提交linux kernel patch流程
  • 第08章 排序ORDER BY
  • 大模型微调技术 --> LoRA 系列之 AdaLoRA
  • ABAP开发-内存管理
  • Flutter环境配置
  • 论文阅读《Structure-from-Motion Revisited》
  • Unet++改进3:添加NAMAttention注意力机制
  • 故障排查 之 单点登录跳转失败(Ingress 相关)
  • Linux系列-进程的状态
  • 【网易云插件】听首歌放松放松
  • 在数据抓取的时候,短效IP比长效IP有哪些优势?
  • 药品进销存表格制作 佳易王药店药品入库出库台账库存管理系统操作教程
  • 18-分页与遍历 - From, Size, Search_after Scroll API
  • (vue3)在Pinia Store中正确使用Vue I18n
  • 记录mkdocs+yeti生成页面左侧导航(sidebar)添加滚动条(scroll bar)方法
  • LLM训练”中的“分布式训练并行技术;分布式训练并行技术
  • 整合本地市场机会 同城小程序打造社区商圈
  • ESP32-S3 IDF以太网接口移植
  • C++之priority_queue容器