Skip to content

第四章:指令系统与寻址方式

指令系统是计算机硬件与软件之间的接口,定义了处理器能够执行的所有指令的集合。它是计算机体系结构设计的核心,直接影响着计算机的性能、复杂度和编程效率。

4.1 指令系统概述

4.1.1 指令的定义与作用

**指令(Instruction)**是计算机能够识别和执行的基本操作命令。每条指令都包含两个基本部分:

  • 操作码(Opcode):指定要执行的操作类型
  • 操作数(Operand):指定操作的对象或数据

生动例子:想象指令就像烹饪食谱

  • 操作码 = 烹饪方法("炒"、"煮"、"蒸")
  • 操作数 = 食材和调料("鸡蛋"、"西红柿"、"盐")
  • 完整指令 = "炒鸡蛋"(操作码:炒,操作数:鸡蛋)

4.1.2 指令系统的设计要求

  1. 完备性:能够完成所有必要的计算任务
  2. 规整性:指令格式统一,便于硬件实现
  3. 高效性:常用操作用简单指令实现
  4. 兼容性:保持向后兼容,支持软件移植

4.2 指令格式

4.2.1 基本指令格式

指令格式定义了指令中各个字段的布局和含义。常见的指令格式包括:

三地址指令格式

| 操作码 | 目标操作数 | 源操作数1 | 源操作数2 |
|   OP   |     D      |     S1    |     S2    |

例子ADD R1, R2, R3 (R1 = R2 + R3)

  • 操作码:ADD(加法)
  • 目标操作数:R1(结果存储位置)
  • 源操作数1:R2(第一个加数)
  • 源操作数2:R3(第二个加数)

二地址指令格式

| 操作码 | 目标操作数 | 源操作数 |
|   OP   |     D      |     S    |

例子ADD R1, R2 (R1 = R1 + R2)

  • 操作码:ADD(加法)
  • 目标操作数:R1(既是源又是目标)
  • 源操作数:R2(加数)

一地址指令格式

| 操作码 | 操作数 |
|   OP   |   A    |

例子LOAD A (将地址A的内容加载到累加器)

  • 操作码:LOAD(加载)
  • 操作数:A(内存地址)

4.2.2 指令长度分类

定长指令

所有指令长度相同,便于硬件实现,但可能浪费存储空间。

例子:MIPS指令系统

  • 所有指令都是32位
  • 便于流水线实现
  • 指令译码简单

变长指令

指令长度可变,节省存储空间,但硬件实现复杂。

例子:x86指令系统

  • 指令长度从1字节到15字节不等
  • 节省存储空间
  • 需要复杂的指令译码器

4.3 操作码与操作数

4.3.1 操作码设计

操作码编码方式

定长操作码

  • 所有操作码长度相同
  • 译码简单,但可能浪费编码空间
  • 例子:4位操作码可表示16种操作

变长操作码

  • 操作码长度可变
  • 节省编码空间,但译码复杂
  • 例子:Huffman编码

操作码扩展技术

操作码扩展允许在指令中嵌入更多信息:

| 操作码 | 扩展位 | 操作数 |
|   OP   |   EXT  |   A    |

例子:条件分支指令

  • 基本操作码:BRANCH
  • 扩展位:000(无条件)、001(等于)、010(不等于)等

4.3.2 操作数类型

立即数(Immediate)

指令中直接包含的常数。

例子ADD R1, R2, #5 (R1 = R2 + 5)

  • #5是立即数,直接嵌入指令中

寄存器操作数

指定CPU寄存器作为操作数。

例子ADD R1, R2, R3 (R1 = R2 + R3)

  • R1、R2、R3都是寄存器操作数

内存操作数

指定内存地址作为操作数。

例子LOAD R1, [0x1000] (将地址0x1000的内容加载到R1)

  • [0x1000]是内存操作数

4.4 寻址方式

寻址方式决定了如何计算操作数的有效地址。不同的寻址方式提供了灵活性和效率的平衡。

4.4.1 立即寻址(Immediate Addressing)

操作数直接包含在指令中。

格式指令 寄存器, 立即数

例子MOV R1, #42

  • 将立即数42直接存入寄存器R1
  • 有效地址 = 指令中的立即数

特点

  • 优点:执行速度快,无需访问内存
  • 缺点:操作数范围受指令长度限制

4.4.2 直接寻址(Direct Addressing)

指令中直接给出操作数的内存地址。

