carry/overflow & subtraction in x86

10,130

Solution 1

Here's a reference table that might help. This shows an example of every possible combination of the 4 arithmetic flags that can result from the ADD and SUB instructions on x86. 'h' 'ud' and 'd' stand for hex, unsigned decimal and signed decimal representations of each value. For example, the first row for SUB says 0xFF - 0xFE = 0x1 with no flags set.

But, I think the short story is that Alex's answer is correct.

 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

Solution 2

All 4 combinations of the carry and overflow values are possible when adding or subtracting. You can see more examples in this answer.

This answer contains a proof of the fact that the carry that you get from A-B is the inverse of the carry you get from A+(-B). The code by the first link exploits this property to turn ADC into SBB.

The signed overflow flag value, however, must be the same for both A-B and A+(-B) because it depends on whether or not the result has the correct sign bit and in both cases the sign bit will be the same.

Share:
10,130

Related videos on Youtube

Robz
Author by

Robz

If I had money to waste, I'd waste it on art.

Updated on June 04, 2022

Comments

  • Robz
    Robz about 2 years

    I'm trying to wrap my head around overflow & carry flags in x86.

    As I understand it, for addition of signed 2's complement numbers, the flags can only be generated in one of four ways (my examples are 4-bit numbers):

    1. pos+pos = neg (overflow)
      • 0111 + 0001 = 1000 (7 + 1 = -8)
    2. pos+neg = pos (carry)
      • 0011 + 1110 = 0001 (3 + -2 = 1)
    3. neg+neg = neg (carry)
      • 1111 + 1111 = 1110 (-1 + -1 = -2)
    4. neg+neg = pos (overflow & carry)
      • 1000 + 1001 = 0001 (-8 + -7 = 1)

    So, in x86 assembly, does subracting B from A generate the same flags as adding A and -B?

  • James Black
    James Black over 11 years
    Your table is helpful, but 127 - -1 is 128 not -128.
  • srking
    srking over 11 years
    @James - No, quoting the x86 programmer's reference "Integer values range from –128 to +127 for a byte integer"
  • Cubi73
    Cubi73 about 9 years
    doc.ic.ac.uk/~eedwards/compsys/arithmetic Nice explaination on how to determine carry and overflow systematically. For both, addition and subtraction.
  • mrexodia
    mrexodia about 6 years
    A useful note in case someone is implementing x86 semantics for SBB in terms of ADC: SBB{inputs(a, b, cf), outputs(out, of, sf, zf, af, pf, cf)} = ADC{inputs(a, NOT(b), NOT(cf)), outputs(out, of, sf, zf, NOT(af), pf, NOT(cf))}
  • old_timer
    old_timer over 4 years
    8 bit twos complement 128 (0x80) = -128 (0x80) the proper form would be -128 if shown as a signed number as the table shows signed numbers not unsigned. Its an overflow as demonstrated: 127 - - 1 = -128 if it had not overflowed then the result would be +128. (need 9 bits for that)