想象你帮妈妈去超市买菜。妈妈给你一张购物清单,上面写着“苹果:5斤”。你把 5 斤这个数字直接记在清单上,店员一看就知道装多少——这是第一种方式。但清单上也可能写着“苹果:按 3 号储物柜里的纸条装”。你打开 3 号储物柜,取出里面写着“5斤”的纸条,再交给店员——这是第二种方式。 中央处理器(CPU)执行指令时,也面临同样的问题:指令里的“操作数”(要处理的数据)到底从哪里来?x86 处理器给出了好几种答案,其中最基础、最常用的两种,就是立即寻址和寄存器寻址。立即寻址把数据本身直接“写进”指令里,就像清单上直接写“5斤”;寄存器寻址则让数据住进 CPU 内部的寄存箱,指令只标个“柜号”,CPU 再去对应的寄存箱里取。 整篇文章,我们就用“购物清单”和“储物柜”的比喻,把这两种寻址方式的原理、编码、优缺点和实际应用讲透。看完之后,你会对 CPU 如何取数、汇编指令如何变成机器码、编译器又为何那样优化,建立起清晰的直觉。

岗位关联

对 AI 从业者而言,理解立即寻址与寄存器寻址是读懂反汇编日志、定位性能瓶颈和优化推理引擎底层算子的一把钥匙——当模型部署到 CPU 上,你看到的每一行汇编都在用这两种寻址方式搬运数据。

目录
  1. 可视化演示
  2. 寻址方式基础
  3. 立即寻址原理
  4. 立即数寻址特征
  5. 寄存器寻址原理
  6. 寄存器寻址特征
  7. 两者对比选择
  8. 编码与反汇编
  9. 工程优化实践
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示指令编码格式、ModR/M字节结构与性能对比,支持时钟周期调节。

本节配有交互动效(进入视口后自动加载,约 3KB)。

指令编码格式对比 红色立即寻址将常量编码在指令字节中,ModR/M后紧跟立即数 青色寄存器寻址通过ModR/M的mod=11指定寄存器,无需额外字节 MOV EAX, 42 vs MOV EAX, EBX 立即寻址指令更长但无需加载,寄存器寻址效率最高

寻址方式基础

想象你在超市里帮妈妈购物。妈妈给的清单上,每一个物品都对应一条指令。可问题是,物品的“数量”到底写在哪里?是直接写在清单上,还是放在某个柜子里,清单只写柜号?CPU 处理指令时,同样要回答一个基础问题:操作数在哪儿?这个“在哪儿”的答案,就是寻址方式。寻址,说白了就是寻找操作数的地址。

从汇编语言视角看,一条指令通常由操作码(干什么事)和操作数(对谁干)两部分组成。x86 指令的操作数可以来自三个地方:一是直接写在指令里的常量,二是 CPU 内部寄存器里的值,三是内存某个单元里的值。本文聚焦前两种——立即寻址和寄存器寻址。

寻址方式决定了 CPU 每执行一条指令要花多少功夫。如果数据就在手边,CPU 就能快速完成;如果数据躺在遥远的内存里,CPU 就需要通过外部总线去取,耗时显著增加。因此,理解寻址方式,是读懂指令编码、分析程序性能的第一步。

回到购物清单的比喻:寻址方式的本质,就是决定“把数量写在哪”以及“店员从哪里读数量”的规则。规则选得好,买菜快;规则选得差,光找柜子就花半天。

立即寻址原理

妈妈在清单上写“苹果:5斤”,5斤这个数字就白纸黑字写在清单上,店员一眼看到,不需要再去别处找。立即寻址(Immediate Addressing)就是这种思路:操作数本身是一个常量,直接编码在指令中。

在 x86 汇编里,这样的指令形如 MOV AX, 1234h。指令中的 MOV 是操作码,告诉 CPU“把后面的数据搬进 AX 寄存器”;1234h 就是立即数,它不是一个地址,而是实实在在的数据。CPU 在执行时,从指令流中直接取出这个常量,放进目标寄存器,整个过程不访问内存。

立即寻址有一个严格限制:立即数只能作为源操作数,不能作为目标操作数。你不可能写 MOV 1234h, AX——因为常量是只读的,它没有“房间”可以接收新数据,就像你不能把“5斤”这个数字本身擦掉重写,清单上的字一旦印好就是固定的。

