第 4 章 名词库

这一页是复习主入口。 目标是把第 4 章的名词收全,并把每个词的边界和适用范围钉死。

每条最多四行:是(定义)/不是(划掉最常见的误解)/易混(成对的对手)/范围(该结论在什么条件下才成立)。

建设进度:✅ 4.1 指令系统 ✅ 4.2 指令的寻址方式 ✅ 4.3 程序的机器级代码表示 ✅ 4.4 CISC和RISC的基本概念 (全章完整)


4.1.1 指令集体系结构

指令集体系结构 ISA

  • 是:软件与硬件之间机器语言级的正式契约,规定指令格式、类型、寻址方式、数据类型、寄存器组织、存储模型、I/O 方式、异常中断机制、特权级。
  • 不是:不是一个部件,主板上找不到它;也不是”越底层越 ISA”。
  • 易混:↔ 微体系结构(在它下面);↔ ABI(在它上面)。
  • 范围:判据是「改了之后老程序还能不能跑」。

微体系结构 Microarchitecture

  • 是:同一份 ISA 的一种硬件实现——流水线深度、Cache 参数、控制器实现方式、分支预测、乱序执行。
  • 不是:不属于 ISA。改了它,老程序照跑,只是快慢不同。
  • 范围:主频、制程、超标量、乱序全部在这一层。

ABI 应用程序二进制接口

  • 是:同一 ISA 上二进制模块的互操作约定——调用约定、栈帧布局、目标文件格式、系统调用编号。
  • 不是:不属于 ISA。改了它,机器码依然合法,但模块之间接不上。
  • 易混:↔ ISA。同一颗 x86 上 Windows 与 Linux 的 ABI 不同,指令编码完全相同。

汇编语法(Intel / AT&T)

  • 是:助记符的书写规则,由汇编器约定。
  • 不是:不属于 ISA。两种语法汇编出的机器码一个字节不差。

预处理

  • 是:.c → .i,宏展开、插入头文件、条件编译,纯文本替换。
  • 范围:完全不涉及 ISA,输出仍是 C 代码。

编译

  • 是:.i → .s,生成目标机器的汇编代码。
  • 范围:ISA 的主要客户,换 ISA 要换编译器后端。

汇编(过程)

  • 是:.s → .o,按 ISA 编码表逐条译成二进制。
  • 范围:跨模块引用的地址先填 0,同时留下重定位记录。

链接

  • 是:符号解析(把引用接到定义)+ 重定位(按最终布局补齐地址)。
  • 不是:链接器基本不看指令语义,只认符号表和重定位类型。

可重定位目标文件 .o

  • 是:已经是机器码,但地址尚未最终确定的目标文件。
  • 易混:↔ 可执行文件(地址已确定)。

特权指令

  • 是:只能在内核态执行的指令(如设置页表基址、开关中断)。
  • 范围:机制属于 ISA,“哪些操作需要特权”由 ISA 与 OS 共同划定。

4.1.2 指令的基本格式

操作码 OP

  • 是:指令中说明”做什么”的字段。
  • 范围:定长时位于最高 位且位置固定;扩展操作码时长度可变但仍从最高位开始。

地址码 A(形式地址)

  • 是:指令中说明”对谁做”的字段。
  • 不是:里面装的不一定是主存地址——也可以是寄存器号、立即数、位移量、端口号。
  • 范围:它代表什么,由操作码和寻址方式共同决定。

机器字长

  • 是:CPU 一次能处理的二进制位数 = 通用寄存器位数 = ALU 宽度。
  • 易混:↔ 存储字长、指令字长。三者互相独立。

存储字长

  • 是:一个存储单元的位数,等于 MDR 的位数。
  • 范围:见 3.2.3。

指令字长

  • 是:一条指令的总位数。
  • 范围:存储字长( 可为 );取指访存次数 指令字长 存储字长。

单字长 / 双字长 / 半字长指令

  • 是:指令字长为存储字长的 1 倍 / 2 倍 / 一半。
  • 不是:不是相对机器字长说的。

