DEV Community

UPinar
UPinar

Posted on

Daily Dose of x86-64 - II

Overflow and Carry Flags

Before we start learning flags, we need to know, how negative numbers stored in memory. The type that it stores negative numbers are signed integers. So lets start...


Think about an 8 bit memory. Normally 256 positive number can be stored inside of that memory, from 0 to 255. That type is unsigned byte(uint8_t).

0   -> 0000 0000
255 -> 1111 1111
Enter fullscreen mode Exit fullscreen mode

When we want to store negative values in 8 bit memory, Most Significant Bit(MSB) assigned as a Sign bit (leftmost bit), where the value 1 represents negative (sign bit = 1, integer is negative) and value 0 represents positive. This type is signed byte(int8_t).

1111 1111 -> MSB

0    -> 0000 0000
127  -> 0111 1111
-1   -> 1111 1111        
-128 -> 1000 0000       
Enter fullscreen mode Exit fullscreen mode

 
In unsigned type MSB's value equals to (+2^7) = 128 
1001 0000 = (2^7 * 1) + (2^5 * 1) = 128 + 32 = 160
8 bit unsigned integer(uint8_t) stores from 0 to 255.

 
In signed type MSB's value equals to (-2^7) = -128 and other bits still have positive values. 
1001 0000 = (2^7 * -1) + (2^5 * 1) = -128 + 32 = -96 
8 bit signed integer(int8_t) stores from -128 to 127.


In x86-64 assembly language, there is a instruction called neg, if the value is positive neg instruction makes it negative and if it is negative neg makes it positive, basically multiplying the value by -1. What actually it does is, taking two’s complement of that value. How we take two’s complement?

It is easy, we will flip all bits in integer (one’s complement) and add 1 (two’s complement).

neg instruction

0011 0000 = +48
1100 1111 = -49 (one’s complement)
1101 0000 = -48 (two’s complement)
Enter fullscreen mode Exit fullscreen mode
1111 1111 = -1
0000 0000 =  0 (one’s complement)
0000 0001 = +1 (two’s complement)
Enter fullscreen mode Exit fullscreen mode

Now that we have a better understanding of how the negative values stored in memory, we can go on with flags. It is better to continue with examples..

Overflow Flag - 1

In general explanation, Overflow Flag (OF) set (we call the verb set when a flags value returns 1 and clear when the value is 0) in signed integers when its value exceeds limits of signed integer. For example AL register's (8 bit) limits are -128 and 127 when we store signed values inside of it.
We create a variable called var1 in data section and gave it a value 1000 0001b = -127d. We assign that value to AL register and subtract 3. Result is needs to be -130 but -130 exceeds the limits so Overflow Flag will set. But how it actually happens? 


Forget about exceeding limits for now. We will explain setting Overflow Flag with a different way.

1000 0001(-127) - 0000 0011(3) = 0111 1110(126)
Enter fullscreen mode Exit fullscreen mode

0111 1110 = result is 126 and because of 126 is a positive value,
MSB = 0.

But the real result needs to be -130 which is a negative value,
MSB = 1.

Because of MSBs are NOT SAME and the type is a signed integer, Overflow Flag will set.


Overflow Flag - 2

Exceeding 8 bit integers positive limit (127), results sign bit changes from positive to negative.

0111 1101 (125) + 0000 0101(5) = 1000 0010 (-126)
Enter fullscreen mode Exit fullscreen mode

Results MSB = 1 (negative), but normally it has to be positive, 125 + 5 = 130 MSB = 0 (positive). Because of MSBs are NOT SAME and the type is signed integer, Overflow Flag will set.


Lets check Carry Flag.. 

Carry Flag - 1

Carry flag used for unsigned integers. We will use 8 bit unsigned integers (uint8_t) as variables. 8 bit unsigned integer can store values from 0 to 255.

To understand Carry Flag, we need to ask ourselves about if there was one more bit(9th bit) in our 8 bit memory, could we carry 1(binary) to that bit or could we barrow 1(binary) from that, while we are doing addition and subtraction.

In examples inside the image above,

1111 1110(254) + 0000 0111(7) = 0000 0101 (5), normally the result should be 261 but because of there was not 9th bit, that 1(binary), we need to carry will go to Carry Bit and it will set Carry Flag.

0000 0101 (5) - 0000 1000(8) = 1111 1101 (253), normally we need to barrow 1(binary) from the 9th bit but there is no 9th bit so it will go to Barrow Bit and will set Carry Flag.


Useful Links

One's Complement, Two's Complement, and Signed Magnitude

Two's Complement Representation of Negative Numbers

Overflow and Carry Flags

The CARRY flag and OVERFLOW flag in binary arithmetic

Top comments (0)