从编码来看,立即数是紧跟在操作码后面的一串字节。x86 采用小端字节序,即低位字节存放在前面。所以 MOV AX, 1234h 的机器码是 B8 34 12,其中 B8 是指令要“把立即数装入 AX”,34 12 是 1234h 的低字节在前、高字节在后。

立即数寻址特征

立即寻址最突出的优势是“快”。因为数据跟着指令走,CPU 在取指阶段就把操作数一起拿到了,不需要发出一条内存访问请求。想象店员在收银台前扫描清单,看到“5斤”直接装袋——不用跑去仓库翻找。

但这种“快”是有代价的。第一,灵活性受限。立即数在编译时就必须确定,程序运行期间无法改变。如果你想通过用户输入动态改变数量,立即寻址就无能为力了。第二,指令长度会变长。一个 32 位立即数要占用 4 个字节跟在操作码后面,指令变长意味着取指时间变长、代码体积变大。

从编码角度看,立即寻址的机器码结构是“操作码 + 立即数”:

回到比喻:立即寻址就像在清单上写死“5斤”,好处是店员不用问任何人;坏处是如果明天要买 6 斤,你得重新打印一张清单——也就是重新编译程序。

MOV AX, 1234h⇒B8⏟操作码 34 12⏟立即数(小端)\text{MOV AX, 1234h} \Rightarrow \underbrace{\text{B8}}_{\text{操作码}} \ \underbrace{\text{34 12}}_{\text{立即数(小端)}}
一句话:立即寻址用“定死的值”换“极致的快”,适合初始化常量、设置掩码等场景。
  1. 操作码 B8B8 是 x86 指令体系中“把 16 位立即数装入 AX 寄存器”的专用操作码。CPU 看到 B8,就知道后面跟随的是要装入 AX 的立即数。
    B8\text{B8}
  2. 立即数 34 121234h 按小端字节序拆分,低字节 34h 放在前面,高字节 12h 放在后面。CPU 读取时自动按小端规则还原成 1234h。
    1234h→34 12\text{1234h} \rightarrow \text{34 12}
  3. 指令拼接操作码在前、立即数在后,最终形成 3 字节指令 B8 34 12。指令长度 = 1 字节操作码 + 2 字节立即数。
    B8+34 12=B8 34 12\text{B8} + \text{34 12} = \text{B8 34 12}

寄存器寻址原理

购物清单上写着“苹果:按 3 号储物柜里的纸条装”。店员走到收银台旁边的 3 号储物柜,打开抽屉,取出纸条,上面写着“5斤”。这个储物柜,就是 CPU 内部的寄存器(Register)。

寄存器寻址(Register Addressing)的操作数存放在寄存器中,指令里只写出寄存器编号或名字。x86 的通用寄存器有 EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP 等,每个都是 CPU 内部一个极小的存储单元,访问速度比内存快一个数量级。

汇编指令如 MOV AX, BX,含义是“把 BX 寄存器里的值复制到 AX 寄存器”。这条指令没有立即数,只有两个寄存器名字。在机器码层面,x86 通过 ModRM 字节来编码寄存器组合。ModRM 字节分为三个字段:mod(寻址模式)、reg(源寄存器)、rm(目标寄存器)。

寄存器寻址与立即寻址最大的不同在于:寄存器里的值是“活的”。程序可以随时用新指令改写某个寄存器的内容,而立即数是“死的”,编译完就固定了。这就像储物柜里的纸条可以随时换新,而清单上印好的数字不能改。

寄存器寻址特征

寄存器寻址的招牌优势是“最快”。它不需要访问内存,数据就在 CPU 内部。对比来看,内存寻址要经过地址总线、数据总线,耗时是寄存器的几十倍甚至上百倍。所以编译器在优化代码时,会拼命把频繁使用的变量塞进寄存器,这就是“寄存器分配”优化。

但寄存器寻址有一条铁律:位宽必须匹配。x86 的 32 位寄存器 EAX 可拆成 16 位的 AX,再拆成 8 位的 AL(低 8 位)和 AH(高 8 位)。你不能把 32 位的数据塞进 8 位的 AL,就像不能把 5 公斤的大米装进只能装半斤的小盒子。

从机器码看,寄存器寻址的格式是“操作码 + ModRM”:

此外,寄存器寻址可以作为目标操作数——MOV BX, AX 是完全合法的,因为寄存器是“可写的储物柜”。这一特性让寄存器寻址成为程序中最常用的数据搬运方式。

MOV AX, BX⇒89⏟操作码 D8⏟ModRM 寄存器字段\text{MOV AX, BX} \Rightarrow \underbrace{89}_{\text{操作码}} \ \underbrace{\text{D8}}_{\text{ModRM 寄存器字段}}
一句话:寄存器寻址 = 开柜取物,又快又能改,是编译器眼中的“头号优选”。
  1. 操作码 8989 表示“MOV r/m16, r16”,即把源寄存器(reg 字段指定)的值传给目标寄存器(rm 字段指定)。
    89\text{89}
  2. ModRM 字节 D8D8 = 1101 1000,拆开看是 mod=11、reg=011、rm=000。mod=11 告诉 CPU 这是寄存器到寄存器的操作,不需要计算内存地址。
    D8=1 10 11 0002\text{D8} = \text{1 10 11 000}_2
  3. 寄存器解码reg=011 对应 BX,rm=000 对应 AX,于是 CPU 知道要将 BX 内容复制到 AX。
    reg=011→BX,rm=000→AX\text{reg}=011 \rightarrow \text{BX}, \quad \text{rm}=000 \rightarrow \text{AX}

两者对比选择

现在我们把两种寻址方式摆上擂台。立即寻址像一个“死记硬背”的店员:清单上写 5 斤就装 5 斤,不会错,但不会变通。寄存器寻址像一个“看柜办事”的店员:柜子里纸条写多少就装多少,纸条可以随时换,灵活得多。

速度对比:两者都不访问内存,因此都比内存寻址快。严格来说,寄存器寻址略胜一筹,因为立即数需要占用指令流带宽,而寄存器访问是 CPU 内部操作,不额外消耗取指带宽。但在宏观层面,两者差距很小,主要瓶颈都在其他环节。

灵活度对比:寄存器寻址完胜。立即数只能表达编译时已知的常量,而寄存器可以承载运行时动态变化的值。循环计数器、累加结果、函数参数——这些非寄存器不可。

适用场景:

  • 立即寻址:初始化常量、设置标志位、构造掩码、指定地址偏移。
  • 寄存器寻址:算术运算、数据搬运、循环控制、函数调用约定。

用访存次数对比,可以记住这个关键差异:

回到购物清单:如果你只需要买“永远不变的 5 斤”,直接写在清单上即可;但如果你今天买 5 斤、明天买 8 斤,就必须准备一个可擦写的储物柜。聪明的编译器,正是这样在两种寻址方式之间做选择的。

访存次数:立即寻址=0寄存器寻址=0内存寻址≥1\text{访存次数}: \quad \text{立即寻址}=0 \quad \text{寄存器寻址}=0 \quad \text{内存寻址}\ge 1
一句话:立即寻址负责“恒定”,寄存器寻址负责“善变”;真正的性能优化,就是把该放柜子里的数据放对柜子。
  1. 立即寻址访存次数为 0常量直接编码在指令中,CPU 在取指阶段已拿到数据,不需要额外访问内存。
    立即寻址=0 次访存\text{立即寻址} = 0\ \text{次访存}
  2. 寄存器寻址访存次数为 0数据在 CPU 内部的寄存器中,访问寄存器是 CPU 内部电路操作,不经过内存总线。
    寄存器寻址=0 次访存\text{寄存器寻址} = 0\ \text{次访存}
  3. 内存寻址至少 1 次操作数存放在内存中,CPU 必须通过地址总线和数据总线去取,至少一次外部访问。
    内存寻址≥1 次访存\text{内存寻址} \ge 1\ \text{次访存}

编码与反汇编

购物清单上的汉字,店员看了能懂,但收银机只认条形码。汇编指令也一样——CPU 只认识机器码,汇编指令是给人看的。编码(Encoding)就是把汇编指令翻译成机器码的过程,反汇编(Disassembly)则是逆行翻译。

立即寻址的编码规则是“操作码 + 立即数”。MOV AX, 1234h 编码为 B8 34 12,其中立即数按小端字节序存储,低字节在前。这里有个常见坑:新手常以为应该写成 12 34,但 x86 的小端规则恰恰相反。