四地址指令

  • 是:OP A1 A2 A3 A4, 给出下条指令地址。
  • 范围:纯理论格式,现实不存在。PC 的发明就是把它省掉。

三地址指令

  • 是:,下条地址由 PC 隐含。
  • 范围:直接寻址、单字长时共访存 4 次。

二地址指令

  • 是:。
  • 不是: 的原值不保留,被结果覆盖。
  • 范围:共访存 4 次。

一地址指令

  • 是:(双操作数型),或 (单操作数读改写型)。
  • 范围:双操作数型访存 2 次,读改写型 3 次。

零地址指令

  • 是:NOP、HLT,或堆栈机的运算指令。
  • 不是:不一定不访存——堆栈机取操作数要访存(软堆栈)。

累加器 ACC

  • 是:一地址指令中隐含的操作数来源兼结果去向。

定长指令字

  • 是:所有指令长度相同。
  • 易混:↔ 定长操作码。两个维度独立,可自由组合。
  • 范围:PC 增量恒定、取指与译码可并行 → 流水线友好。

变长指令字

  • 是:指令按需长短不同(x86:1~15 字节)。
  • 范围:代码密度高,代价是取指与译码的串行依赖。

4.1.3 定长操作码指令格式

定长操作码

  • 是:所有指令的操作码位数相同、位置相同(最高 位)。
  • 范围: 位最多 条指令; 条指令至少 位。“最多”和”至少”是两个问题。

编码容量

  • 是:一组操作码位数能区分的指令条数上限。
  • 范围: 只在定长操作码下成立;扩展操作码下这个上界不适用。

地址字段位数

  • 是:, 为指令字长、 为操作码位数、 为等长地址字段个数。
  • 范围: 位 → 最多 个通用寄存器,或 个可直接寻址的存储单元。

4.1.4 扩展操作码指令格式

扩展操作码(变长操作码)

  • 是:地址字段少的指令操作码长,空出的地址位拿去装操作码。
  • 不是:不改变指令字长。教材例题里 16 位始终是 16 位。
  • 范围:教材例子里三地址指令码短,原因是地址字段挤占,不是使用频率。

前缀码

  • 是:任何码字都不是另一码字的前缀的编码。
  • 范围:扩展操作码 = 操作码用前缀码编码;性质是唯一可译,一串比特只有一种切分。

扩展窗口

  • 是:本层留出的未用编码,供下一层继续扩展。
  • 不是:不必是全 1,也不必只留一个。
  • 范围:最后一层(零地址)不留窗口,所以 16 位指令字 / 4 位地址的经典分配是 15/15/15/16。

扩展操作码递推

  • 是:下层最多条数 =(上层总数 − 上层已用)。
  • 范围:正推反推都用它。“最多几条”与”若还要留扩展则最多几条”差 1。

Kraft 不等式(超纲)

  • 是:一组前缀码存在的充要条件 , 表示编码空间用尽。
  • 范围:统考不考,作为验算工具用: 必冲突, 还有余量。

变长指令的长度

  • 是:由操作码隐含推出——操作码定类型,类型定格式,格式定长度。
  • 不是:不需要额外的”长度字段”,一位空间都不占。
  • 范围:代价在时序不在空间——取指与译码串行,第 2 条指令的起点要等第 1 条译完。

4.1.5 指令的操作类型

数据传送指令

  • 是:把数据从一处搬到另一处,内容不变。
  • 范围:一般不影响标志位,因此可插在 CMP 和 Jcc 之间。

LOAD / STORE

  • 是:主存与寄存器之间的传送。
  • 范围:在 RISC 里是唯一能访存的指令;CISC 无此限制。

PUSH / POP

  • 是:压栈 / 弹栈,隐含使用并自动修改 SP。

CMP / TEST

  • 是:CMP 做减法、TEST 做与,都只置标志位、不保存结果。
  • 不是:CMP 不会把差值写回目的操作数。

转移指令

  • 是:唯一能写 PC 的一类指令。
  • 范围:JMP/Jcc 不存返回地址;CALL 存返回地址;TRAP/INT 还要存 PSW 并切换特权级。

