setbe
sets the result to 1 if (ZF=1) or (CF=1)
. If the documentation you're reading says that it sets it on (ZF=0) and (CF=1)
, it's wrong. See the 80386 Programmer's Reference Manual. Below is a detailed analysis:
setbe
sets the result to 1 if the result of the preceding comparison was below-or-equal, when compared as unsigned integers (the equivalent for signed integers would be setle
, for less-or-equal).
When cmp
instruction is performed, the destination operand is subtracted from the source operand, and the result is discarded. The only output is the setting of the condition flags. Remember that when we subtract two numbers A-B
, we're really adding A+(~B)+1
in two's complement, where ~B
is the one's complement of B
(i.e. all the bits are flipped).
Let's look at 6 cases:
Case 0: Compare 1 to 0
0 - 1
= 0 + ~1 + 1
= 0x00000000 + 0xfffffffe + 1
= 0xffffffff ≠ 0, no carry
==> ZF = 0, CF = 0
Case 1: Compare 0 to 0
0 - 0
= 0 + ~0 + 1
= 0x00000000 + 0xffffffff + 1
= 0x00000000 = 0, with carry
==> ZF = 1, CF = 0
Case 2: Compare 0 to 1
1 - 0
= 1 + ~0 + 1
= 0x00000001 + 0xffffffff + 1
= 0x00000001 ≠ 0, with carry
==> ZF = 0, CF = 1
Case 3: Compare UINT_MAX to 0
0 - 4294967295
= 0 + ~4294967295 + 1
= 0x00000000 + 0x00000000 + 1
= 0x00000001 ≠ 0, no carry
==> ZF = 0, CF = 0
Case 4: Compare 0 to UINT_MAX
4294967295 - 0
= 4294967295 + ~0 + 1
= 0xffffffff + 0xffffffff + 1
= 0xffffffff ≠ 0, with carry
==> ZF = 0, CF = 1
Case 5: Compare UINT_MAX to UINT_MAX
4294967295 - 4294967295
= 4294967295 + ~4294967295 + 1
= 0xffffffff + 0x00000000 + 1
= 0x00000000 = 0, with carry
==> ZF = 1, CF = 1
The cases in which the first argument is below-or-equal to the second are cases 1, 2, 4, and 5. All of these satisfy (ZF=1) or (CF=1)
, and the remaining cases in which the comparison is false satisfy the opposite condition, (ZF=0) and (CF=0)
. Note that we've also enumerated all possible combinations of CF and ZF. Hence, we conclude that the correct behavior for setbe
is to set on (ZF=1) or (CF=1)
.