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

问题描述 投票:2回答:2

我正在阅读x86/x64 developer's manual试图理解指令编码并被来自段寄存器的mov混淆,即this page上的第12和第13种形式。有两个具体问题:

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

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

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

assembly x86-64 instructions machine-code
2个回答
3
投票

我认为那是一个编辑错误。我认为REX前缀应该从第12行中省略,与第11行的16位形式和第13行的64位形式相比(正如16-32-和64位形式一样)对于其他变种)。

(也许有人试图将这三种形式合并为一行。该条目的“描述”栏中写着“将零扩展16位段寄存器移至r16 / r32 / r64 / m16”,这与某人开始一致合并行然后意识到r64行应该是分开的,但忘记从16/32位行中删除REX.W。)

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


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

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

例外情况是比Pentium Pro早的32位CPU,以及仅32位的Quark (based on P5)

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


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

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


1
投票

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

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

但是,REX前缀可能在那里(如果在64位模式下)但是.W = 0,在这种情况下,操作数大小将是32位。也就是说,除非还有操作数大小前缀(66H),它将把它翻转到16位。

并且可能存在REX。[RXB]来改变操作数地址编码(使用寄存器r8及更高版本)而不影响操作数大小。

© www.soinside.com 2019 - 2024. All rights reserved.