陷阱指令 TRAP / INT

  • 是:程序自愿执行的同步转移,通过中断向量表进入内核。
  • 不是:不是异步事件;它是一条指令。
  • 范围:用户态主动进入内核态的唯一途径。

IRET

  • 是:中断返回,弹出返回地址并恢复 PSW 与特权级。
  • 易混:↔ RET(只弹返回地址)。两者不可互换。

程序状态字 PSW

  • 是:存放标志位与机器状态的寄存器。
  • 范围:由算术逻辑类指令产生、由转移类指令消费,是所有条件分支的传递媒介。

输入输出指令 IN / OUT

  • 是:与 I/O 端口交换数据的专用指令。
  • 范围:只在 I/O 独立编址的机器上存在;统一编址时用普通访存指令,ISA 里没有 I/O 指令。“没有 I/O 指令”不等于”不能做 I/O”。

4.2.1 指令寻址和数据寻址

指令寻址

  • 是:确定下一条指令地址的过程,结果送 PC。
  • 易混:↔ 数据寻址(结果送去取操作数)。两者的算法是同一套。

顺序寻址

  • 是:,取指时自动完成。
  • 不是:那个 不是 1,而是 指令字长编址单位。
  • 范围:变长指令的 不是常数,要等译码后才确定。

跳跃寻址

  • 是:由转移指令给 PC 装一个非顺序值,装完立刻恢复顺序寻址。
  • 不是:不是一种”寻址方式”的名字,具体算法仍从十种里挑。

形式地址

  • 是:写在指令里的那几位,是计算 EA 的原料。
  • 不是:不等于操作数地址——只有直接寻址时两者相等。

有效地址 EA

  • 是:算出来的、操作数真正所在的地址。
  • 范围:寻址方式寄存器主存。立即寻址没有 EA。

寻址特征字段

  • 是:指令中说明本条用哪种寻址方式的字段。
  • 范围: 位 → 最多 种寻址方式。RISC 常靠操作码隐含,不设此字段。

地址翻译链

  • 是:符号 → 形式地址 → EA(逻辑地址) → 线性地址 → 物理地址 → Cache 划分 / 主存译码。
  • 范围:相邻两层是”输出→输入”,不是同层的两种做法,因此不能比较优劣、不能互相替代。

4.2.2 常见的数据寻址方式

隐含寻址

  • 是:操作数地址隐含在操作码中(如一地址指令的 ACC)。

立即寻址

  • 是: 字段里躺的就是操作数本身。
  • 不是:没有有效地址;且不访存。
  • 范围:立即数是补码,范围 ,不是 。

直接寻址

  • 是:,取操作数访存 1 次。
  • 范围:寻址范围只有 , 为形式地址位数。

间接寻址

  • 是:,取操作数访存 2 次(多级则每级加 1)。
  • 范围:换来两样东西——突破形式地址位数限制、地址可在运行时改(子程序返回、跳转表、函数指针的基础)。

多级间接寻址

  • 是:被指向的字里还是地址,需在字中留一位标志说明是否继续。
  • 范围:因此一个 32 位字里往往只有 31 位是地址。

寄存器寻址

  • 是:,操作数在寄存器里,访存 0 次。

寄存器间接寻址

  • 是:,访存 1 次。
  • 易混:↔ 间接寻址(2 次)。“少一次访存”就是它存在的全部理由。

偏移寻址

  • 是:某寄存器 的统称,含相对、基址、变址三种。
  • 范围:三者加法电路完全相同,不是三种硬件。

相对寻址

  • 是:。
  • 不是:基准不是当前指令地址,是取指后已增量的 PC(下一条指令地址)。
  • 范围: 是带符号补码,转移范围 ;因范围有限,只能做段内转移。

基址寻址

  • 是:,面向系统:程序重定位、多道程序。
  • 范围:寄存器是常量(执行期间不变,由 OS/装入程序设定),形式地址是变量。

基址寄存器 BR

  • 是:存放程序装入基址的寄存器,可为专用亦可为通用寄存器。
  • 不是:不是段寄存器。段寄存器在地址翻译链的下一层。
  • 易混:8086 中对应 BX / BP(Base),不是 DS/SS。