寄存器寻址的编码规则是“操作码 + ModRM”。MOV AX, BX 编码为 89 D8,ModRM 字节同时携带源寄存器和目标寄存器的编号。ModRM 的设计精巧之处在于,一个字节就表达了两三个信息,节省了宝贵的指令空间。

反汇编器(如 objdump、IDA Pro)读取机器码时,先解析操作码,再根据操作码类型决定后面跟着的是立即数还是 ModRM 字节。这也是为什么反汇编工具能准确还原出汇编指令——它只是把编码规则倒过来执行了一遍。

用指令长度公式可以概括这种编码的代价:

理解编码规则后,你再看到一段十六进制字节流,就能像破译密码一样读出它的含义。这也是逆向工程师的日常基本功。

指令长度=操作码字节数+操作数编码字节数\text{指令长度} = \text{操作码字节数} + \text{操作数编码字节数}
一句话:编码是“把清单翻译成条形码”,反汇编是“把条形码还原成清单”;立即数占地方,寄存器字段省地方。
  1. 操作码字节数x86 的操作码长度通常为 1 字节(如 B8、89),部分指令有前缀或扩展,但基础寻址中操作码为 1 字节。
    操作码=1 字节\text{操作码} = 1\ \text{字节}
  2. 操作数编码字节数立即寻址中,操作数就是立即数本身,16 位为 2 字节、32 位为 4 字节;寄存器寻址中,操作数是 ModRM 字节,固定 1 字节。
    立即数=2/4 字节,ModRM=1 字节\text{立即数} = 2/4\ \text{字节}, \quad \text{ModRM} = 1\ \text{字节}
  3. 指令总长度将两部分相加,立即寻址的 MOV AX, imm16 为 3 字节,寄存器寻址的 MOV AX, BX 为 2 字节。寄存器寻址往往更紧凑。
    1+2=3,1+1=21 + 2 = 3, \quad 1 + 1 = 2

工程优化实践

当编译器把 C 语言代码编译成机器码时,它就像一位经验丰富的店员,不断在“清单上写字”和“用储物柜”之间做抉择。这个抉择直接决定了程序的运行速度。

编译常量传播:如果代码里写了 int x = 5; int y = x + 1;,编译器发现 x 的值始终是 5,就不会真给 x 分配内存或寄存器,而是直接把 y 的初始化优化成 MOV y, 6。这就是常量传播——用立即寻址消除不必要的变量。

寄存器分配:对于循环中的变量,编译器会优先分配寄存器。因为循环体可能要执行百万次,如果每次迭代都去内存读写,性能会急剧下降。把计数器放在 ECX 里,用寄存器寻址做 INC ECX,速度比内存版本快一个量级。这也是编译器优化中最重要的“寄存器分配”环节。

性能调试:当你用 perf 或 gdb 观察程序时,看到的反汇编代码里,立即寻址和寄存器寻址的出现频率反映了代码质量。频繁出现在内存寻址说明可能发生了“寄存器溢出”(寄存器不够用),这是优化的重要信号。

这里有一个典型的取舍案例:调试版本的二进制文件通常使用内存寻址存储每个变量,因为方便断点观察;发布版本则大量使用寄存器和立即数寻址,换取最高性能。你在 gdb 里看到的汇编和线上运行的汇编,往往不是同一份。

AI 应用场景

反汇编模型推理日志

阶段:模型部署与性能分析

解决的问题:AI 模型部署到 CPU 端时,性能分析工具展示的反汇编代码中包含大量 MOV EAX, imm32 和 MOV EAX, EBX 类指令。若工程师不理解立即寻址和寄存器寻址,就无法判断瓶颈是数据搬运开销还是算子本身的计算量。

具体案例:使用 perf 分析 ONNX Runtime 的推理热函数,发现某算子内部反复将常量加载进寄存器。通过反汇编定位到 MOV EAX, 1 这类立即寻址指令,结合算子融合优化,将这条指令从热点循环中移出,推理延迟降低了 12%。

编译器后端指令选择

阶段:AI 编译器开发(如 TVM、MLIR 后端)

解决的问题:AI 编译器要把张量计算图翻译成高效的机器码,必须决定每个常量用立即寻址还是寄存器寻址。选择错误会导致指令冗余或寄存器压力过大。

具体案例:在 TVM 的 x86 后端,对 scale = 0.5 这样的常量,编译器将其编码为立即数直接参与向量运算;对不断更新的累积变量,则分配寄存器。理解两种寻址方式的编码代价,帮助后端开发者为每个常量选择最短编码路径,显著减小二进制体积。