格式指令 寄存器, [地址]

例子LOAD R1, [0x1000]

  • 将地址0x1000的内容加载到R1
  • 有效地址 = 指令中的地址

生动例子:就像直接告诉邮递员"去123号大街取包裹"

4.4.3 间接寻址(Indirect Addressing)

指令中给出的是操作数地址的地址。

格式指令 寄存器, [[地址]]

例子LOAD R1, [[0x1000]]

  • 先从0x1000读取地址,再访问该地址的内容
  • 有效地址 = 内存[指令中的地址]

生动例子:就像"去123号大街,那里有个纸条写着真正的地址"

4.4.4 寄存器寻址(Register Addressing)

操作数在CPU寄存器中。

格式指令 目标寄存器, 源寄存器

例子ADD R1, R2, R3

  • R1 = R2 + R3
  • 有效地址 = 寄存器编号

特点

  • 优点:访问速度最快
  • 缺点:寄存器数量有限

4.4.5 寄存器间接寻址(Register Indirect Addressing)

寄存器中存放的是操作数的地址。

格式指令 寄存器, [寄存器]

例子LOAD R1, [R2]

  • 将R2指向的内存内容加载到R1
  • 有效地址 = 寄存器内容

4.4.6 基址寻址(Base Addressing)

有效地址 = 基址寄存器内容 + 偏移量

格式指令 寄存器, [基址寄存器 + 偏移量]

例子LOAD R1, [R2 + 8]

  • 有效地址 = R2 + 8
  • 常用于数组访问

生动例子:就像"从你家(基址)往前走8步"

4.4.7 变址寻址(Indexed Addressing)

有效地址 = 基址 + 变址寄存器内容

格式指令 寄存器, [基址 + 变址寄存器]

例子LOAD R1, [0x1000 + R2]

  • 有效地址 = 0x1000 + R2
  • 常用于循环中的数组访问

4.4.8 相对寻址(Relative Addressing)

有效地址 = 程序计数器 + 偏移量

格式指令 目标地址

例子BRANCH +100

  • 跳转到当前指令地址 + 100的位置
  • 常用于条件分支

生动例子:就像"从当前位置向前跳100步"

4.5 RISC与CISC指令系统

4.5.1 CISC(Complex Instruction Set Computer)

特点

  • 复杂指令:一条指令可以完成复杂操作
  • 变长指令:指令长度不固定
  • 多种寻址方式:支持多种寻址方式
  • 微程序控制:用微程序实现复杂指令

典型例子:x86指令系统

复杂指令例子

text
MOVSB    ; 移动一个字节(字符串操作)
REP MOVSB ; 重复移动多个字节

一条指令完成复杂操作

  • 自动递增源和目的地址
  • 重复执行指定次数
  • 设置条件标志

CISC的优势

  1. 编程效率高:复杂操作用一条指令完成
  2. 代码密度高:程序占用内存少
  3. 向后兼容:保持软件兼容性

CISC的劣势

  1. 硬件复杂:需要复杂的指令译码器
  2. 执行效率低:复杂指令执行时间长
  3. 流水线困难:指令长度不等,难以流水线化

4.5.2 RISC(Reduced Instruction Set Computer)

特点

  • 简单指令:每条指令只完成一个基本操作
  • 定长指令:所有指令长度相同
  • 寄存器操作:大量使用寄存器
  • 硬连线控制:用硬件直接实现指令

典型例子:MIPS指令系统

简单指令例子

text
ADD $t0, $t1, $t2    ; $t0 = $t1 + $t2
LW  $t0, 4($t1)      ; $t0 = memory[$t1 + 4]
SW  $t0, 8($t1)      ; memory[$t1 + 8] = $t0

指令特点

  • 所有指令都是32位
  • 只有三种基本指令格式
  • 大量使用寄存器

RISC的优势

  1. 硬件简单:指令译码器简单
  2. 执行效率高:简单指令执行快
  3. 易于流水线:定长指令便于流水线实现
  4. 功耗低:硬件简单,功耗低

RISC的劣势

  1. 代码密度低:需要更多指令完成复杂操作
  2. 编程复杂:程序员需要写更多指令

4.5.3 RISC vs CISC 对比

特性RISCCISC
指令数量少(几十条)多(几百条)
指令长度定长变长
寻址方式
寄存器数量
控制方式硬连线微程序
代码密度
硬件复杂度
执行效率
流水线容易困难

