assembly MOV r/m32,imm 32与MOV r32,imm 32之间的操作码差异

jgwigjjp  于 2023-02-04  发布在  其他
关注(0)|答案(1)|浏览(157)

这些是 * 英特尔® 64和IA-32架构软件开发人员手册 * 中的MOV指令操作码:
B8+ rd id MOV r32, imm32 OI Valid Valid Move imm32 to r32.
C7 /0 id MOV r/m32, imm32 MI Valid Valid Move imm32 to r/m32.
我按如下方式拆卸:

0:  b8 44 33 22 11          mov    eax, 0x11223344
0:  67 c7 00 44 33 22 11    mov    DWORD PTR[eax], 0x11223344

我想问的问题是:

  • 为什么使用C7操作码寄存器/内存(r/m32, imm32),而不是仅内存(m32, imm32)?
  • 是否有任何时候我们使用C7进行仅寄存器(r32, imm32),而不是使用B8
xoshrz7s

xoshrz7s1#

为什么操作码是C7r/m32, imm32而不是仅内存m32,imm32
因为它可能需要额外的晶体管来处理ModRM上的特殊情况和#UD故障。mode = 11(寄存器目标),而不是像其他具有mov r/m32, r32等只写目标的指令那样运行它。
是否有任何时候我们可以将C7用于mov r32, imm32而不是B8
在32位模式下,当做出此设计选择时,没有。除了对齐后续代码,而不是单独的nop-What methods can be used to efficiently extend instruction length on modern x86?
在64位模式下,您可以使用带有寄存器目标的C7,但只能使用雷克斯.W前缀。mov rax, -123的最短编码是REX.W mov r/m64, sign_extended_imm32。REX.W B8+rd是10字节的mov r64, imm64
当然,对于适合32位零扩展的64位值,比如mov rax, 0x0000000012345678,实际上应该使用5字节的mov eax, 0x12345678。NASM默认会这样做,GAS默认也会这样做,使用as -Osgcc -Wa,-Os。其他汇编器不会这样做,所以由程序员决定是否对非大型非负64位常量使用32位操作数大小。
有关示例和更多详细信息,请参见

顺便说一句,在64位模式下使用[eax]作为目的地有点奇怪;像[rax]这样的64位地址大小具有更紧凑的机器码,并且通常您的地址被适当地扩展到64位寄存器,即使您将它们打包到更窄的存储空间中,这就是为什么您的反汇编程序具有额外的67字节。

相关问题