变址寻址

  • 是:,面向用户:数组、字符串、循环。
  • 范围:形式地址是常量(数组首址),寄存器是变量(下标)——与基址寻址角色互换。

变址寄存器 IX

  • 是:存放下标/偏移的寄存器,由用户程序修改。
  • 不是:不存数组首地址(首地址在形式地址 里)。
  • 易混:8086 中对应 SI / DI(Index)。

比例因子

  • 是:x86 的 中的 。
  • 范围:直接对应数组元素的字节数,使 arr[i] 一步到位。

前变址 / 后变址

  • 是:前变址 ;后变址 。
  • 不是:两者不等价。判据是题目给的括号位置。

堆栈寻址

  • 是: 栈顶,由 SP 隐含。
  • 范围:硬堆栈(专用寄存器组)不访存,软堆栈(主存)每次访存 1 次。

静态重定位

  • 是:装入时由装入程序逐条改写指令里的地址字段,需要重定位表。
  • 易混:↔ 动态重定位(改 BR,不动指令);↔ 相对寻址(位移天然相对)。
  • 范围:这就是”汇编/链接后那个地址转换过程”的正身。

动态重定位

  • 是:由基址寄存器实现,每次访存时硬件做加法,指令字节不变。
  • 范围:生效时机是每次访存,静态重定位是装入时一次。

段寄存器

  • 是:8086 的 CS/DS/SS/ES,参与 段寄存器。
  • 不是:不是基址寄存器的实现,也不属于任何一种寻址方式。
  • 范围:属于分段机制(地址翻译链第 2 层);MIPS 没有段寄存器却照样有基址寻址。

4.3.1 常用汇编指令介绍

Intel 格式

  • 是:mov dst, src,寄存器写 eax,内存写 [ebp+8]。
  • 范围:第一个操作数是目的。

AT&T 格式

  • 是:movl src, dst,寄存器写 %eax,立即数写 $8,内存写 8(%ebp)。
  • 范围:第一个操作数是源。判据:有 % $ 就是 AT&T。两种格式机器码完全相同。

LEA

  • 是:把有效地址本身送入寄存器。
  • 不是:从不访存;方括号在这里不表示取内容;不改标志位。
  • 易混:↔ MOV(取的是内容)。
  • 范围:能当算术用,因内存操作数语法本身是 ;等效于一条三地址指令;赢在指令条数与执行端口(AGU),不赢在单条延迟。

MOVZ / MOVS

  • 是:零扩展 / 符号扩展后再传送。
  • 范围:扩展方式必须与原类型的符号性一致,否则值会变(见 2.1.4)。

CF 进位标志

  • 是:无符号运算的进位/借位。
  • 范围:服务于无符号比较(ja/jb)。inc/dec 不改 CF。

OF 溢出标志

  • 是:有符号运算溢出。
  • 范围:服务于有符号比较(jg/jl)。

ZF / SF

  • 是:结果为 0 / 结果最高位为 1。
  • 范围:一次减法同时置好 CF、OF、ZF、SF——硬件不做选择,硬件提供全部选项。

shl 与 sal

  • 是:同一条机器指令的两个助记符(左移时逻辑与算术行为相同)。
  • 易混:↔ shr 与 sar(必须分家:补 0 vs 补符号位)。

4.3.2 选择语句的机器级表示

Jcc 条件转移

  • 是:读 PSW 决定是否改 PC 的指令。
  • 不是:只读标志位,不改标志位;不必紧跟 cmp(中间可插 mov/lea)。
  • 范围:g/l 是有符号(greater/less),a/b 是无符号(above/below)。

条件取反

  • 是:编译器把源码条件取反后跳转,让 then 分支 fall through。
  • 范围:读汇编时看到 jle,源码多半写的是 >。

跳转表

  • 是:switch 的 实现,用变址寻址 + 存储器间接寻址一次跳到位。
  • 范围:三步——减下界平移 → 无符号 ja 挡越界 → jmp [表首址 + 下标×4];case 稀疏时表太大,改用级联比较。

