是否可以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].我的调查指出了与上面基本相同的答案:可能不是.
不,您不能在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和条件跳转,并且如下面彼得所指出的,这导致奇怪的情况,其中至少一些这样的指令(push和pop包括)不能被编码使用32位操作数,但可以使用16位操作数(带0x66前缀).