Search code examples
assemblyx86binaryeflagssigned-overflow

what conditions set the overflow and carry flags?


I've been reading and watching tutorials but I only get more confused since my instructor did not go into much details with this, or her explanations are quite vague.

(The values in the flags were only dictated to us.)

Example 1:


  1010 1010 0100 0101
- 0100 0110 0111 1000
  ___________________
  0110 0011 1100 1101

SF = 0
ZF = 0
PF = 0
CF = 1
OF = 1
AF = 1

Why were CF and OF set to 1? And as I understand it, AF is set when there is a carry out of the b3 or a borrow into it, meaning it's the one who needs to borrow. Am I right?

Example 2:

  0110 0111 1011 0100
+ 1111 1010 1100 1110
_____________________
1 0110 0010 1000 0010

SF = 0
ZF = 0
PF = 0 
CF = 1 
OF = 1 
AF = 1

Here, AF was set because....? I thought AF is only set when there is a carry out of it (or when it needs to borrow)? Also, with CF, as I understand it, it cannot be set if there was a carry out of the MSB, and also a carry into it. It works like XOR, only one condition can be true.

This has been confusing me for days now. And yes, I'm still confused with the differences in how these flags work depending if the numbers are signed or unsigned, because my instructor never mentioned that to us.


Solution

  • example 1:

    mov     ax, 1010101001000101b
    mov     bx, 0100011001111000b
    sub     ax, bx
    
    • CF = 0: CF is not set because there is no borrow from the most significant bit (bit 15) into the next higher bit (bit 16).
    • OF = 1: OF is used for 2k-numbers. When you interpret the 2 numbers in example 1 as 2k numbers, then the 1st number is negative, the 2nd is positive. Substracting a positive from a negative number is like adding 2 negative numbers. The result should be negative, but it is not => OF is set.
    • AF = 1: You have a borrow from the lowest nibble (lowest 4 bits) to the next nibble (from the 3rd bit to the 4th bit, when you call your least significant bit the 0th bit)

         0101
       - 1000 
       ______
        11101
      

    example 2:

    mov     ax, 0110011110110100b   
    mov     bx, 1111101011001110b   
    add     ax, bx
    
    • CF = 1 CF is set, because you add two 16 bit numbers and the result is too big for 16 bit. It is 17 bit long (registers have a size of 8, 16, 32, 64 bit).
    • OF = 0 OF is not set, because you add a positive and a negative 2k number. Because of that your result is automatically inbetween those 2 numbers and this way it can not be a too big or too negative 2k number -> no overflow possible.
    • PF = 1 There is a even number of 1s in the least significant byte (there are two 1s).
    • AF = 1 You have a carry from the 3rd bit to the 4th bit:

        0100
      + 1110
      ______
       10010
      

    Here is the explanation from the intel manual:

    The status flags (bits 0, 2, 4, 6, 7, and 11) of the EFLAGS register indicate the results of arithmetic instructions, such as the ADD, SUB, MUL, and DIV instructions. The status flag functions are:
    CF (bit 0) Carry flag — Set if an arithmetic operation generates a carry or a borrow out of the mostsignificant bit of the result; cleared otherwise. This flag indicates an overflow condition for unsigned-integer arithmetic. It is also used in multiple-precision arithmetic.
    PF (bit 2) Parity flag — Set if the least-significant byte of the result contains an even number of 1 bits; cleared otherwise.
    AF (bit 4) Adjust flag — Set if an arithmetic operation generates a carry or a borrow out of bit 3 of the result; cleared otherwise. This flag is used in binary-coded decimal (BCD) arithmetic.
    ZF (bit 6) Zero flag — Set if the result is zero; cleared otherwise.
    SF (bit 7) Sign flag — Set equal to the most-significant bit of the result, which is the sign bit of a signed integer. (0 indicates a positive value and 1 indicates a negative value.)
    OF (bit 11) Overflow flag — Set if the integer result is too large a positive number or too small a negative number (excluding the sign-bit) to fit in the destination operand; cleared otherwise. This flag indicates an overflow condition for signed-integer (two’s complement) arithmetic.