无符号越界检查

  • 是:减去下界后用 ja 比较,一次同时挡住上下两侧越界(下界之外的值减法后成为大无符号数)。
  • 不是:用有符号 jg 会漏掉下界。

条件传送 CMOV

  • 是:按条件决定是否写入目的寄存器,不产生任何转移指令,无分支预测失败。
  • 不是:不能用于有副作用、可能出错或开销大的分支——两个分支都会被求值(p ? *p : 0 会无条件解引用)。

4.3.3 循环语句的机器级表示

do-while 骨架

  • 是:循环体 → 比较 → 条件后向跳转,整个循环只有一条转移指令。
  • 范围:三种循环最终都塌缩到这个骨架。

跳到中间 jump-to-middle

  • 是:-O0 下 while 的翻译——入口一条无条件 jmp 跳到判断处。
  • 易混:↔ 守卫式。入口是无条件 jmp 还是条件跳出,是判据。

守卫式 guarded-do

  • 是:-O1+ 下 while 的翻译——先判一次(守卫),然后整体当 do-while。
  • 范围:判断代码被复制一份,换来循环体内只剩一条后向分支,利于分支预测。

continue 的落点

  • 是:for 里 continue 跳到 update,while 里跳到 test。
  • 范围:这是 for 不能机械改写成 while 的唯一原因;break 两者相同。

归纳变量替换

  • 是:把 a[i] 的地址计算换成一个指针每轮加常量,消掉乘法。
  • 范围:结果是汇编里找不到 i;每轮固定增量 = 元素字节数,终止条件变成指针与 &a[n] 比较。

循环展开

  • 是:把若干轮合并成一轮以减少分支与判断。
  • 范围:读汇编时看到重复的相同结构、指针一次加 16,不要以为源码写了四遍。

LOOP 指令

  • 是:x86 的 ECX--; if(ECX≠0) jump,一条顶三条。
  • 范围:编译器几乎从不生成(多数微架构上比 dec+jnz 更慢)——CISC 的负面例证。

4.3.4 过程调用的机器级表示

CALL

  • 是:push (下一条指令地址); jmp addr。
  • 不是:压入的不是 call 自身的地址。
  • 易混:↔ JMP(不存返回地址);↔ TRAP(还要存 PSW、切特权级)。

RET

  • 是:pop → PC。
  • 易混:↔ IRET(还要恢复 PSW 与特权级)。两者不可互换。

返回地址

  • 是:存放在栈上([ebp+4])。
  • 范围:存在栈上,递归才可行;同时它是可写数据,缓冲区溢出改的就是它。

栈帧

  • 是:一次函数调用在栈上占据的区域,含参数、返回地址、旧 EBP、保存的寄存器、局部变量。
  • 范围:参数区属于调用者的栈帧,由调用者分配、(cdecl 下)由调用者释放。

帧指针 EBP

  • 是:指向本帧基址的寄存器,函数执行期间固定不变。
  • 易混:↔ ESP(栈顶,随压弹变动)。
  • 范围:[ebp+8]=第一参数、[ebp+4]=返回地址、[ebp]=旧 EBP、[ebp-4]=第一局部变量。这是基址寻址的标准实战:寄存器常量、形式地址变量。

序言 prologue / 尾声 epilogue

  • 是:push ebp; mov ebp,esp; sub esp,N / mov esp,ebp; pop ebp; ret。
  • 范围:leave = 前两条尾声指令的合并。顺序不能乱。

调用者保存寄存器

  • 是:EAX ECX EDX(IA-32),语义是”调用之后这几个的值我不保证”。
  • 范围:调用后还要用的值,要么放被调用者保存寄存器,要么调用前自己存。

被调用者保存寄存器

  • 是:EBX ESI EDI EBP,语义是”调用前后这几个的值不变”。
  • 范围:分成两类是为了让双方各存自己真正在用的那些。

调用约定 cdecl / stdcall

  • 是:cdecl 调用者清参数栈(支持可变参数如 printf);stdcall 被调用者清栈(ret N,代码小但参数个数固定)。
  • 范围:属于 ABI,不属于 ISA。这就是同一颗 CPU 上两套 ABI 不能混用的具体样子。

