【发布时间】:2017-01-03 13:06:39
【问题描述】:
是否可以在 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 字节编码的细节似乎也指向“否”,但这已经足够复杂,有足够多的极端情况,我不确定我是否做对了。
我最感兴趣的是 x86-64 行为,但当然,如果它在 32 位模式下可行,我只想知道。
作为一个附加问题太小并且与值得另一篇文章相关 - 16 位寄存器可以用于基址或索引吗?例如,mov rax, [rbx + cx]。我的调查指向与上述基本相同的答案:可能不是。
【问题讨论】:
-
不可能,两个寄存器的大小都必须与地址大小相同,因此也排除了
[reg16 + disp32]。你需要一个movzx。显示编码的表格确实列举了所有种可能的编码。 -
是的,表格显示了诸如 rax/eax/ax/al 之类的内容。所以它让我的希望保持在高位。您可以计算位并看到只有三个可用于选择寄存器以猜测只有一种大小可用,但是您必须检查所有不同字节的大小变化位,并读取所有 REX 前缀的详细信息,等等。但是,是的,我已经很怀疑了。
-
寻址模式表不会显示
al,因为没有 8 位寻址模式。不过,我理解这个问题的动机:当我刚接触 x86 时,我一直想知道是否有我不知道的寻址模式。但事实证明只有[base + idx*scale + disp8/disp32],或者省略这三个组件中的一个或两个的任何子集。 (加上 64 位模式下的相对于 RIP)。这就是 I wrote this answer 的原因,这可能是一个很好的文档主题。 -
对。不过,我从来没有在英特尔文档中找到适合 64 位寻址模式的表格。当前英特尔开发手册第 2A 卷第 2.1.5 节中有表 2-3,其中涵盖了 32 位情况,但我从未找到 64 位情况的对应表。我在搜索的早期被this page 进一步抛弃,这清楚地表明
[disp + reg8 + reg32*scale]寻址模式,这正是我想要的(在32 位模式下)。看起来这是一个错字,他们的意思是disp8 + reg32 ...。 -
嗯,是
xlat(或xlatb)的奇怪案例。它确实(隐式地)使用8 位寄存器al作为[r/e]bx隐式指向的表的索引。不幸的是,它非常浪费编码空间,并且只能加载到al寄存器中。
标签: assembly x86 x86-64 addressing-mode