首页/计算机组成原理/指令系统/指令字长和操作码扩展 🔗 在 Obsidian 中打开
计算机组成原理 · 指令系统

指令字长和操作码扩展

重要度 ⭐⭐⭐⭐⭐指令系统操作码扩展定长编码扩展编码
速查
指令字长 = 操作码长度 + 地址码总长度。扩展操作码的核心:每减少一个地址码,操作码就多出 A 位(15/15/15 法每级保留全 1 作扩展标志)。定长译码快、哈夫曼空间最优、扩展编码是折中。

指令字长

指令字长 = 操作码长度 + 地址码总长度。

固定指令字长

  • 所有指令等长,取指简单
  • 短指令浪费空间,长指令受限制
  • 适合 RISC

可变指令字长

  • 指令长度灵活,编码效率高
  • 取指复杂,需判断指令边界
  • 适合 CISC

操作码编码方式

定长编码(固定操作码)

所有指令的操作码等长:n 位操作码 → 最多 $2^n$ 条指令。

  • 优点:译码简单、速度快
  • 缺点:灵活性差,指令总条数受限

可变长编码(哈夫曼编码)

根据指令使用频率分配操作码长度:

  • 常用指令:短操作码
  • 不常用指令:长操作码
  • 编码效率最高,但译码复杂

扩展操作码编码(等长扩展)

定长编码和可变长编码的折中方案:保留部分编码空间用于扩展,较短指令的操作码后面用特定模式表示「需要扩展」。

操作码扩展详解

基本思想

假设定长指令字 W 位、地址码每个 A 位、一条指令有 n 个地址码:

  • 三地址指令:操作码 = W − 3A 位
  • 二地址指令:操作码 = W − 2A 位
  • 一地址指令:操作码 = W − A 位
  • 零地址指令:操作码 = W 位
关键每减少一个地址码,操作码长度增加 A 位——这就是扩展的本质。

扩展方式

15/15/15 法:每级保留一个编码(如全 1)表示「继续扩展」,每级可编码的指令数 = $2^A - 1$。

8/64/512 法:第一级用 3 位(000–110)编码 7 条三地址指令,111 表示扩展;第二级用 6 位编码 64 条二地址指令……

手算示例

例 1:标准操作码扩展(15/15/15/16)

定长指令字 16 位、每个地址码 4 位,设计 15 条三地址、15 条二地址、15 条一地址、16 条零地址指令:

三地址指令:OP(4) + A1(4) + A2(4) + A3(4) = 16 位
  编码空间:0000~1110(15 种),保留 1111 用于扩展
二地址指令:1111 + OP(4) + A1(4) + A2(4) = 16 位
  编码空间:1111_0000~1111_1110(15 种),保留 1111_1111
一地址指令:1111_1111 + OP(4) + A1(4) = 16 位
  编码空间:1111_1111_0000~1111_1111_1110(15 种),保留全 1
零地址指令:1111_1111_1111 + OP(4) = 16 位
  编码空间:16 种(16 条)

验证:$15 + 15 + 15 + 16 = 61$ 条指令 ✓;操作码总编码空间 $2^4 \times 4 = 2^6 = 64$ 种。

例 2:非均匀扩展

设计 14 条三地址、31 条二地址、15 条一地址、16 条零地址指令:

三地址:0000~1101(14 种),保留 1110、1111 两个扩展前缀
二地址:[1110/1111] + OP(4) + 2×4 位
  2 个前缀 × 16 = 32 种,用 31 种,保留 1111_1111 扩展
一地址:1111_1111 + OP(4) + 1×4 位,取 15 种,保留全 1
零地址:1111_1111_1111 + OP(4),16 种

例 3:编码效率计算(哈夫曼)

A 类 50%、B 类 30%、C 类 20%:

哈夫曼编码:A: 0(1位)  B: 10(2位)  C: 11(2位)
平均长度 = 0.5×1 + 0.3×2 + 0.2×2 = 1.5 位
等长编码:2 位
效率提升 = (2 − 1.5) / 2 = 25%

例 4:给定条件求最大指令数

定长指令字 32 位、操作码 8 位、3 个地址码,每个地址码可指向 4GB 空间:

每个地址码位数 = ⌈log₂(4GB)⌉ = ⌈log₂(2^32)⌉ = 32 位
操作码(8) + 3×地址码(32) = 104 位 > 32 位!→ 放不下
改为一地址:8 + 32 = 40 位 > 32 位 → 也不行
改为寄存器型:OP(8) + R1(5) + R2(5) + R3(5) + 立即数(9) = 32 位
(假设 32 个寄存器,5 位编号)
启示地址码位数超限时,出路是「减少地址码个数」或「用寄存器代替内存地址」。

操作码扩展的约束条件

设指令字长 W 位、地址码 A 位,n 地址指令最多编码 $2^{W-nA}$ 种。

重要约束短操作码的编码不能与长操作码的前缀冲突

$$n_0 \leq 2^{W} - n_1 \cdot 2^{A} - n_2 \cdot 2^{2A} - \cdots$$

(此为简化的约束公式,实际设计需要更精细的分析)

记忆卡片

操作码扩展的核心思想?
减少地址码个数 → 多出的位给操作码用 → 编码更多指令。记忆:少一个地址多一截编码空间。
15/15/15 扩展法怎么操作?
每级保留全 1 编码做「扩展标志」,每级可编码 $2^A - 1$ 条指令。记忆:每级留一张通行证给下一级。
定长 vs 哈夫曼编码优劣?
定长译码快但空间利用率低;哈夫曼空间最优但译码慢。记忆:定长=简单粗暴,哈夫曼=精打细算。
指令字长与各部分关系?
指令字长 = 操作码长度 + 各地址码长度之和。记忆:一个蛋糕切成操作码和地址码。

交互动画 · 操作码扩展阶梯

16 位指令字 · 每格 4 位 · 红 = 扩展前缀(全 1)· 橙 = 操作码 · 绿 = 地址码
点击层级按钮,观察扩展前缀如何逐级「吃掉」地址码
15/15/15/16 法 · 共 61 条指令
示意图:四个层级纵向排列,每级从「全 1 扩展前缀 + 更多操作码位」构成;红色块为上一级保留的扩展标志。

相关知识点

instruction-format instruction-set-design

↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。