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 d8
(mov eax,ds
没有前缀)保留未定义或未修改 RAX 的高 6 字节的可能性。但是 Intel 的手册很清楚,所有 Intel64 CPU 都将零扩展到 32 位(因此在写入 32 位寄存器时像往常一样隐式扩展到 64 位)。
66h
操作数大小前缀可用于编码 66 8c d8
(mov ax,ds
),使 RAX 的高位字节保持不变(就像写入 16 位寄存器一样) .
通常你不会想要这个,但是操作数大小前缀 确实 影响 mov reg, SR
不同于 REX.W.
几十年来,该手册因其拼写错误和(自我)不一致而臭名昭著。而且这不是唯一一个草率的,第一个或最后一个。所以,应该不会有太多惊喜,除非它是您阅读的第一本手册。
是的,REX.W 对于小于 64 位的操作数没有多大意义。
然而,REX 前缀可能存在(如果在 64 位模式下)但 .W=0 并且在这种情况下操作数大小将为 32 位。也就是说,除非还有操作数大小前缀 (66H),这会将其翻转为 16 位。
并且可能有 REX.[RXB] 在不影响操作数大小的情况下更改操作数地址编码(使用寄存器 r8 及以后)。
我正在阅读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 d8
(mov eax,ds
没有前缀)保留未定义或未修改 RAX 的高 6 字节的可能性。但是 Intel 的手册很清楚,所有 Intel64 CPU 都将零扩展到 32 位(因此在写入 32 位寄存器时像往常一样隐式扩展到 64 位)。
66h
操作数大小前缀可用于编码 66 8c d8
(mov ax,ds
),使 RAX 的高位字节保持不变(就像写入 16 位寄存器一样) .
通常你不会想要这个,但是操作数大小前缀 确实 影响 mov reg, SR
不同于 REX.W.
几十年来,该手册因其拼写错误和(自我)不一致而臭名昭著。而且这不是唯一一个草率的,第一个或最后一个。所以,应该不会有太多惊喜,除非它是您阅读的第一本手册。
是的,REX.W 对于小于 64 位的操作数没有多大意义。
然而,REX 前缀可能存在(如果在 64 位模式下)但 .W=0 并且在这种情况下操作数大小将为 32 位。也就是说,除非还有操作数大小前缀 (66H),这会将其翻转为 16 位。
并且可能有 REX.[RXB] 在不影响操作数大小的情况下更改操作数地址编码(使用寄存器 r8 及以后)。