我听说 Motorola 68000 和 Intel x86 架构处理左移溢出的方式不同。特别是 68k LSL 与英特尔 SAL/SHL 汇编指令。

有谁知道这个的具体情况吗?他们是否设置了不同的标志,或者以不同的方式设置了它们?我试图在参考手册中查找这一点,但我没有看到任何区别。为什么人们想要以不同的方式处理这种情况?

有帮助吗?

解决方案

X 位不涉及。68000 标志的混淆是因为有两个左移指令:

  • LSL,逻辑左移,清除溢出标志。
  • ASL(算术左移)如果 MSB 在移位期间的任何时间改变符号,则设置 V 标志。

x86 指令集远没有那么强大。如果移位计数 = 1,则溢出标志 OF = (MSB XOR CF),即如果 MSB 由于 1 位移位而改变符号,则 OF = 1,否则 OF = 0。

如果移位计数 >1,则 OF 为 不明确的。 (英特尔 SHL 文档的 HTML 摘录).

其他提示

CPU 的程序员手册有详细说明:

摩托罗拉 68K:

X — Set according to the last bit shifted out of the operand; 
    unaffected for a shift count of zero. 
N — Set if the result is negative; cleared otherwise. 
Z  — Set if the result is zero; cleared otherwise. 
V — Always cleared. 
C — Set according to the last bit shifted out of the operand; 
    cleared for a shift count of zero. 

英特尔x86:

  • CF 标志包含从目标操作数移出的最后一位的值;对于计数大于或等于目标操作数的大小(以位为单位)的 SHL 和 SHR 指令,它是未定义的。
  • OF 标志仅对 1 位移位影响(请参阅上面的“说明”);否则,它是未定义的。
  • 根据结果​​设置 SF、ZF 和 PF 标志。如果计数为 0,则标志不受影响。
  • 对于非零计数,AF 标志未定义。

所以对溢出标志的处理是不同的。它会让您知道在 x86 中乘以 2(一位左移)是否导致溢出。我不知道为什么它如此特定于 1 位移位。我猜测(这只是猜测)OF 标志是根据“最后”位移位设置的 - 这可能并不表明整个操作是否溢出,因此英特尔只是将其记录为“未定义”。

(是的,我检讨从1979年我的摩托罗拉68000参考。)

也许你在想什么的是68000的相当奇怪的X位。该扩展位基本上是C(进位)位的副本,但不会受非算术指令。 假设你要添加的12字整数,例如。在x86上,你会看到类似这样的:

  .
  .
loop:
  ADC AX,[SI]    ; recycle carry-out from last iter as carry-in to this one

  LEA SI, [SI+2] ; flags untouched
  INC BX         ; BX is loop index.  sets all flags except CF
  CMP BX, 12     ; doh, changes carry (BUG)
  JB  loop

此代码不工作,因为比较指令渣土了进位标志。这是一个原因,为什么loop指令是历史上非常有用,而无需修改标志CX计数下降到零。倒计时到零dec / jnz也可以,但是会导致对现代局部x86的标志摊位。不幸的是 loop现在是慢得,所以有使约486这样的循环,直到SandyBridge的好方法。

但是,在68000:

  .
  .
loop:
  ADDX.W (A0)+, D0   ; both C and X set the same
  INC.W  D7          ; D7 is loop index
  CMP.W  #12, D7     ; harms C, but X left intact
  BCC  loop

摩托罗拉还以为他们在做程序员的青睐,但X位企业最终造成更多的混乱比它的价值。

scroll top