这些是 * 英特尔® 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
?
1条答案
按热度按时间xoshrz7s1#
为什么操作码是
C7
r/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.Wmov r/m64, sign_extended_imm32
。REX.WB8+rd
是10字节的mov r64, imm64
。当然,对于适合32位零扩展的64位值,比如
mov rax, 0x0000000012345678
,实际上应该使用5字节的mov eax, 0x12345678
。NASM默认会这样做,GAS默认也会这样做,使用as -Os
或gcc -Wa,-Os
。其他汇编器不会这样做,所以由程序员决定是否对非大型非负64位常量使用32位操作数大小。有关示例和更多详细信息,请参见
顺便说一句,在64位模式下使用
[eax]
作为目的地有点奇怪;像[rax]
这样的64位地址大小具有更紧凑的机器码,并且通常您的地址被适当地扩展到64位寄存器,即使您将它们打包到更窄的存储空间中,这就是为什么您的反汇编程序具有额外的67
字节。