4.6 指令类型

4.6.1 数据传送指令

负责在寄存器、内存之间传送数据。

例子

text
MOV R1, R2        ; 寄存器间传送
LOAD R1, [0x1000] ; 内存到寄存器
STORE R1, [0x1000]; 寄存器到内存

4.6.2 算术运算指令

执行基本的算术运算。

例子

text
ADD R1, R2, R3    ; 加法
SUB R1, R2, R3    ; 减法
MUL R1, R2, R3    ; 乘法
DIV R1, R2, R3    ; 除法

4.6.3 逻辑运算指令

执行逻辑运算。

例子

text
AND R1, R2, R3    ; 逻辑与
OR  R1, R2, R3    ; 逻辑或
XOR R1, R2, R3    ; 逻辑异或
NOT R1, R2        ; 逻辑非

4.6.4 移位指令

执行数据的移位操作。

例子

text
SHL R1, R2, 2     ; 左移2位
SHR R1, R2, 2     ; 右移2位
ROL R1, R2, 1     ; 循环左移1位

4.6.5 比较指令

比较两个操作数的大小。

例子

text
CMP R1, R2        ; 比较R1和R2
TEST R1, R2       ; 测试R1和R2的位

4.6.6 分支指令

改变程序执行顺序。

例子

text
JMP label         ; 无条件跳转
JE  label         ; 相等时跳转
JNE label         ; 不等时跳转
CALL function     ; 调用函数
RET               ; 返回

4.7 指令执行过程

4.7.1 指令执行的基本步骤

  1. 取指令(Fetch):从内存中取出指令
  2. 译码(Decode):分析指令的操作码和操作数
  3. 执行(Execute):执行指令指定的操作
  4. 写回(Write Back):将结果写回目标位置

4.7.2 指令执行示例

例子:执行指令 ADD R1, R2, R3

  1. 取指令

    • 从程序计数器指向的地址取出指令
    • 指令内容:操作码(ADD) + 目标寄存器(R1) + 源寄存器1(R2) + 源寄存器2(R3)
  2. 译码

    • 识别操作码为ADD
    • 识别操作数为R1、R2、R3
    • 确定需要执行加法运算
  3. 执行

    • 从R2和R3读取数据
    • 执行加法运算:R2 + R3
    • 产生结果
  4. 写回

    • 将结果写入目标寄存器R1
    • 更新程序计数器指向下一条指令

4.8 指令系统的设计考虑

4.8.1 指令格式设计原则

  1. 规整性:指令格式应该规整统一
  2. 扩展性:为未来扩展预留空间
  3. 效率性:常用操作用简单指令实现
  4. 兼容性:保持向后兼容

4.8.2 操作码分配策略

  1. 频率分配:常用操作分配短操作码
  2. 功能分组:相关操作分配相近操作码
  3. 扩展预留:为未来扩展预留操作码空间

4.8.3 寻址方式选择

  1. 常用优先:常用寻址方式优先支持
  2. 硬件平衡:寻址方式复杂度与硬件成本平衡
  3. 编程便利:支持程序员常用的寻址模式

4.9 现代指令系统发展趋势

4.9.1 向量指令

支持对多个数据同时进行相同操作。

例子:SIMD指令

text
VADD V1, V2, V3   ; 向量加法,同时处理多个数据

4.9.2 多媒体指令

专门为多媒体应用设计的指令。

例子:MMX、SSE、AVX指令集

  • 支持图像、音频、视频处理
  • 提高多媒体应用性能

4.9.3 安全指令

支持硬件级安全功能的指令。

例子

  • 加密解密指令
  • 内存保护指令
  • 安全启动指令

4.10 总结

指令系统是计算机体系结构的核心,它定义了硬件与软件的接口。本章介绍了:

  1. 指令格式:三地址、二地址、一地址指令格式
  2. 操作码与操作数:操作码编码和操作数类型
  3. 寻址方式:立即、直接、间接、寄存器等寻址方式
  4. RISC与CISC:两种不同的指令系统设计哲学
  5. 指令类型:数据传送、算术、逻辑、分支等指令
  6. 指令执行:取指、译码、执行、写回的基本过程

理解指令系统对于理解计算机工作原理和进行系统设计具有重要意义。现代处理器在保持指令系统兼容性的同时,不断引入新的指令类型和功能,以适应不断发展的应用需求。


外部参考