4

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

有人知道这件事的具体情况吗?他们设置不同的标志,还是设置不同的标志?我试图在参考手册中查找这一点,但我没有发现任何区别。为什么要以不同的方式处理这种情况?

4

3 回答 3

6

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

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

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

如果移位计数 >1,则 OF未定义。英特尔 SHL 文档的 HTML 摘录)。

于 2009-11-11T20:48:24.037 回答
4

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 标志未定义。

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

于 2009-11-11T03:24:19.410 回答
3

(是的,我正在查看 1979 年的摩托罗拉 68000 参考。)

可能你想到的是68000的相当奇怪的X位。eXtend 位本质上是 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 位业务最终导致的混乱比它的价值还多。

于 2009-11-11T04:29:34.047 回答