i386 指令 "div ah" 没有意义吗?

Is the i386 instruction "div ah" pointless?

来自https://www.felixcloutier.com/x86/div

    ...
    temp ← AX / SRC;
    IF temp > FFH
        THEN #DE; (* Divide error *)
        ELSE
            AL ← temp;
            AH ← AX MOD SRC;
    FI;
    ...

对于 div ahSRC 将是 ah。恕我直言 temp 将始终大于 FFH 因此将引发异常,因为:

  1. AX = 256*AH+AL
  2. 温度=AX/AH=(256*AH+AL)/AH=256+AL/AH
  3. 温度结束FFH

我是不是漏掉了什么?

这是正确的,就像 div edx 它永远不会在没有错误的情况下使用。 2N/N => N-bit div 不溢出其商的标准是 high_half(dividend) < divisor,如您所示,因此使用 divisor = high(dividend) 将始终溢出(或除以零)。 Why "DIV EDX" in MASM always generates processor exception? 用另一种方式解释同样的事情。

有趣的一点是,这是一种保证 one-instruction 提高 #DE 的方法,但不需要任何指令将值放入寄存器。

(在保护模式下,int 0 不是 完全相同的东西。例如在 Linux 下,在 user-space int 0#GP -> SIGSEGV 因为 IDT 条目的权限,而实际除法异常将 #DE -> SIGFPE).


正如 Jester 指出的那样,该编码仅占 F6 /6 div r/m8 的 2^5 种可能编码中的一种,仅计算 ModRM 字节(不包括寻址模式可以使用的额外字节的大量可能性)。

使其成为 not-encodeable 需要解码器中的额外晶体管。然后你如何处理这个 2 字节的序列? #UD非法指令异常?这很愚蠢,只是让它在正常解码后引发 #DE 并像任何其他 div 指令一样进入执行单元。或者将它用于其他一些特殊的事情,例如 mfence?

div ah 的 2 字节机器代码实际上意味着一些完全不同的单指令,这可能并不是一个明智的设计决定。无论如何,那艘船以 8086 航行,它将升起 #DE,而不是 #UD;任何更改都会破坏向后兼容。由于为新操作码(例如 the illegal encodings of lds and les or whatever that VEX prefixes borrow)寻找新 coding-space 的侵入性较小的方法,Intel 和 AMD 还没有屈服于这种疯狂。那些 LES / LDS 32-bit-mode 编码已经引发了 #ud 而不是另一个异常,更重要的是有更多的备用位,所以 VEX 前缀有空间实际编码那些 2 或 3 字节前缀中的一些字段。