在x86-64索引寻址模式

时间:2016-08-26 19:23:39

标签: x86 x86-64

是否可以在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]。我的调查指出基本上与上面相同的答案:可能不是

1 个答案:

答案 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位长模式行为,适用于0x67REX.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 ║ ╚════════╩═════════════╩═════════════╩═══════════════╩══════════════╝ 前缀,特别是REXpushpop和条件跳转,正如Peter在下面指出的那样,这导致奇怪的情况,其中至少有一些指令(包括callpush)不能被编码为使用32位操作数,但可以使用16位操作数(带pop前缀)。