第4章 指令系统
第4章 指令系统¶
既出选择题也结合其他章出综合题。核心是各种寻址方式的有效地址计算(尤其三种偏移寻址)、扩展操作码设计、CISC 与 RISC 对比。2022 年新增的机器级表示(读汇编代码)历年多次出现,难度大但有套路。
b_153_3【知识树】第4章骨架¶
- 指令格式
- 操作码 + 地址码;定长指令字 vs 变长指令字
- 零/一/二/三地址指令及其访存次数
- 定长操作码 vs 扩展操作码
- 指令类型:数据传送 / 算逻运算 / 移位 / 顺序控制 / I/O / CPU 控制
- 寻址方式
- 指令寻址:顺序寻址(PC 自增)、跳跃寻址(绝对/相对)
- 数据寻址十种:隐含 / 立即 / 直接 / 间接 / 寄存器 / 寄存器间接 / 相对 / 基址 / 变址 / 堆栈
- 三种偏移寻址:相对、基址、变址
- 机器级代码表示
- x86 寄存器与常用指令
- 选择结构、循环结构、过程调用的机器级表示
- CISC 与 RISC
b_153_0;PDF 第 153 页 · b_153_44.1 指令格式¶
ISA 规定了哪四方面内容? ★2考¶
- 指令格式、寻址方式、操作类型,以及各操作所需操作数的个数、类型和寻址约束
- 操作数的数据类型,以及按大端还是小端存放
- 程序可访问的寄存器编号、数量和位数,存储空间大小及编址方式
- 程序员可见的控制状态,如程序计数器、条件码的定义与行为
★ 考过 2022、2025
b_153_9指令字长由什么决定?定长和变长各有什么好处?¶
指令字长取决于操作码长度、地址码长度及地址码个数。 - 定长指令字结构:所有指令字长相等 → 取指和译码简单,有利于流水线实现 - 变长指令字结构:指令字长随功能而异
⚠️ 主存按字节编址时,指令字长通常是字节的整数倍。
b_154_7四种地址格式的指令各需要几次访存? ★1考¶
(设地址码均为主存地址)
- 零地址:无操作数指令(空操作、停机、关中断)或堆栈运算指令
- 一地址:
- 若为 OP(A₁)→A₁,需3 次访存(取指 1 + 取数 1 + 写回主存 1)
- 若为 (ACC)OP(A₁)→ACC 且结果只留在 ACC,通常是2 次访存(取指 1 + 取主存操作数 1)
- 二地址:(A₁)OP(A₂)→A₁,4 次访存(取指 1 + 取数 2 + 存结果 1)
- 三地址:(A₁)OP(A₂)→A₃,4 次访存(同上)
⚠️ 上述数字依赖“地址码都是主存地址”及具体语义;寄存器操作数、无需写回或堆栈隐含操作数都会改变访存次数。
★ 考过 2015
b_154_9定长操作码最多支持多少条指令? ★1考¶
n 位操作码字段最多表示 2ⁿ 条指令。 好处是简化硬件设计、提高译码速度,32 位及更长字长的系统常用。
★ 考过 2015
b_155_7设计扩展操作码必须遵守哪两条规则? ★3考¶
- 短操作码不能是长操作码的前缀(即短码不能与长码的前面部分相同)
- 各指令的操作码一定不能重复
另外一条设计原则:使用频率高的指令分配短操作码,频率低的分配长操作码,以减少译码时间。
★ 考过 2017、2021、2022
💡 记忆法:"短码不当长码的头" —— 否则译码时会提前误判。
b_155_10扩展操作码的经典算例是什么样的?¶
16 位指令字,4 位基本操作码 + 3 个 4 位地址字段: - 三地址指令:用 0000~1110 共 15 条,留 1111 作扩展窗口 - 二地址指令:用 1111 0000~1111 1110 共 15 条,留 1111 1111 继续扩展 - 一地址指令:同理 15 条,留 1111 1111 1111 - 零地址指令:16 条
⚠️ 每层都要留一个码字作为下一层的扩展窗口,所以每层是 15 条而不是 16 条(最后一层例外)。
b_155_9;PDF 第 155 页 · b_155_13【做题模板】扩展操作码怎样用前缀树数槽位?¶
- 从最短操作码层画一棵前缀树,每个码字是一条路径。
- 已分配给短指令的叶结点必须封死,不能再向下扩展;否则短码会成为长码前缀。
- 每保留一个未用短码,就能在下一层展开出 \(2^k\) 个新槽位(\(k\) 为本次新增位数)。
- 逐层扣除已分配指令,最后一层无须再为下一层留窗口。
- 用 Kraft 条件或逐层槽位数做反查,确认没有重码或前缀冲突。
高频指令放短码只是优化原则;“总位数必须是 8 的倍数”仅在题设采用按字节取指/编码时成立,不是 ISA 通则。
b_155_10;PDF 第 155 页 · b_155_13调用指令和转移指令的根本区别? ★1考¶
调用指令会保存下一条指令的地址(返回地址),以便子程序结束后返回主程序;转移指令不返回。
另外:无条件转移任何情况下都跳;条件转移仅在条件满足时跳,转移条件通常是某个标志位或多个标志位的组合。
★ 考过 2019
b_156_104.2 指令寻址¶
PC 自增的大小由什么决定? ★4考¶
由编址方式和指令字长共同决定。 现代计算机按字节编址时: - 指令字长 16 位(2 字节)→ (PC) + 2 - 指令字长 32 位(4 字节)→ (PC) + 4
★ 考过 2013、2014、2019、2023
b_161_11跳跃寻址的两种方式?¶
- 绝对转移:地址码直接给出目标地址
- 相对转移:地址码给出相对于当前 PC 值的偏移量
⚠️ 无论哪种,转移指令的执行结果都是修改 PC 的值。
b_161_8;PDF 第 161 页 · b_161_14形式地址的位数分别限制了什么? ★2考¶
看是哪种寻址方式: - 立即寻址 → 形式地址位数决定操作数的取值范围 - 直接寻址 → 决定可寻址的存储空间大小 - 寄存器寻址 → 决定通用寄存器的最大数量 - 寄存器间接寻址 → 由寄存器的位数决定可寻址空间大小
★ 考过 2020、2023
b_161_184.3 数据寻址方式(本章计算核心)¶
八种显式数据寻址方式的有效地址和访存次数?(主表)¶
(访存次数不含取本条指令) | 寻址方式 | 有效地址 | 访存次数 | |---|---|---| | 立即寻址 | A 即是操作数 | 0 | | 直接寻址 | EA = A | 1 | | 一次间接寻址 | EA = (A) | 2 | | 寄存器寻址 | EA = Rᵢ | 0 | | 寄存器间接寻址 | EA = (Rᵢ) | 1 | | 相对寻址 | EA = (PC) + A | 1 | | 基址寻址 | EA = (BR) + A | 1 | | 变址寻址 | EA = (IX) + A | 1 |
💡 记忆法:"立即和寄存器不访存,一次间址访两次,其余都一次"。
⚠️ 本表只列 8 种显式给出地址/寄存器字段的方式。若按本章“十种数据寻址”口径,还要加: - 隐含寻址:操作数地址由操作码或专用寄存器隐含 - 堆栈寻址:操作数由 SP 指示的栈顶隐含
b_165_9立即寻址的优缺点? ★1考¶
形式地址字段直接存放操作数本身(立即数,通常用补码表示),用 # 标识。 - 优点:执行阶段无须访问存储器,速度最快 - 缺点:立即数大小受形式地址字段位数限制,寻址范围非常有限
★ 考过 2023
b_162_11直接寻址的寻址范围怎么算? ★2考¶
EA = A,形式地址就是操作数真实地址。若形式地址占 24 位,则寻址范围为 2²⁴ = 16M。 - 优点:实现简单,执行阶段只访存一次 - 缺点:寻址范围受形式地址位数限制,且地址固定难以动态修改
★ 考过 2010、2021
b_162_16间接寻址为什么能扩大寻址范围? ★1考¶
EA = (A) —— 形式地址指向一个主存单元,该单元里存的才是操作数的有效地址。
因为有效地址的位数由存储字长决定,通常大于形式地址 A 的位数,所以能扩大寻址范围,还支持地址动态生成(指针、转移表)。代价是一次间址要 2 次访存。
★ 考过 2016
b_163_3寄存器编号位数和寄存器数量什么关系? ★2考¶
寄存器编号位数 = log₂(寄存器数量)。 例:CPU 有 32 个通用寄存器 → 编号需 5 位。
寄存器寻址(EA = Rᵢ)的优点:执行阶段无须访存,速度快;地址码位数少,有助于缩短指令字长。
★ 考过 2022、2024
b_163_10寄存器间接寻址相比另两种有什么取舍? ★1考¶
EA = (Rᵢ) —— 寄存器里存的是操作数所在主存单元的地址。 - 相比间接寻址:执行阶段只需一次访存(间接寻址要两次),开销更小 - 相比寄存器寻址:多了一次主存访问 - 寻址范围不受形式地址位数限制
★ 考过 2010
b_163_15相对寻址怎么算?陷阱在哪? ★6考¶
EA = (PC) + A
⚠️ 最大的坑:这里的 PC 是取指完成后自动更新的值(指向下一条指令),不是当前指令地址!
经典算例:按字节编址、指令长 2B,转移指令位于 1000H,形式地址 A = 0005H → 取指后 PC = 1002H → 目标地址 = 1002H + 0005H = 1007H(不是 1005H)
优点:目标地址相对当前指令位置偏移,程序可在内存任意浮动,便于重定位和代码共享。
★ 考过 2009、2010、2013、2014、2019、2023 —— 本章最高频
三步法:① 先确定题设所用的取指后 PC;② 把位移 \(A\) 按规定做符号扩展;③ 若 ISA 规定位移以字/半字为单位,再先左移缩放后相加。
💡 记忆法:"先定 PC,再扩展,最后按单位缩放"。是否缩放、缩放几位由 ISA/题设决定。
b_163_24基址寻址的 EA 和特点? ★1考¶
EA = (BR) + A - 基址寄存器 BR 的内容由操作系统设定,程序执行期间保持不变(作基地址) - 形式地址 A 作偏移量,由用户程序指定、可变 - 优点:扩大寻址范围(BR 位数通常大于 A)、简化编程(用户不必关心程序在主存的具体位置),利于多道程序和浮动程序 - 缺点:形式地址 A 位数较短,限制了偏移量范围
★ 考过 2019
b_164_7变址寻址的 EA 和典型用途? ★5考¶
EA = (IX) + A - 变址寄存器 IX 面向用户,其内容(偏移量)可在程序执行中动态修改 - 形式地址 A(基地址)保持不变 - 典型用途:处理数组、编写循环程序
算例:数组 B 首地址 1000H 存在 A 中,元素占 4B,访问 B[3] → IX 置为 0CH(3×4=12)→ EA = 0CH + 1000H = 100CH
★ 考过 2013、2016、2017、2018、2024
b_164_0基址寻址和变址寻址的本质区别? ★3考¶
两者都是"寄存器内容 + 形式地址",但分工完全相反: - 基址寻址面向系统:BR 由操作系统设定、运行时不可变,A 是可变的偏移量;用于多道程序和存储分配 - 变址寻址面向用户:IX 由用户程序动态调整,A 是固定的基地址;用于灵活的数据访问
★ 考过 2017、2018、2024
💡 记忆法:"基址系统定、变址用户改" —— 谁在变就看名字:变址的"变"在寄存器上。
b_165_0哪三种寻址方式属于偏移寻址? ★1考¶
相对寻址、基址寻址、变址寻址。 共同特点是通过某个寄存器的值与形式地址相加来确定有效地址,区别只在于用的是哪个寄存器(PC / BR / IX)。
★ 考过 2011
b_165_3堆栈寻址的两种实现?¶
- 硬堆栈:由高速寄存器构成,成本高、容量小
- 软堆栈:从主存划出一段区域实现,更经济实用
栈顶地址由堆栈指针 SP 给出。采用堆栈结构的机器中,多数指令表面上表现为无操作数形式,因为操作数地址由 SP 隐含指定。
b_165_54.4 x86 汇编基础¶
x86 有哪 8 个 32 位通用寄存器?各自的角色?¶
- EAX 累加器、EBX 基地址寄存器、ECX 计数寄存器、EDX 数据寄存器
- ESI / EDI 变址寄存器
- EBP 堆栈基指针、ESP 堆栈顶指针
⚠️ 除 EBP 和 ESP 外,其余通用寄存器用途比较灵活。EAX~EDX 的低 16 位可作 AX~DX 用,AX 又可拆成 AH / AL 两个 8 位寄存器。
b_177_5mov 指令有什么硬性限制? ★1考¶
两个操作数不能同时为内存 —— mov 不能直接从内存复制到内存。若需内存间复制,必须先加载到寄存器,再从寄存器写入目标内存。
★ 考过 2012
b_178_3push 和 pop 对 ESP 做什么?¶
- 在本书采用的 32 位 x86、32 位操作数示例中,push 先将 ESP 减 4,再写入;pop 先读出,再将 ESP 加 4
⚠️ 并非所有 x86 模式和操作数大小都固定变化 4B;实际对 SP/ESP/RSP 的改变量由模式和操作数大小决定。
💡 记忆法:"压栈先减后放,出栈先取后加",栈往低地址长。
b_178_4;PDF 第 178 页 · b_178_84.5 x86 常用指令¶
mul 和 imul 的溢出判据不同在哪?¶
- mul(无符号乘):仅单操作数格式,被乘数隐含在 eax,乘积放在 edx:eax。edx ≠ 0 表示结果超出 32 位 → 置 CF = 1、OF = 1
- imul(有符号乘):支持双操作数和三操作数格式,结果溢出时同样置 CF = 1、OF = 1
⚠️ 判据口径:无符号乘法以 CF 判断溢出,有符号乘法以 OF 为准。
b_178_19idiv 的被除数在哪?商和余数放哪?¶
- 指令只指定除数
- 被除数 = edx:eax 组成的 64 位数(edx 高 32 位、eax 低 32 位)
- 执行后:商存入 eax,余数存入 edx
div 与 idiv 格式完全一致,只是对操作数的解释不同(无符号/有符号)。
💡 记忆法:"除法进去 edx:eax,出来商在 eax、余在 edx"。
b_179_1两个常见的位运算技巧?¶
and eax, 0fH→ 把 eax 的高 28 位置 0、低 4 位保留(提取低位)xor edx, edx→ 把 edx 清零(比 mov edx,0 更快,是编译器常用写法)
b_179_6cmp 和 test 的区别?¶
- cmp:执行减法运算但不保存结果,仅设置标志位(相当于 sub)
- test:执行按位与运算但不保存结果,仅更新标志位、特别是 ZF(相当于 and)
典型搭配:
- cmp eax, ebx + jle done → 比较后条件跳转
- test eax, eax + jz xxx → 测试 eax 是否为零(自己和自己与,结果为 0 说明 eax 为 0)
★ 考过 2013
b_180_8call 和 ret 各做了什么? ★1考¶
- call:将下一条指令的地址(返回地址)压入栈,然后转移到 label 处执行
- ret:从栈顶弹出返回地址,并转移到该地址继续执行
这两条是函数调用机制的核心。x86 用 EIP(指令指针寄存器,相当于 PC)指示当前指令地址,EIP 不能直接访问,只能通过控制流指令修改。
★ 考过 2019
b_180_15AT&T 格式和 Intel 格式有哪六点区别?¶
统考用 Intel 格式,但要能读懂 AT&T:
- 大小写:AT&T 必须小写,Intel 不敏感
- 操作数顺序:AT&T 是"源, 目的";Intel 是"目的, 源" ← 最容易搞反
- 前缀:AT&T 寄存器加 %、立即数加 $;Intel 都不加
- 内存寻址符号:AT&T 用圆括号 ();Intel 用方括号 []
- 复杂寻址:AT&T disp(base, index, scale);Intel [base + index*scale + disp]
- 操作数长度:AT&T 在助记符后加后缀 b/w/l;Intel 用 byte ptr / word ptr / dword ptr
⚠️ x86 里 word(字)始终表示 16 位(因为 32/64 位都是从 16 位扩展来的)。
💡 记忆法:"AT&T 源在前,Intel 目的在前" —— Intel 像赋值语句 目的 = 源。
b_180_20mov 和 lea 的区别?¶
- mov:复制源操作数的值到目的操作数;可以是立即数→寄存器、寄存器→寄存器或寄存器↔内存(但不能两个操作数同时为内存)
- lea:把有效地址本身加载到寄存器,不访问内存
例:lea eax, [edx+eax*2+8] → R[edx] + R[eax]×2 + 8 → R[eax](只算地址不取数)。
b_181_34.6 选择与循环的机器级表示¶
哪些指令会设置条件码?¶
- 很多算术逻辑运算指令(如 add、sub、imul、or、and、shl、inc、dec、sal)会按各自规则更新部分条件码
- cmp 和 test 专门用于设置条件码,执行运算但不保存结果
常用条件码:CF、ZF、SF、OF。
⚠️ x86 的 NOT 不影响任何标志位;不同逻辑/移位指令更新哪些标志也不完全相同,不能把“自动设置全部条件码”当通则。
b_181_8if-else 翻译成 goto 形式的固定套路?¶
t = test_expr;
if (!t) goto false; // 条件为假跳到假分支
then_statement
goto done; // 真分支执行完跳过假分支
false:
else_statement
done:
⚠️ 关键点:编译后先判断"假"的情况并跳转,真分支紧跟在判断之后。
b_181_12指针比较为什么用 jbe 而不是 jle?¶
在本题给定的目标代码中,编译器用 jbe,说明机器级比较采用了无符号条件码。C 语言层面,两个指针只有在指向同一数组对象(或其尾后位置)时做关系比较才有标准定义;不能据此推出“任意 C 指针都按无符号整数比较”。
⚠️ 这是汇编阅读题的常见陷阱:看到 jbe/ja/jb 说明操作数按无符号解释,看到 jle/jg/jl 说明按有符号解释。
b_182_0三种循环编译后统一变成什么形式? ★4考¶
为了讲清控制流,可把 while、for 等价改写成带标签和条件跳转的 do-while/跳转形式;实际编译器可因优化级别、体系结构和分支布局生成多种等价控制流,并非“编译器眼里只有 do-while”。
-
do-while(后测试):循环体至少执行一次
-
while(前测试):加一个前置判断
-
for:先转成 while,
init_expr只执行一次,update_expr放在循环体之后
★ 考过 2014、2017、2019、2023
💡 记忆法:"编译器眼里只有 do-while" —— while 就是前面加个判断跳过,for 就是 while 加初始化和更新。
b_182_64.7 过程调用的机器级表示¶
过程调用的六个步骤?¶
设 P 调用 Q: - ① P 将入口参数放到 Q 能访问的位置 - ② P 执行 call:把返回地址(call 的下一条指令地址)压栈,转移到 Q - ③ Q 建立自己的栈帧,为局部变量分配空间,必要时保存寄存器 - ④ Q 执行主体代码 - ⑤ Q 把返回结果放到约定位置(EAX),释放局部变量空间,恢复保存的寄存器 - ⑥ Q 执行 ret:弹出返回地址,转移回 P
b_184_5哪些寄存器是调用者保存?哪些是被调用者保存?¶
- 调用者保存寄存器:EAX、ECX、EDX
- 若 P 希望调用后仍使用这些寄存器的值,P 必须在调用前自行保存(压栈),返回后恢复
- 被调用者保存寄存器:EBX、ESI、EDI
- 若 Q 需要使用它们,Q 必须在使用前保存到栈,返回前恢复
💡 记忆法:"AX/CX/DX 归调用者管,BX/SI/DI 归被调用者管" —— 前三个是"干活寄存器",随时可能被覆盖。
b_184_7EBP 和 ESP 在栈帧中各起什么作用?¶
- EBP(基址指针):指向当前栈帧的基址(保存旧 EBP 的位置),在当前过程执行期间保持不变 → 便于用固定偏移访问参数和局部变量
- ESP(栈指针):始终指向当前栈顶,随入栈出栈动态变化
⚠️ 栈从高地址向低地址增长。 参数位于 [ebp+8]、[ebp+12]…(正偏移),局部变量位于 [ebp-4]、[ebp-8]…(负偏移)。
💡 记忆法:"参数在上(正偏移),局部变量在下(负偏移),中间隔着旧 EBP 和返回地址"。
b_184_4;PDF 第 184 页 · b_184_10过程的机器级代码分哪三部分?¶
- 准备阶段:
push ebp(保存调用者的 EBP)+mov ebp, esp(建立新栈帧) - 过程体:实际功能代码
- 结束阶段:
pop ebp(恢复调用者 EBP)+ret(弹出返回地址跳回)
b_186_3;PDF 第 186 页 · b_186_4leave 指令等价于哪两条指令?¶
执行完后 ESP 正好指向返回地址,ret 就能取出它跳回去。
b_185_9栈帧大小的对齐要求是什么?¶
在本书给定的 ABI、编译选项和代码生成示例中,GCC 为满足调用点的 16B 栈对齐约定加入填充。
算例:caller 实际用了 4(旧 EBP)+ 12(三个局部变量)+ 8(两个参数)+ 4(返回地址)= 28 字节 → 但最终分配 32 字节,多出的 4 字节是对齐填充。
⚠️ 这不是“所有 GCC、所有架构、每个函数栈帧本身都必须是 16B 倍数”的全局语法规则;要按目标 ABI、模式和调用点要求分析。
b_185_0参数入栈的顺序是怎样的?¶
左参数位于较低地址,右参数位于较高地址。
例:调用 add(temp1, temp2) 时,先把 temp2(右)放 [esp+4],再把 temp1(左)放 [esp]。所以在被调用者里,[ebp+8] 是第一个参数、[ebp+12] 是第二个参数。
b_185_0;PDF 第 185 页 · b_185_1为什么汇编里看不到加法指令却完成了加法?¶
因为编译器用 lea 指令代替 add:lea eax, [edx+eax] 实际执行 R[edx] + R[eax] → R[eax]。
lea 本意是算有效地址,但它的地址计算本身就是加法和乘法,所以常被编译器借用来做算术运算(且不影响标志位)。
b_186_04.8 CISC 与 RISC¶
CISC 的七个特点? ★1考¶
- 指令系统庞大复杂,指令数量通常超过 200 条
- 指令长度不固定,指令格式和寻址方式种类繁多
- 多数指令均可直接访问内存
- 各类指令的使用频率差异显著
- 指令执行时间相差较大,大多数指令需多个时钟周期
- 控制器多采用微程序控制
- 难以通过优化编译生成高效目标代码
★ 考过 2017
b_196_2RISC 的七个特点? ★2考¶
- 只选使用频率最高的简单指令,复杂功能由多条简单指令组合
- 指令长度固定,指令格式和寻址方式种类少
- 仅 LOAD/STORE 指令可访问内存,其余运算都在寄存器间进行
- CPU 中配备大量通用寄存器
- 指令规整、易于流水;经典教材模型常把理想流水吞吐率写成接近 1 CPI,不等于每条指令的实际延迟都只有一个周期
- 以硬布线控制为主,极少或不用微程序控制
- 高度依赖编译器优化
★ 考过 2009、2025
b_196_880/20 规律说的是什么?¶
对传统 CISC 指令系统的统计表明:约 80% 的程序执行仅依赖于 20% 的简单指令,其余 80% 的复杂指令使用频率极低。
这个观察正是 RISC 诞生的直接依据 —— 只保留高频简单指令,复杂功能用组合实现。
b_196_0CISC 与 RISC 的十项对比表?¶
| 对比项 | CISC | RISC |
|---|---|---|
| 指令数目 | > 200 条 | < 100 条 |
| 指令字长 | 不固定 | 定长 |
| 可访存指令 | 不加限制 | 只有 LOAD/STORE |
| 指令执行时间 | 相差较大 | 规整、利于流水,理想吞吐可接近 1 CPI |
| 指令使用频度 | 相差很大 | 都比较常用 |
| 通用寄存器 | 较少 | 多 |
| 目标代码 | 难以优化编译 | 编译后代码高效 |
| 控制方式 | 经典教材常见微程序控制 | 经典教材常见硬布线控制 |
| 指令流水线 | 均可实现;复杂译码增加难度 | 指令规整,通常更易深度流水 |
| 兼容性 | 通常向后兼容 | 通常无法与老机型兼容 |
b_197_3;PDF 第 197 页 · b_197_4RISC 相比 CISC 的四点优势?¶
- 更高效利用芯片面积(本书历史模型):把更多面积用于寄存器/数据通路而非复杂控制;“50%/10%”是教材示例,不是现代处理器通用比例
- 更高的运算速度:指令少、格式统一、寻址简单 + 大量通用寄存器 + 流水线
- 更易设计与维护:设计周期短、出错概率低
- 更利于编译优化:指令类型和寻址方式有限,编译器易选最优指令序列
b_197_3;PDF 第 197 页 · b_197_4;PDF 第 197 页 · b_197_5LOAD/STORE 型指令有什么特点?¶
- 访存与计算分离:只有 LOAD(内存→寄存器)和 STORE(寄存器→内存)能访问主存,所有运算指令仅操作寄存器
- 指令格式规整:寄存器编号位数远少于内存地址,可实现定长指令,简化译码
- 利于流水线:统一的指令长度和访存边界,使各阶段易于并行
b_199_11寻址方式多或少各有什么影响?¶
- 寻址方式丰富:程序更简洁高效、便于表达复杂访问模式;但增加译码逻辑复杂度、不利于流水线调度、增大控制单元面积
- 寻址方式过少:简化硬件、提升执行速度;但限制程序表达能力,迫使用多条指令模拟复杂访问
b_199_3【易混点】第4章成对概念对照¶
| 易混对 | 分界线 |
|---|---|
| 二地址 vs 三地址指令 | 访存次数都是 4 次,别以为三地址更多 |
| 定长操作码 vs 扩展操作码 | 前者 n 位固定支持 2ⁿ 条;后者短码不能当长码前缀 |
| 转移指令 vs 调用指令 | 调用保存返回地址、要回来;转移不返回 |
| 直接寻址 vs 间接寻址 | EA = A(1 次访存)vs EA = (A)(2 次访存) |
| 寄存器寻址 vs 寄存器间接寻址 | EA = Rᵢ(0 次访存)vs EA = (Rᵢ)(1 次访存) |
| 基址寻址 vs 变址寻址 | BR 由 OS 设定不可变、A 可变;IX 由用户动态改、A 固定 |
| 相对寻址里的 PC | 是取指后自动更新的值(已指向下一条指令) |
| AT&T vs Intel 格式 | 源在前 vs 目的在前;%/$ vs 无前缀;() vs [] |
| jbe/ja vs jle/jg | 前者无符号比较(指针用),后者有符号比较 |
| mov vs lea | 取内容 vs 取地址(lea 常被借去做加法) |
| 调用者保存 vs 被调用者保存 | EAX/ECX/EDX vs EBX/ESI/EDI |
| CISC vs RISC | 教材典型实现常见微程序 vs 硬布线;RISC 的规整格式更利于流水线,但两类都可采用流水线或不同控制实现 |
b_199_5【必背数字】第4章¶
- 访存次数按“取指 + 主存型源操作数 + 主存写回”逐项数:典型 ACC 一地址且结果留在 ACC 时 2 次;若结果写回主存则 3 次
- 定长操作码 n 位 → 最多 2ⁿ 条指令
- 执行阶段取操作数次数:立即/寄存器 0、一次间址通常 2、直接/寄存器间接通常 1;均不含取指
- 相对寻址 EA = (PC) + A,PC 已自增
- 基址寻址 EA = (BR) + A;变址寻址 EA = (IX) + A
- 寄存器编号位数 = log₂(寄存器数),32 个寄存器需 5 位
- 本书 32 位 x86/cdecl 栈帧例:首个栈上传参常从 [ebp+8] 起、局部变量向负偏移;具体 ABI、优化和省略帧指针会改变布局
- 栈对齐由 ABI/调用点约定决定;常见现代 ABI 要求 16B 对齐,但不是“GCC 永远如此”的语言规则
- 32 位示例中
push/pop常使 ESP 减/加 4B;真实步长等于操作数/栈槽宽度 - “CISC 指令多、RISC 指令精简”和 80/20 是教材中的历史趋势/经验规律,不是以 100、200 条划出的现代 ISA 定义
b_165_9;PDF 第 165 页 · b_165_10