How is subtraction performed on unsigned numbers within the CPU?

I am learning about various flag states for the cmp instruction. From reading, the cmp instruction is really just a sub instruction that sets the various flags (OF, CF, ZF) accordingly depending on the result of the sub.

As I understand it, there is no pure "subtraction (sub)" instruction implementation in x86, rather, the second operand is negated, and then the two numbers are added; i.e. 8-4 becomes 8+(-4).

If this is true, then how is subtraction implemented for unsigned numbers? For example, if we are limited to 8 bits and want to subtract 255-254, the 2's compliment representation of 254 is well outside of the range of 8 bits.

Signed and unsigned numbers are added / subtracted in exactly the same way (add / sub will set both OF and CF flag). The only difference is how you interpret the result. See link and link.

When you subtract two 8 bit numbers, say a - b, it's like you were adding 256 - b = 0b11111111 - b + 1 = NOT(b) + 1 to a. In case of a = 255, b = 254, a - b = 255 + NOT(0b11111110) + 1.

For any 8 bit number n: n + NOT(n) + 1 = 0, so NOT(n) + 1 is the inverse of n (in additive group) modulo 256 no matter if you interpret it as signed or unsigned.

• Ok. So I guess you negate the number by simply taking the 2's compliment of it, minus the MSB sign bit (which isn't relevant for addition anyway) and then add as normal Sep 18 '19 at 4:06
• Yes. First, you negate the number you want to subtract by changing all 1s to 0s and vice versa and then add 1 to it. Then the addition is performed. Sep 18 '19 at 9:09
a = 255
b = 254
c = int(bin(~b),2)
print ("subtracting is equal to not (input) + 1")
print ("254 = 0b11111110  flipped 254= 0b00000001 adding one makes it 0n00000010")
print ("adding 0b11111111 to 0b00000010 will leave 0b00000001 ")
print ("a =", a , "b =" , b , "not b =", c , "a+b =", a+c , "final result =" , a+c+1 )

result

:\>python sub.py
subtracting is equal to not (input) + 1
254 = 0b11111110  flipped 254= 0b00000001 adding one makes it 0n00000010
adding 0b11111111 to 0b00000010 will leave 0b00000001
a = 255 b = 254 not b = -255 a+b = 0 final result = 1