我正在阅读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)包含了它?
答案 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 d8
(mov eax,ds
(无前缀))保留未定义或未修改的RAX高6字节。但是,英特尔的手册明确规定,所有Intel64 CPU都将零扩展为32位(因此,与编写32位寄存器时一样,隐式扩展为64位)。
66h
操作数大小前缀可用于编码66 8c d8
(mov 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及更高版本),而不会影响操作数的大小。