Intel x86 Assembly Language & Microarchitecture Testing conditions


Example

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.


Flags

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:

FlagWhen setWhen clear
ZFWhen result is zero.
EAX - EBX = 0 ⇒ EAX = EBX
When result is not zero.
EAX - EBX ≠ 0 ⇒ EAX ≠ EBX
CFWhen 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
SFWhen result MSb is set.When result MSb is not set.
OFWhen a signed overflow occurred.When a signed overflow did not occur.
PFWhen 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.
AFWhen 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.

Non-destructive tests

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.

DestructiveNon destructive
subcmp
andtest

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

Signed and unsigned tests

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.