【问题标题】:carry/overflow & subtraction in x86x86中的进位/溢出和减法
【发布时间】:2012-02-16 11:10:15
【问题描述】:

我正在努力解决 x86 中的溢出和携带标志。

据我了解,对于有符号 2 的补数的加法,只能以四种方式之一生成标志(我的示例是 4 位数字):

  1. pos+pos = 否定(溢出)
    • 0111 + 0001 = 1000 (7 + 1 = -8)
  2. pos+neg = pos(进位)
    • 0011 + 1110 = 0001 (3 + -2 = 1)
  3. 否定+否定=否定(进位)
    • 1111 + 1111 = 1110 (-1 + -1 = -2)
  4. neg+neg = pos(溢出和进位)
    • 1000 + 1001 = 0001 (-8 + -7 = 1)

那么,在 x86 汇编中,从 A 中减去 B 会生成与添加 A 和 -B 相同的标志吗?

【问题讨论】:

标签: math x86 overflow twos-complement carryflag


【解决方案1】:

这是一个可能有帮助的参考表。这显示了 x86 上的 ADD 和 SUB 指令可能产生的 4 个算术标志的每个可能组合的示例。 'h' 'ud' 和 'd' 代表每个值的十六进制、无符号十进制和有符号十进制表示。例如,SUB 的第一行显示 0xFF - 0xFE = 0x1,没有设置任何标志。

但是,我认为短篇小说是亚历克斯的答案是正确的。

 ADD
       A                   B                   A + B              Flags  
 ---------------     ----------------    ---------------      -----------------
 h  |  ud  |   d   | h  |  ud  |   d   | h  |  ud  |   d   | OF | SF | ZF | CF
 ---+------+-------+----+------+-------+----+------+-------+----+----+----+---
 7F | 127  |  127  | 0  |  0   |   0   | 7F | 127  |  127  | 0  | 0  | 0  | 0
 FF | 255  |  -1   | 7F | 127  |  127  | 7E | 126  |  126  | 0  | 0  | 0  | 1
 0  |  0   |   0   | 0  |  0   |   0   | 0  |  0   |   0   | 0  | 0  | 1  | 0
 FF | 255  |  -1   | 1  |  1   |   1   | 0  |  0   |   0   | 0  | 0  | 1  | 1
 FF | 255  |  -1   | 0  |  0   |   0   | FF | 255  |  -1   | 0  | 1  | 0  | 0
 FF | 255  |  -1   | FF | 255  |  -1   | FE | 254  |  -2   | 0  | 1  | 0  | 1
 FF | 255  |  -1   | 80 | 128  | -128  | 7F | 127  |  127  | 1  | 0  | 0  | 1
 80 | 128  | -128  | 80 | 128  | -128  | 0  |  0   |   0   | 1  | 0  | 1  | 1
 7F | 127  |  127  | 7F | 127  |  127  | FE | 254  |  -2   | 1  | 1  | 0  | 0


 SUB
       A                   B                   A - B              Flags  
 ---------------     ----------------    ---------------      -----------------
 h  |  ud  |   d   | h  |  ud  |   d   | h  |  ud  |   d   || OF | SF | ZF | CF
----+------+-------+----+------+-------+----+------+-------++----+----+----+----
 FF | 255  |  -1   | FE | 254  |  -2   | 1  |  1   |   1   || 0  | 0  | 0  | 0
 7E | 126  |  126  | FF | 255  |  -1   | 7F | 127  |  127  || 0  | 0  | 0  | 1
 FF | 255  |  -1   | FF | 255  |  -1   | 0  |  0   |   0   || 0  | 0  | 1  | 0
 FF | 255  |  -1   | 7F | 127  |  127  | 80 | 128  | -128  || 0  | 1  | 0  | 0
 FE | 254  |  -2   | FF | 255  |  -1   | FF | 255  |  -1   || 0  | 1  | 0  | 1
 FE | 254  |  -2   | 7F | 127  |  127  | 7F | 127  |  127  || 1  | 0  | 0  | 0
 7F | 127  |  127  | FF | 255  |  -1   | 80 | 128  | -128  || 1  | 1  | 0  | 1

【讨论】:

  • 您的表格很有帮助,但 127 - -1 是 128 而不是 -128。
  • @James - 不,引用 x86 程序员的参考“Integer values range from –128 to +127 for a byte integer”
  • doc.ic.ac.uk/~eedwards/compsys/arithmetic 很好地解释了如何系统地确定进位和溢出。对于两者,加法和减法。
  • 8 位二进制补码 128 (0x80) = -128 (0x80) 如果显示为有符号数,则正确的形式为 -128,因为表格显示有符号数不是无符号数。它是一个溢出,如图所示:127 - - 1 = -128 如果它没有溢出,那么结果将是 +128。 (需要 9 位)
【解决方案2】:

在加法或减法时,进位和溢出值的所有 4 种组合都是可能的。您可以在this answer 中查看更多示例。

This answer 包含一个事实证明,即您从 A-B 获得的进位是您从 A+(-B) 获得的进位的倒数。第一个链接的代码利用此属性将ADC 转换为SBB

但是,A-BA+(-B) 的带符号溢出标志值必须相同,因为这取决于结果是否具有正确的符号位,并且在两种情况下符号位都将相同。

【讨论】:

  • 如果有人在 ADC 方面为 SBB 实现 x86 语义,一个有用的注释:SBB{inputs(a, b, cf), outputs(out, of, sf, zf, af, pf, cf)} = ADC{输入(a, NOT(b), NOT(cf)), 输出(out, of, sf, zf, NOT(af), pf, NOT(cf))}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多