N.E 有什么区别?我在英特尔手册中?

What is the difference between N.E. and I in Intel manual?

Intel's manual for Intel 64 and IA-32 instruction set3.1.1.5节中,在指令摘要中引入了64/32位模式栏目table。

对于 64 位模式支持,它表示:

  • I - Not supported
  • N.E. - Indicates an instruction syntax is not encodable in 64-bit mode (it may represent part of a sequence of valid instructions in other modes

在 64 位模式下不可编码的指令和在 64 位模式下不支持的指令有什么区别?

目前还不完全清楚英特尔到底做了什么区分,或者为什么区分是有用的1。看起来 Invalid 仅用于将 #UD(非法指令错误)的操作码,这就是他们使用 N.E 的原因。即使在没有 other 方法来使用该操作数大小对指令进行编码的情况下。

N.E. ... it may represent part of a sequence of valid instructions in other modes

这是有道理的,如果他们说“在 this 模式下”,我认为与他们的文档相匹配。例如0x1Fnot a valid opcode or prefix in 64-bit mode,但在其他模式下表示 pop ds

脚注 1:当然 #UD 没有未来的保证 - 未来 CPU 上的未来 ISA 扩展可能将未使用的操作码重新用于 64 位模式,有效地将 Invalid 更改为 N.E。 (面向未来的#UD 方式是 the 0F 0B opcode, documented as ud2


无效的一个例子是64位模式下的aam(立即除法)没有编码在该模式下根本没有指令,并且操作码未使用。

N.E的例子。 inc r32 short form 0x40+rd 是 64 位模式(连同 0x48+rd dec)重新用作 REX 前缀的。 inc eax 也是可编码的,但不能使用 that 操作码。

同样,inc r/m64 被列为 N.E。对于 compat/legacy 模式;即它仅在长模式下可用,通过 REX 前缀。

pop 两种例子合二为一 table:

  • 不再有任何方法可以对任何操作数大小执行 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 位
    table 行有 N.E。对于 64 位模式,对 compat/legacy 有效。而 ... by 64 bits 行是相反的,对 64 位有效,对 32 位无效。(有趣的是,当 RSP 计数时,他们写“by 64 bits”而不是“by 8”以字节为单位,而不是位。)

pop r32pop r/m32 都列为 N.E。对于 64 位模式,并非无效,尽管在该模式下无法编码 pop eaxpop dword [rdi]所以看起来无效是关于操作码,而不是指令。

(对于默认为 64 的操作码,即使 REX.W=0 也不会将操作数大小覆盖为 32 位,但是 66 操作数大小前缀确实可以照常工作使 push/pop 16 位。尽管“描述”文本说操作数大小可能被 REX.W 覆盖 - 这似乎是在谈论一般指令,正如当前代码段所暗示的那样D旗。)

可能是因为 64 位模式仍然可以使用相同的操作码弹出其他 2 种大小(64 或 16 位)?或者其他 2 种尺寸的 r/m 有 pop?例如pop axpop word [rdi] 在 64 位模式下有效,当然还有 pop rax

这与他们列出的方式一致 pop ds


我想知道是否 movsxd r64, r/m32 would be Invalid or N.E. in 16/32-bit mode, because the same opcode has a different meaning outside of 64-bit mode (ARPL r,r/m16 - http://ref.x86asm.net/coder32.html#x63).

但它只是 N.E。对于 32 位模式,movsxd r32, r/m32 在两种模式下都被列为“有效”! 这一定是一个错误,因为它显然是错误的。 compat/legacy 模式下的操作码 63ARPL。 (它被列为 N.E。(64) / 有效 (32),并且其操作部分提到 movsxd 用于 64 位模式。)因此 N.E。会匹配他们将它用于具有其他含义但不会出错的事物的模式。

(像 NASM 和 YASM 这样的现实世界的汇编器甚至在 64 位模式下也拒绝 movsxd eax, ecx;他们想要一个 64 位的目的地,拒绝让你把它当作更糟糕的 mov eax, ecx 尽管 在机器代码中是 可能的,但英特尔的手册不鼓励这样做。movsxd 不幸的是需要一个 REX 前缀来服务于它的唯一目的:符号扩展 32 到 64 . 不是堆栈或分支操作我猜 AMD 决定将操作数大小默认为 64 位更一致。)