调试器单步跟踪变量

阶段:算法调试与故障定位

解决的问题:AI 训练时出现梯度异常,工程师希望在 gdb 中查看某个中间变量的实际值。理解寄存器寻址才能看懂 mov eax, DWORD PTR [rbp-0x4] 和 mov eax, ebx 的区别,快速判断变量到底存在寄存器还是内存。

具体案例:调试 PyTorch 自定义算子时,核心循环变量被编译器分配在 EBX 寄存器中。通过 gdb 的寄存器窗口观察 EBX 的变化,工程师发现循环索引在下标溢出后变成了负数,定位到整数溢出 bug。

Python 演示

python53 行
"""x86 立即寻址与寄存器寻址编码模拟器演示 MOV 指令如何从汇编变成机器码""" import struct REG16 = {'ax': 0, 'cx': 1, 'dx': 2, 'bx': 3, 'sp': 4, 'bp': 5, 'si': 6, 'di': 7}REG32 = {'eax': 0, 'ecx': 1, 'edx': 2, 'ebx': 3, 'esp': 4, 'ebp': 5, 'esi': 6, 'edi': 7}  def encode_mov_imm(dest_reg, imm, width=16):    """立即寻址编码: mov dest_reg, imm"""    if width == 16:        opcode = 0xB8 + REG16[dest_reg]        code = bytes([opcode]) + struct.pack('<H', imm & 0xFFFF)    else:        opcode = 0xB8 + REG32[dest_reg]        code = bytes([opcode]) + struct.pack('<I', imm & 0xFFFFFFFF)    return code.hex(' ').upper()  def encode_mov_reg(dst, src):    """寄存器寻址编码: mov dst, src (32位)"""    opcode = 0x89    modrm = 0b11_000_000 | (REG32[src] << 3) | REG32[dst]    return bytes([opcode, modrm]).hex(' ').upper()  def disasm(hex_str):    """极简反汇编: 还原人类可读的汇编"""    if hex_str.startswith('B8'):        imm = hex_str.split()[1] + hex_str.split()[2]        return "MOV EAX, 0x" + imm    if hex_str == '89 D8':        return "MOV EAX, EBX"    if hex_str == '89 CB':        return "MOV EBX, ECX"    return "未知指令"  if __name__ == '__main__':    print('=== 立即寻址编码 ===')    print('MOV AX, 1234h ->', encode_mov_imm('ax', 0x1234, 16))    print('MOV EAX, 1   ->', encode_mov_imm('eax', 1, 32))     print('\n=== 寄存器寻址编码 ===')    print('MOV EAX, EBX ->', encode_mov_reg('eax', 'ebx'))    print('MOV EBX, ECX ->', encode_mov_reg('ebx', 'ecx'))     print('\n=== 反汇编还原 ===')    print('B8 01 00 00 00 ->', disasm('B8 01 00 00 00'))    print('89 D8          ->', disasm('89 D8'))
目的:模拟 x86 中立即寻址和寄存器寻址的机器码编码过程,并演示最简反汇编还原,帮助理解指令编码的本质。
  1. opcode = 0xB8 + REG16[dest_reg]立即寻址的操作码从 B8 开始,加上寄存器编号即可得到对应指令的操作码。
  2. struct.pack('<H', imm & 0xFFFF)<H 表示按小端字节序打包 16 位整数,这正是 x86 存储立即数的方式。
  3. modrm = 0b11_000_000 | (REG32[src] << 3) | REG32[dst]构造 ModRM 字节:mod=11 表示寄存器模式,中间 3 位放源寄存器编号,低 3 位放目标寄存器编号。
  4. hex_str.startswith('B8')反汇编器通过识别操作码前缀,判断这是一条“立即数装入 EAX”的指令。
  5. imm = hex_str.split()[1] + hex_str.split()[2]从编码中提取立即数字节,并拼接还原出完整数值。

常见误区

误区

正解

误区

正解

误区

正解

误区

正解

误区

正解

面试题

Q1. 在立即寻址中,操作数存放在哪里?

单选题 · easy

  • A.通用寄存器中
  • B.内存的数据段中
  • C.指令自身编码中← 正确答案
  • D.独立的高速缓存中

