assemblyx86integer-arithmeticcarryflageflags

What is wrong with my derivation of this carry flag result for SUB?


To be clear, I am certain that the derivation below is incorrect, but I am hoping someone can point out where in my "proof" I am wrong.

I am trying to prove that the x86 instruction setb indeed implements x<y as an unsigned comparison when used after a cmp instruction. Specifically, let us consider (ATT syntax, and I will neglect suffixes indicting the number of bits)

# Compare two registers, e.g., %eax and %ebx with values y and x, respectively, when unsigned
cmp %ebx, %eax

# Set %al to 1 if %eax is below %ebx (unsigned comparison)
setb %al

The claim is that %al gets value 1 at the end of this if and only if the values of x,y obey x<y when considered as unsigned. We note that in the ATT syntax, the cmp instruction is subtracting the contents of %ebx from the contents of %eax and that this operation sets the relevant condition flags appropriately--including the carry out flag, which is of interest here. That is, it is putting the bit pattern into a subtractor unit to calculate x(-^u)y, where I use that notation to describe unsigned subtraction and I'll use - to describe subtraction of the corresponding integers.

Now here is my problem. Let's suppose x<y. We want to show that a carry out results from the subtraction. Suppose each number is w bits. I know (from my text, Bryant and O'Hallaron's CS:APP3e) that

x(-^u)y := x(+^u)((-^u) y) = x(+^u)(2^w - y) = 2^w + x - y < 2^w,

so ostensibly no carry out was obtained since the result fits into our w bits. That is, no carry out. This is just one direction of the "proof", but already I can clearly see I am wrong. Where am I going wrong though?


Solution

  • x86's sub and cmp set CF if there's a borrow from the subtraction. This is the case if there's no carry-out from adding the bitwise-inverse with a carry-in of 1, like the binary adder-subtractor in the ALU does.

    Some ISAs (like ARM) are opposite of x86 for sub, set their carry flag directly from the carry-out of the adder-subtractor. x86 (and some other ISAs) invert it.

    Related: Arithmetic identities and EFLAGS - note that a correct asm equivalent to sub is a single add with carry-in of 1 and a cmc, not a separate neg and add, if you care about the EFLAGS result.