2

I know the Carry flag during SUB is set whenever the minuend is smaller than the subtrahend and a borrow is required, but haven't been able to find anything explaining this in more detail.

Since subtraction is actually just adding with two's complement, how does the CPU know that the subtrahend is larger and a borrow has occurred?

The only thing I can think of is that maybe the Carry flag is set automatically during SUB, whenever converting the subtrahend to its 2's complement. Then unless another Carry occurs (as it should during the addition whenever the minuend is larger than the subtrahend) to switch it back off, it stays on.

Or am I way off?

cafekaze
  • 377
  • 2
  • 6
  • 18
  • 3
    You are over-complicating it. The processor does not know about 2's complement. The ALU subtracts the operands and the resulting carry goes into that `C` flag. It will also set the `O` flag from a carry-out to the m.s. bit. And the `S` flag to mirror the m.s. bit. And the `Z` flag if the result was `0`. Other flags too, dependant on processor. *How* is it done? That is not a "language" question. – Weather Vane Jan 25 '17 at 01:31
  • 1
    The carry from the conversion is discarded, the output carry is the negated carry from the addition. Some architectures in fact don't negate it, so you actually get CF=1 when no borrow occurs. – Jester Jan 25 '17 at 01:33
  • subtraction is done in unsigned so no need to know about the type. The carry flag is checked by the output bits – phuclv Jan 25 '17 at 01:51
  • 1
    See **[Understanding Carry vs. Overflow conditions/flags for signed vs. unsigned](http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt)**. Also see other links in the [x86 tag wiki](http://stackoverflow.com/tags/x86/info). – Peter Cordes Jan 25 '17 at 05:07
  • It's possible to implement true subtraction logic that doesn't involve negating a number and adding, but I don't know if there are any processors that use [subtractor logic](http://en.wikipedia.org/wiki/Subtractor#Full_subtractor) . – rcgldr Jan 25 '17 at 05:23
  • @Jester That makes perfect sense - so conversion to 2's complement carry is inverted, then in x86 the carry from addition is inverted again. Thanks - don't know why I couldn't find any info on this. – cafekaze Feb 02 '17 at 04:04

1 Answers1

2

You seem to confuse the carry and overflow flags.
The carry flag checks unsigned overflow and the overflow flag checks signed overflow.
The way this works is that prior to subtraction the (unsigned) numbers are compared and if b > a then CF is set.
If the sign of the first operand changes overflow is set.

During the subtraction the CPU does not care whether the operands are negative.
If the unsigned base is smaller than the unsigned number being subtracted then a carry occurs.

E.g. (just tested in the CPU view of my debugger)

 0 - -1 = 1  ->> CF = 1, because 0xFFFFFFFF > 0  
10 - -1 = 11 ->> CF = 1, same reason
-2 -  4 = -6 ->> CF = 0, because 0x4 < 0xFFFFFFFE  

Remember in signed arithmetic these results are correct, but in unsigned arithmetic they are *way* off, hence CF=1.

The carry flag does not know or care about sign, it is (only) meant for unsigned overflow. Remember the CPU has no way of knowing whether you want to perform signed or unsigned operations. It is up to the application to test the relevant flags to interpret the results, this is why the CPU provides two sets of overflow flags.

Here's a list of the most common flags and their function:

code | descripton     |name     | When set
---+++----------------+---------+-------------------
CF  unsigned overflow  Carry      If unsigned over-/underflow occurs
OF  signed overflow    Overflow   If sign bit (MSB) flips
SF  Sign flag          Sign       If MSB is set, i.e. is result is negative
ZF  Zero flag          Zero       If Result is zero

Neither of these flags have much in the way of 'intelligence'.
You need to remember that these flags were designed when transistors where in short supply.

About 2's complement
2's complement is designed so that addition and subtraction don't need to know about the conversion from positive to negative.
You can just add and subtract without care if the operand or the result will be positive or negative.
The only caveats occur on overflow, which is exactly what the carry flag tests.

If you where to use plain inversion (i.e. 1's complement) as negative numbers then you'd need all sorts of safeguards around addition and subtraction; this is why 2's complement is universally used.

Further reading
http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt
Thanks Peter

Johan
  • 74,508
  • 24
  • 191
  • 319
  • For one's complement, the number to be subtracted is just complemented (one's complement). During addition, if there is a carry, the result is incremented. Some older computers (like CDC 3000 series) used one's complement. – rcgldr Jan 25 '17 at 08:18