首页 > 解决方案 > 带有段寄存器的 x86-64 MOV 指令上的 REX.W 前缀

问题描述

我正在阅读x86/x64 开发人员手册,试图理解指令编码,但被段寄存器中的 mov 弄糊涂了,即本页的第 12 和第 13 形式。具体有两个问题:

(1) 两者都标有 REX.W 前缀,但据我了解,此标志仅在操作数大小为 64 位时使用。我知道为什么它应该与 r64 一起使用,但除此之外,为什么这两条指令都标有 REX.W 前缀?

(2) 两条指令中都有一个m16目的地,不是重复吗?为什么这两个指令首先是分开的?

对于 (2),我能想到的一个原因是,在第一种形式中,可以使用 66H 前缀选择 r16/r32,而当 REX.W 存在时(对于 r64)会忽略 66H。但是 66H 似乎也不适用于 m16,为什么它包含在第二种形式(r64/m16)中?

标签: assemblyx86-64instructionsmachine-code

解决方案


我认为这是一个编辑错误。我认为应该从第 12 行省略 REX 前缀,以与第 11 行的 16 位形式和第 13 行的 64 位形式(就像有 16-32 和 64 位形式对于其他变体)。

(也许有人试图将这三种形式组合成一行。该条目的“描述”列显示“将零扩展 16 位段寄存器移动到 r16/r32/ r64 /m16 ”,所以这与有人开始合并行,然后意识到该r64行应该是单独的,但忘记从 16/32 位行中删除 REX.W。)

我认为 m16 出现在所有三种形式上的原因是从段寄存器到内存的移动始终是 16 bits,无论操作数大小如何。 mov来自 SR 是一个奇怪的指令。


没有理由使用 64 位形式:所有支持 64 位模式的 CPU 都零扩展至没有前缀的完整寄存器大小。

对于 ... 和所有 Intel 64 处理器,目标寄存器的高位为零。

例外情况是比 Pentium Pro 更早的仅 32 位 CPU,以及同样仅 32 位的Quark(基于 P5)

我没有查看 AMD 手册以查看是否有任何 AMD64 CPU 可能会留下未定义或未修改的 RAX 的高 6 字节8c d8mov eax,ds没有前缀)。但是 Intel 的手册很清楚,所有 Intel64 CPU 都将零扩展为 32 位(因此在写入 32 位寄存器时总是隐含到 64 位)。


操作数大小前缀可66h用于编码66 8c d8( mov ax,ds),它使 RAX 的高字节保持不变(就像总是写入 16 位寄存器一样)。

通常你永远不会想要这个,但操作数大小前缀确实会影响mov reg, SR与 REX.W 不同。


推荐阅读