参数从右往左压栈

  • 是:IA-32 的约定。
  • 范围:因此第一参数固定落在 [ebp+8],被调用者不必知道参数总数——可变参数函数得以成立。

尾递归优化

  • 是:把尾位置的递归调用改写成循环,复用同一个栈帧。
  • 范围:优化后递归深度不再增长,不会栈溢出。

4.4.1 复杂指令系统计算机(CISC)

CISC

  • 是:指令多而复杂、格式可变、任意指令均可访存、多周期、寄存器少的 ISA 设计倾向。
  • 不是:本质不是”指令条数多”,而是单条指令功能复杂 + 任意指令可访存。
  • 范围:三条历史动因——主存贵(代码密度)、编译器弱(语义鸿沟)、微程序使扩充廉价。

语义鸿沟

  • 是:高级语言语义与机器指令语义之间的差距,CISC 试图靠复杂指令缩小它。
  • 范围:今天基本失效——编译器优化能力已超过手写汇编,多条简单指令的调度空间更大。

二八定律(80-20 法则)

  • 是:程序 80% 的运行时间只用到约 20% 的指令。
  • 范围:RISC 的实测依据——把”复杂指令好不好”从哲学争论变成工程问题。

微操作 μops

  • 是:现代 x86 把 CISC 指令译码成的定长、类 RISC 的内部操作。
  • 范围:说明 ISA 层与微架构层可以分属两种风格;x86 的 ISA 仍是 CISC。

长度预译码

  • 是:超标量 x86 中专门用来切分指令边界的流水级。
  • 范围:变长指令的代价的具体形态;RISC 完全不需要这级电路。

复杂指令的价值判据

  • 是:看硬件有没有真的为它建一条专用通路。
  • 范围:lea 有 AGU 通路 → 编译器大量生成;loop 走微码 → 编译器几乎不用。一正一反两个例证。

代码密度

  • 是:同一程序编译后占用的存储空间。
  • 范围:CISC 唯一保住的优势;收益已从”省主存”转为”省指令 Cache”。ARM 的 Thumb 就是 RISC 反过来学这一条。

4.4.2 精简指令系统计算机(RISC)

RISC

  • 是:指令简单且定长、格式统一、寻址方式少、仅 load/store 访存、CPI≈1、寄存器多的设计倾向。
  • 不是:精简的不是指令条数,是每条指令的功能。RISC-V 加扩展后指令并不少。
  • 范围:全部设计选择都指向同一个词——流水线。

Load/Store 结构

  • 是:只有 load/store 能访存,其余指令只碰寄存器。
  • 范围:真正意义是让每条指令经过相同的流水段,从 ISA 层禁止”中途访存两次”。
  • 不是:不等于总访存数据量减少——减少的是中间结果的访存,要靠寄存器多来兑现。

CPI ≈ 1

  • 是:流水线满载时的吞吐口径——平均每周期完成一条指令。
  • 不是:不是延迟口径。一条指令仍要经过 5 个周期才走完。

寄存器数量 ≥ 32

  • 是:Load/Store 结构的必要配套。
  • 范围:32 个寄存器要 5 位编号,三地址指令 15 位——与 32 位定长指令字互相配合设计。

指令调度

  • 是:编译器重排指令顺序以填满流水线空档、避开数据相关。
  • 范围:与寄存器分配、复杂操作合成一起,构成”RISC 把优化重心移到编译器”的具体内容。

延迟槽

  • 是:早期 MIPS 让转移指令后一条指令无论转不转都执行。
  • 不是:不是所有 RISC 的共同特征——RISC-V 和 ARM 都没有采用。

4.4.3 CISC 和 RISC 的比较

CPU 性能公式

  • 是:。
  • 范围:CISC 与 RISC 在三个因子上方向相反(CISC: 少、CPI 大、 长),所以只给一个因子问快慢,答案是”无法判断”。

指令条数 IC

  • 是:同一程序编译后的指令总数。
  • 不是:不是”指令系统里的指令种类数”。RISC 的 更多(约多 20%~40%)。

