REX.W 带段寄存器的 x86-64 MOV 指令前缀

REX.W prefix on x86-64 MOV instruction with segment register

我正在阅读x86/x64 developer's manual trying to understand instruction encoding and got confused by the mov from segment register, i.e. the 12th and 13th form on this page。具体有两个问题:

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

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

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

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

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

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


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

The upper bits of the destination register are zero for ... and all Intel 64 processors.

例外情况是早于 Pentium Pro 的仅 32 位 CPU,Quark (based on P5) 也仅是 32 位。

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


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

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

几十年来,该手册因其拼写错误和(自我)不一致而臭名昭著。而且这不是唯一一个草率的,第一个或最后一个。所以,应该不会有太多惊喜,除非它是您阅读的第一本手册。

是的,REX.W 对于小于 64 位的操作数没有多大意义。

然而,REX 前缀可能存在(如果在 64 位模式下)但 .W=0 并且在这种情况下操作数大小将为 32 位。也就是说,除非还有操作数大小前缀 (66H),这会将其翻转为 16 位。

并且可能有 REX.[RXB] 在不影响操作数大小的情况下更改操作数地址编码(使用寄存器 r8 及以后)。