In order to use a conditional jump a condition must be tested. Testing a condition here refers only to the act of checking the flags, the actual jumping is described under Conditional jumps.
x86 tests conditions by relying on the EFLAGS register, which holds a set of flags that each instruction can potentially set.
Arithmetic instructions, like sub
or add
, and logical instructions, like xor
or and
, obviously "set the flags". This means that the flags CF, OF, SF, ZF, AF, PF are modified by those instructions. Any instruction is allowed to modify the flags though, for example cmpxchg
modifies the ZF.
Always check the instruction reference to know which flags are modified by a specific instruction.
x86 has a set of conditional jumps, referred to earlier, that jump if and only if some flags are set or some are clear or both.
Arithmetic and logical operations are very useful in setting the flags. For example after a sub eax, ebx
, for now holding unsigned values, we have:
Flag | When set | When clear |
---|---|---|
ZF | When result is zero. EAX - EBX = 0 ⇒ EAX = EBX | When result is not zero. EAX - EBX ≠ 0 ⇒ EAX ≠ EBX |
CF | When result did need carry for the MSb. EAX - EBX < 0 ⇒ EAX < EBX | When result did not need carry for the MSb. EAX - EBX ≮ 0 ⇒ EAX ≮ EBX |
SF | When result MSb is set. | When result MSb is not set. |
OF | When a signed overflow occurred. | When a signed overflow did not occur. |
PF | When the number of bits set in least significant byte of result is even. | When the number of bits set in least significant byte of result is odd. |
AF | When the lower BCD digit generated a carry. It is bit 4 carry. | When the lower BCD digit did not generate a carry. It is bit 4 carry. |
The sub
and and
instructions modify their destination operand and would require two extra copies (save and restore) to keep the destination unmodified.
To perform a non-destructive test there are the instructions cmp
and test
.
They are identical to their destructive counterpart except the result of the operation is discarded, and only the flags are saved.
Destructive | Non destructive |
---|---|
sub | cmp |
and | test |
test eax, eax ;and eax, eax
;ZF = 1 iff EAX is zero
test eax, 03h ;and eax, 03h
;ZF = 1 if both bit[1:0] are clear
;ZF = 0 if at least one of bit[1:0] is set
cmp eax, 241d ;sub eax, 241d
;ZF = 1 iff EAX is 241
;CF = 1 iff EAX < 241
The CPU gives no special meaning to register values1, sign is a programmer construct. There is no difference when testing signed and unsigned values. The processor computes enough flags to test the usual arithmetic relationships (equal, less than, greater than, etc.) both if the operands were to be considered signed and unsigned.
1 Though it has some instructions that make sense only with specific formats, like two's complement. This is to make the code more efficient as implementing the algorithm in software would require a lot of code.