“指令条数少”的两种读法

  • 是:①指令种类少(RISC 大体对);②同一程序的指令条数少(CISC 对,RISC 错)。
  • 范围:统考考的是第二种,因为它出现在性能公式里。

控制器搭配

  • 是:CISC↔微程序、RISC↔硬布线,都是典型搭配而非定义。
  • 范围:因果强度不对称——RISC→硬布线较硬(指令不简单就没法硬布线),CISC→微程序只是历史便利;现代 x86 简单指令走硬布线、复杂指令走微码。

现代融合

  • 是:CISC 内部 RISC 化(μops)、RISC 加扩展(SIMD、Thumb)、共用技术(流水线、超标量、乱序、分支预测、Cache、多核)。
  • 范围:共用技术全属微体系结构,与 ISA 风格无关;CISC/RISC 是设计倾向的两端,不是二元标签。

高频范围限定清单

每一条都是”说法 → 它在什么条件下才成立 / 为什么错”。考前扫这一张表。

常见说法范围限定
”Cache 大小、流水线级数属于 ISA”错。属于微体系结构,改了老程序照跑
”调用约定、栈帧布局属于 ISA”错。属于 ABI,机器码合法但模块接不上
”Intel 语法和 AT&T 语法是两种 ISA”错。是汇编器约定,机器码完全相同
”指令字长等于机器字长”不一定。取指次数看的是指令字长 ÷ 存储字长
”单字长指令即指令字长等于机器字长”错。是相对存储字长说的
”指令字长必须是存储字长的整数倍”不必。半字长指令合法(一次访存取回两条)
“一地址指令一律访存 2 次”错。读改写型(INC A)是 3 次
”零地址指令一定不访存”只对硬堆栈成立;软堆栈机取操作数要访存
”二地址指令执行后第一个操作数保留”错。被结果覆盖,这是格式定义的一部分
”定长指令字必然配定长操作码”错。两个维度独立;统考最常考”指令字定长 + 扩展操作码"
" 位操作码至少能编 条指令”错。是最多。“最多”与”至少”是两个问题
”零地址指令不占用操作码编码”错。一样要占一个编码
”扩展操作码会改变指令字长”错。指令字长不变,变的是内部分界线
”三地址指令操作码最短是因为它最常用”错。因为地址字段占位最多(真实 ISA 里”高频给短码”是另一条独立理由)
“16 位指令字 4 位地址、三地址 15 条 → 二地址最多 15 条”错。最多 16 条;留窗口继续扩展才是 15
”零地址那一层也要留扩展窗口”错。下面没有层了,所以是 16 条
”变长指令需要一个字段标明长度”错。长度由操作码隐含推出,不占任何空间
”变长指令的代价是浪费存储空间”反了。它省空间,代价是取指与译码串行
”MOV 会影响标志位”错。传送类一般不改标志位,LEA 也不改
”INC 会改 CF”错。inc/dec 不改 CF(保护多精度加法的进位链)
“CMP 会把差值写回目的操作数”错。只置标志位
”TRAP 是异步事件”错。它是一条指令,同步、程序自愿
”RET 和 IRET 可以互换”错。IRET 还要恢复 PSW 与特权级
”没有 IN/OUT 指令的机器不能做 I/O”错。统一编址时用普通访存指令
”顺序寻址就是 PC 加 1”错。增量 = 指令字长 ÷ 编址单位;变长指令下还不是常数
”跳跃寻址是一种数据寻址方式”错。是指令寻址的一种情形,算法仍从十种里挑
”转移指令的目标地址有专门算法”错。复用数据寻址那十种
”形式地址就是操作数地址”只有直接寻址时成立
”每种寻址方式都要访存”错。立即、寄存器寻址不访存
”立即寻址的有效地址等于 “错。它没有有效地址
”立即数范围是 “错。是补码,
“间接寻址访存 1 次”错。2 次;多级则每级加 1
”相对寻址的基准是当前指令地址”错。是取指后已增量的 PC(下一条指令地址)
“基址寻址中形式地址不变”错。恰恰是它在变;不变的是基址寄存器
”变址寄存器里存数组首地址”反了。首地址在形式地址 里,变址寄存器存下标
”基址与变址的硬件实现不同”错。同一套加法;408 分的是语义不是硬件
”段寄存器是基址寄存器的具体实现”错。不在同一层——寻址方式出 EA,分段机制把 EA 变物理地址
”8086 里 408 的基址寄存器没有对应物”错。就是 BX / BP(Base);SI/DI 是 Index
”前变址与后变址等价”错。
“程序浮动只能靠基址寄存器”错。三种机制:静态重定位(改指令)、基址寻址(改 BR)、相对寻址(位移天然相对)
“jmp L1(近转移)不是相对寻址”错。恰恰是;x86 近转移默认编码成相对形式
”汇编源码能看出用了哪种寻址方式”错。要看汇编器最终选的机器指令编码
”LEA 要访存一次取出内容”错。从不访存;方括号在 lea 里只是地址表达式语法
”LEA 比 ADD 单条延迟更短”错。相同或更长;赢在指令条数、执行端口、不改标志位
”Intel 格式第一个操作数是源”错。是目的;AT&T 才是源在前
”shr 和 sar 是同一条指令”错。左移才不用分家(shl=sal),右移必须分
”x86 允许两个主存操作数”错。必须借道寄存器
”源码写 >,机器码跳转也是”大于”类”错。编译器把条件取反,跳的是 jle
”Jcc 必须紧跟 cmp”错。中间可插不改标志位的指令(mov/lea)
“有符号比较用 ja/jb”错。那是无符号;有符号用 jg/jl
”跳转表永远优于级联比较”错。case 稀疏时表太大
”跳转表越界检查用有符号比较”错。用无符号 ja 才能一次挡住两侧
”cmov 可以优化 p ? *p : 0”错。两个分支都会被求值,会无条件解引用
”循环体时间局部性好是因为没有跳转”反了。正因为有那条回跳;顺序执行给的是空间局部性
”for 和 while 可以机械互换”错。continue 的落点不同(for 跳 update);break 相同
”汇编里找不到循环变量说明代码错了”错。归纳变量替换——i 被换成指针
”loop 指令比 dec+jnz 快”错。多数微架构上更慢,编译器几乎不用
”call 压入 call 指令自身的地址”错。压入下一条指令的地址
”返回地址存在专用寄存器里”错。存在栈上,否则递归第二层就覆盖第一层
”EBP 在函数执行期间会变”错。固定不变,变的是 ESP
”push 使 ESP 增大”错。栈向低地址生长,ESP 减小
”每个函数都有栈帧”错。叶子函数在 -O2 下常省略 EBP,此时 [ebp+8] 那套失效
”参数区属于被调用者的栈帧”错。属于调用者
”递归需要专门的硬件支持”错。只需要栈
”调用者保存寄存器在调用后值仍可靠”错。那正是”不保证”的一类
”CISC 必须用微程序控制器”错。典型搭配而非定义;现代 x86 简单指令走硬布线
”RISC 必须用硬布线控制器”错。同上(但这个方向的因果更强)
“RISC 的指令条数一定比 CISC 少”看读法:指令种类大体少;同一程序的指令条数反而多 20%~40%
“RISC 每条指令执行延迟 1 个周期”错。CPI≈1 是吞吐口径,延迟仍是 5 个周期
”Load/Store 结构使总访存数据量减少”错。减少的是中间结果的访存
”RISC 代码密度比 CISC 高”错。更低,所以指令 Cache 压力更大
”延迟槽是所有 RISC 的共同特征”错。是 MIPS 的历史选择
”RISC 一定比 CISC 快”错。三因子方向相反,必须算乘积
”只知道 A 机指令条数少就能判断 A 更快”错。正确答案是”无法判断"
"现代 x86 已经变成 RISC”错。ISA 仍是 CISC,只有微架构是 RISC 式
”超标量、乱序、分支预测是 RISC 专有”错。属微体系结构,与 ISA 风格无关

链接