Search code examples
assemblyx86digital-logic

How does comparing the Sign and Overflow Flag determine operand relationships?


Jump's based on comparing signed integers use the Zero, Sign, and Overflow flag to determine the relationship between operands. After CMP with two signed operands, there are three possible scenario's:

  1. ZF = 1 - Destination = Source
  2. SF = OF - Destination > Source
  3. SF != OF - Destination < Source

I'm having trouble understanding scenario 2 and 3. I've worked through the possible combinations and see that they do work - but I still can't figure out why they work.

Can anyone explain why a comparison of the Sign and Overflow flags reflects signed integer relationships?

Edit:

There seems to be some understanding regarding what I'm asking. Jumps based on signed comparisons utilize the Zero, Sign, and Carry flag - these include JG, JL, and so on.

For example:

mov   al, 1
cmp   al, -1    
jg    isGreater

isGreater: 

The jump is taken because Overflow flag = Sign Flag (both are 0), indicating in terms of signed comparison, the destination operand is larger than the source.

If the Overflow flag was set to 1 and the Sign flag set to 0, that would indicate the destination is smaller.

My questions is - I just can't seem to wrap my head around WHY this actually works.


Solution

  • Performing the signed subtraction R = Destination - Source yields a signed result.

    Suppose there is no overflow - the usual arithmetic laws holds: if R = Destination - Source > 0 then Destination > Source.
    Having no overflow means OF = 0 and R > 0 means SF = 0.

    Now suppose there is an overflow - let's call O the most significant, non-sign, bit and S the sign bit.
    An overflow condition means that either a) Computing the result's O needed a borrow and result's S didn't or b) result's O didn't need a borrow and S did.

    In case a) since result's S didn't need a borrow, the two S bits of the operands were either (1, 0) (1, 1) or (0, 0).
    Since result's O needed a borrow, and thus flipping the first source S bit, we must exclude the second and third option.
    So the operands sign bits were 1 and 0 (thus Destination < Source), the result's sign bit SF = 0 and OF = 1 by hypothesis.

    In case b) since result's S did need a borrow, the two S bits of the operands were (0, 1).
    Since O didn't need a borrow, the first operand S bit has been not changed and we don't need to consider any further case.
    So the operands sign bits were 0 and 1 (thus Destination > Source), the result's sign bit SF = 1 and OF = 1 by hypothesis.

    To recap:

    • If OF = 0 then Destination > Source => SF = 0.
    • If OF = 1 then Destination > Source => SF = 1.

    In short OF = SF.