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

时间:2019-04-05 02:12:15

标签: assembly x86-64 instructions machine-code

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

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

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

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

2 个答案:

答案 0 :(得分:3)

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

(也许试图将这三种形式组合成一行。该条目的“说明”列显示“ 将零扩展的16位段寄存器移至r16 / r32 / r64 < / strong> / m16 ”,因此这与开始合并行然后意识到r64行应该分开但忘记将REX.W从16 / 32-位行。)

我认为m16出现在所有三种形式上的原因是从段寄存器到内存的移动始终为16位,而与操作数的大小无关。 SR的mov是很奇怪的指令。


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

  

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

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

我没有检查AMD手册,以查看是否有任何AMD64 CPU可能为8c d8mov eax,ds(无前缀))保留未定义或未修改的RAX高6字节。但是,英特尔的手册明确规定,所有Intel64 CPU都将零扩展为32位(因此,与编写32位寄存器时一样,隐式扩展为64位)。


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

通常您永远都不想这样做,但是与REX.W不同,操作数大小前缀 会影响mov reg, SR

答案 1 :(得分:1)

数十年来,该手册因其错别字和(自)不一致而臭名昭著。它不是唯一的,第一个或最后一个马虎的人。因此,除非这是您有史以来的第一本手册,否则应该没有什么惊喜。

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

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

可能会有REX。[RXB]来更改操作数地址编码(以使用寄存器r8及更高版本),而不会影响操作数的大小。