是否可以在x86-64中的索引寻址模式下使用8位寄存器(al, ah, bl, bh, r8b
)?例如:
mov ecx, [rsi + bl]
mov edx, [rdx + dh * 2]
特别是,这将允许您使用寄存器的底部8位作为0-255偏移量,这对某些内核可能很有用。
我倾注了英特尔的手册,他们并没有明确说明这一点,但他们提供的所有例子都只有32位或64位的基本和索引寄存器。在32位代码中,我只看到16位或32位寄存器。看一下mod-r / m和SIB字节编码的细节似乎也指向" no"但是那个复杂到足够多的角落情况我不确定我是否正确。
我最感兴趣的是x86-64行为,但当然如果它只能在32位模式下使用,我想知道。
作为一个附加问题太小而且与另一个帖子有关 - 可以将16位寄存器用于基数或索引吗?例如,mov rax, [rbx + cx]
。我的调查指出基本上与上面相同的答案:可能不是。
答案 0 :(得分:5)
不,您不能在64位模式下的寻址计算中使用8位或16位寄存器,也不能在32位模式下使用8位寄存器。通过使用.jpg
地址大小前缀,可以在32位模式下使用16位寄存器,在64位模式下使用32位寄存器字节。
This table总结了操作数和地址大小的各种选项。一般模式是默认地址大小与当前模式相同(即32位模式下为32位,64位模式下为64位) 1 ,然后如果包含0x67
前缀,地址大小更改为通常大小的一半(即,32位模式下为16位,64位模式下为32位)。
以上是上面链接的完整表的摘录,仅显示64位长模式行为,适用于0x67
,REX.W
操作数和0x66
地址大小前缀的各种值:< / p>
0x67
1 这看起来很明显,但它与操作数大小在64位模式下的工作方式相反:大多数默认为32位,即使在64-位模式,需要 REX前缀将它们提升到64位。
2 Some instructions默认为64位操作数大小,没有任何╔════════╦═════════════╦═════════════╦═══════════════╦══════════════╗
║ REX.W ║ 0x66 prefix ║ 0x67 prefix ║ Operand size ║ Address size ║
║ ║ (operand) ║ (address) ║ (footnote 2) ║ ║
╠════════╬═════════════╬═════════════╬═══════════════╬══════════════╣
║ 0 ║ No ║ No ║ 32-bit ║ 64-bit ║
║ 0 ║ No ║ Yes ║ 32-bit ║ 32-bit ║
║ 0 ║ Yes ║ No ║ 16-bit ║ 64-bit ║
║ 0 ║ Yes ║ Yes ║ 16-bit ║ 32-bit ║
║ 1 ║ Ignored ║ No ║ 64-bit ║ 64-bit ║
║ 1 ║ ignored ║ Yes ║ 64-bit ║ 32-bit ║
╚════════╩═════════════╩═════════════╩═══════════════╩══════════════╝
前缀,特别是REX
,push
,pop
和条件跳转,正如Peter在下面指出的那样,这导致奇怪的情况,其中至少有一些指令(包括call
和push
)不能被编码为使用32位操作数,但可以使用16位操作数(带pop
前缀)。