题
我听说 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 的程序员手册有详细说明:
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.
- 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位企业最终造成更多的混乱比它的价值。