在x86-64索引寻址模式下使用8位寄存器

Bee*_*ope 5 x86 x86-64

是否可以al, ah, bl, bh, r8b在x86-64中的索引寻址模式下使用8位寄存器()?例如:

mov ecx, [rsi + bl]
mov edx, [rdx + dh * 2]
Run Code Online (Sandbox Code Playgroud)

特别是,这将允许您使用寄存器的底部8位作为0-255偏移量,这对某些内核可能很有用.

我倾注了英特尔的手册,他们并没有明确说明这一点,但他们给出的所有例子都只有32位或64位的基址和索引寄存器.在32位代码中,我只看到16位或32位寄存器.看一下mod-r/m和SIB字节编码的细节似乎也指向"不",但这足够复杂,有足够的角落情况,我不确定我是否正确.

我最感兴趣的是x86-64行为,但当然如果它只能在32位模式下我想知道.

作为一个太小而且与之相关的附加问题,可以使用16位寄存器作为基数还是索引?例如,mov rax, [rbx + cx].我的调查指出了与上面基本相同的答案:可能不是.

Bee*_*ope 5

不,您不能在64位模式下的寻址计算中使用8位或16位寄存器,也不能在32位模式下使用8位寄存器.你可以使用在32位模式的16位寄存器,和32位寄存器在64位模式下,通过使用所述的0x67 地址大小前缀字节.

该表很好地总结了操作数和地址大小的各种选项.一般模式是默认地址大小与当前模式相同(即32位模式下为32位,64位模式下为64位)1,然后如果0x67包含前缀,则地址大小更改为通常大小的一半(即,32位模式下为16位,64位模式下为32位).

下面是上面仅示出64位长模式行为,对于的各种值链接的全表的摘录REX.W,0x66操作数和0x67地址大小前缀:

?????????????????????????????????????????????????????????????????????
? 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       ?
?????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

1这似乎是显而易见的,但它是相反的方式操作数的大小在64位模式下工作:最默认为32位,即使是在64位模式和REX前缀是需要他们提升到64位.

2 有些指令默认为64位操作数大小没有任何REX前缀,特别是push,pop,call和条件跳转,并且如下面彼得所指出的,这导致奇怪的情况,其中至少一些这样的指令(pushpop包括)不能被编码使用32位操作数,但可以使用16位操作数(带0x66前缀).