答案:C。立即寻址将操作数作为常量直接编码在指令的立即数字段中,CPU 取指时一并获得。它不在寄存器中,也不在内存数据段中,与高速缓存无直接关系,故 C 正确。

Q2. 指令 MOV AX, 1234h 采用的是哪种寻址方式?

单选题 · easy

  • A.寄存器寻址
  • B.立即寻址← 正确答案
  • C.直接内存寻址
  • D.基址加变址寻址

答案:B。1234h 是直接写在指令中的常量,而非寄存器名或内存地址,因此是立即寻址。若写成 MOV AX, BX 才是寄存器寻址,MOV AX, [1234h] 才是内存寻址。

Q3. 寄存器寻址的源操作数从哪里获取?

单选题 · easy

  • A.指令的立即数字段
  • B.CPU 内部寄存器← 正确答案
  • C.外部内存单元
  • D.主板上的 CMOS

答案:B。寄存器寻址的操作数存放在 CPU 内部的通用寄存器中,指令只编码寄存器编号,CPU 直接从对应的寄存器读取数据,不需要访问内存。CMOS 与寻址方式无关。

Q4. MOV EAX, 1 在 x86 32 位模式下的机器码最可能是?

单选题 · mid

  • A.B8 01 00 00 00← 正确答案
  • B.01 00 00 00 B8
  • C.B8 00 00 00 01
  • D.01 B8 00 00 00

答案:A。操作码 B8 表示“立即数装入 EAX”,立即数 1 按小端字节序编码为 01 00 00 00,拼接后为 B8 01 00 00 00。若把 1 放在最后则是大端序,不符合 x86 规则。

Q5. 立即寻址的典型限制是什么?

单选题 · mid

  • A.只能用于 64 位寄存器
  • B.常量不能作为目标操作数← 正确答案
  • C.必须配合内存操作数
  • D.只能用于跳转类指令

答案:B。立即数是只读常量,没有可写的存储空间,因此不能作为目标操作数。它可以用在任何位宽寄存器上,也无需配合内存,更不限于跳转指令。

Q6. 相比立即寻址,寄存器寻址的最大优势是?

单选题 · mid

  • A.指令编码长度绝对更短
  • B.可承载可变值且无需访存← 正确答案
  • C.支持任意位宽的数据
  • D.编译时无需确定数据类型

答案:B。寄存器中的数据可在运行时被反复改写,且访问寄存器不经过内存,这是它相比“定死的常量”最核心的优势。编码长度不一定绝对更短,位宽有严格限制,类型在编译时仍需确定。

Q7. 关于寄存器寻址,下列哪些说法正确?

多选题 · mid

  • A.操作数保存在 CPU 内部← 正确答案
  • B.访问时无需内存总线← 正确答案
  • C.指令中编码寄存器编号← 正确答案
  • D.操作数编译后不可修改

答案:ABC。寄存器是 CPU 内部存储单元,访问它走内部电路而非内存总线,指令通过 ModRM 的寄存器字段编码编号。寄存器中的值可以被后续指令修改,D 错误。

Q8. 立即寻址适合哪些应用场景?

多选题 · hard

  • A.给变量赋编译期常量← 正确答案
  • B.设置掩码和标志位← 正确答案
  • C.循环体中的动态累加
  • D.构造固定的地址偏移← 正确答案

答案:ABD。立即寻址适合表达编译期就能确定的常量:初始化、掩码、标志位、地址偏移。循环体中的累加值在运行时不断变化,必须用寄存器寻址。

Q9. 执行 MOV AL, 5 后,EAX 寄存器的高 3 个字节有何变化?

单选题 · hard

  • A.被自动清零
  • B.保持原值不变← 正确答案
  • C.被置为 0xFFFFFF
  • D.变成未定义值

答案:B。x86 中写 AL 寄存器只影响 EAX 的低 8 位,高 24 位保持不变。这是寄存器寻址的“部分写”特性,也是位宽匹配的体现。

Q10. 立即寻址与寄存器寻址的共同点包括哪些?

多选题 · hard

  • A.都不需要访问内存← 正确答案
  • B.都可作为目标操作数
  • C.速度均快于内存寻址← 正确答案
  • D.操作数均存于寄存器

答案:AC。二者都不依赖内存总线,速度显著快于内存寻址。但立即数是只读常量,不能作为目标操作数;它也不存于寄存器,而是编码在指令中。故 A、C 正确。