【问题标题】:What is the difference between N.E. and I in Intel manual?N.E. 和有什么区别我在英特尔手册中?
【发布时间】:2021-03-10 11:32:46
【问题描述】:

Intel's manual for Intel 64 and IA-32 instruction set第3.1.1.5节中,在指令汇总表中引入了64/32位模式列。

对于 64 位模式支持,它说:

  • 我 - 不支持
  • 东北- 表示指令语法在 64 位模式下不可编码(它可能代表其他模式下有效指令序列的一部分

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

【问题讨论】:

    标签: assembly x86 intel instruction-set instructions


    【解决方案1】:

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

    N.E. ...它可能代表其他模式下一系列有效指令的一部分

    这是有道理的,如果他们说“在 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


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

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

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

    pop 在一张表中有这两种类型的示例:

    • 不再有任何方法可以对任何操作数大小执行 pop ds(或 ES/SS),并且这些操作码被释放以供将来使用,因此它在 64 位模式下是“无效的”。 (除了一些未记录的/早期的 8086 之外,pop cs 从未有效;只有像 retf 这样将 CS:[ER]IP 设置在一起的东西,而不仅仅是 CS。)
    • pop fs 和 GS 可以使用 16 位或 64 位操作数大小完成,但不能使用 32 位,所以
      "0F A1 POP FS ... 将栈顶弹出到 FS;将栈指针递增 32 位"
      表的行有 N.E.对于 64 位模式,对兼容/旧版有效。而 ... by 64 bits 行是相反的,对 64 有效,对 32 无效。(有趣的是,当 RSP 以字节为单位时,他们写的是“by 64 bits”而不是“by 8”,不是比特。)

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

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

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

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


    我想知道 movsxd r64, r/m32 是 Invalid 还是 N.E.在 16/32 位模式下,因为相同的操作码在 64 位模式之外具有不同的含义(ARPL r,r/m16 - http://ref.x86asm.net/coder32.html#x63)。

    但它只是 N.E.对于 32 位模式,movsxd r32, r/m32 在两种模式下都被列为“有效”! 这肯定是一个错误,因为它显然是错误的。兼容/传统模式下的操作码 63ARPL。 (列为 N.E. (64) / Valid (32),其操作部分提到 movsxd 用于 64 位模式。)所以 N.E.将匹配他们将其用于具有其他意义但没有错误的事物的模式。

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

    【讨论】:

    • aam (和类似的)是可编码的,只是在 64 位模式下不支持/无效。不同之处在于 NE 指令被误解为其他东西(即使您欺骗了汇编器发出它),而无效的(再次您必须绕过汇编器)则抛出#UD。我仍然不清楚为什么像 aaaaam 这样的指令现在无效,可能是为了释放一些操作码空间?
    • 您仍然可以移入/移出这些段 regs(mov to/from Sreg 有两个操作码),但您几乎不想这样做,因此他们释放了该编码空间以供将来使用。 IDK 为什么他们一直推/弹出 FS 和 GS;也许他们没有定义 MSR 来控制他们的基址寄存器?还是因为那些是 2 字节 0F ?操作码因此价值较低。
    • @MargaretBloom 它们既不可编码也不支持。只是操作码空间尚未分配,否则。其他说明(如 arplboundldsles)已经有了。
    • @fuz 这个问题(和这个答案)的重点是澄清英特尔的术语:操作码将被重用 => 不支持,#UD 和硬故障,操作码已重用 => 不可编码,完全不同的指令,无声的失败。
    • @PeterCordes 从技术上讲,这些扩展也可以在 16 位模式下工作,只是不能在实模式或虚拟 8086 模式下工作。不确定您是否可以在 SMM 模式下使用它们。
    猜你喜欢
    • 2013-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-25
    • 2014-08-02
    • 2010-11-13
    • 1970-01-01
    • 2021-07-19
    相关资源
    最近更新 更多