这些是MOV
指令操作码,来自 * 英特尔® 64和IA-32架构软件开发人员手册 *C7 /0 id MOV r/m32, imm32 MI Valid Valid Move imm32 to r/m32.
B8+ rd id MOV r32, imm32 OI Valid Valid Move imm32 to r32.
我发送两个asm行到反汇编程序
mov eax, 0x11223344
0: b8 44 33 22 11 mov eax,0x11223344
mov DWORD PTR [eax], 0x11223344
0: 67 c7 00 44 33 22 11 mov DWORD PTR[eax], 0x11223344
我想问的问题是:
为什么操作码是C7
r/m32, imm32
而不是仅内存m32,imm32
?
是否有任何时候我们使用C7
代替B8
来表示mov r32, imm32
?
1条答案
按热度按时间f8rj6qna1#
为什么操作码是
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
字节。