在英特尔针对英特尔 64 和 IA-32 指令集的手册 3.1.1.5 节中,它在指令摘要表中引入了 64/32 位模式列。
对于 64 位模式支持,它说:
- I - 不支持
- N.E. - 表示指令语法在 64 位模式下不可编码(它可能表示其他模式下有效指令序列的一部分
指令在 64 位模式下不可编码与指令在 64 位模式下不受支持有什么区别?
目前还不完全清楚英特尔正在做出什么区分,或者为什么做出这种区分是有用的1. 看起来 Invalid 仅用于会 #UD(非法指令错误)的操作码,这就是为什么他们使用 N.E. 即使在没有其他方法使用该操作数大小对指令进行编码的情况下也是如此。
唔...... 它可以表示其他模式下有效指令序列的一部分
这是有道理的,我认为如果他们说">在这种模式下",请匹配他们的文档。 例如0x1F
在 64 位模式下不是有效的操作码或前缀,但在其他模式下表示pop ds
。
脚注 1:当然,没有面向未来的保证 #UD 故障- 未来 CPU 上的未来 ISA 扩展可能会将未使用的操作码重新用于 64 位模式下的某些内容,从而有效地将无效更改为 N.E. (面向未来的 #UD 方法是0F 0B
操作码,记录为ud2
)
无效的一个例子是 64 位模式下的aam
(直接除法):在该模式下根本没有指令编码,并且操作码未使用。
N.E.的一个例子是inc r32
缩写形式0x40+rd,64位模式将其重新用作REX前缀(以及0x48+rddec
)。inc eax
也是可编码的,但不能使用该操作码。
同样,inc r/m64
被列为兼容/传统模式的N.E.;即它仅在长模式下通过REX前缀可用。
pop
在一个表中提供了这两种类型的示例:
- 不再有任何方法可以使用任何操作数大小执行
pop ds
(或 ES/SS),并且这些操作码被释放以供将来使用,因此它在 64 位模式下是"无效的"。 (POP CS从来都不是有效的,除了一些没有文档的/早期的8086;只有像RETF这样的东西,它将CS:[ER]IP放在一起,而不仅仅是CS。 pop fs
和 GS 可以使用 16 位或 64 位操作数大小来完成,但不能使用 32 位,因此
"0F A1 POP FS
...将堆栈顶部弹出到 FS 中;将堆栈指针递增 32 位">
行的表具有 N.E. 用于 64 位模式,对兼容/旧版有效。 而...64位行正好相反,64有效,32无效。 (有趣的是,当RSP以字节而不是位计数时,他们写"64位"而不是"8"。
pop r32
和pop r/m32
都列为 64 位模式的 NE,并非无效,尽管无法在该模式下对pop eax
或pop dword [rdi]
进行编码。所以看起来无效是关于操作码,而不是指令。
(即使是 REX。对于默认值为 64 的操作码,W=0 不会将操作数大小覆盖为 32 位,但操作数大小66
前缀确实照常工作,使推送/弹出 16 位。 尽管"描述"文本说操作数大小可能被 REX 覆盖。W - 这似乎是在谈论一般的指令,正如当前代码段的 D 标志所暗示的那样。
也许是因为 64 位模式仍然可以使用相同的操作码弹出其他 2 种大小(64 位或 16 位)? 还是其他 2 种尺寸的带流行音乐的 r/m? 例如pop ax
和pop word [rdi]
在 64 位模式下有效,当然还有pop rax
。
这与他们列出pop ds
的方式一致。
我想知道movsxd r64, r/m32
在 16/32 位模式下是无效还是 N.E.,因为相同的操作码在 64 位模式(ARPL r,r/m16 - http://ref.x86asm.net/coder32.html#x63)之外具有不同的含义。
但相反,它只是 32 位模式的NE,movsxd r32, r/m32
被列为两种模式的"有效"!那一定是一个错误,因为它显然是错误的。 兼容/传统模式下的操作码63
是 ARPL。 (列为 N.E. (64)/有效 (32),其操作部分提到了 64 位模式的 movsxd。因此,N.E.将匹配他们的模式,将其用于具有其他含义但不出错的事情。
(像NASM和YASM这样的现实世界汇编程序即使在64位模式下也拒绝movsxd eax, ecx
;他们想要一个64位的目标,拒绝让你把它作为一个更糟糕的mov eax, ecx
,即使这在机器代码中是可能的,但英特尔的手册不鼓励这样做。 不幸的是,movsxd
需要一个 REX 前缀来达到其唯一目的:将 32 符号扩展为 64。 不是堆栈或分支操作,我想AMD认为操作数大小默认为64位更一致。