How the CMP Instruction Updates CPU Flags

The CMP (Compare) instruction evaluates the relationship between two operands by performing an internal, implicit subtraction without saving the mathematical result to any destination register. Instead of overwriting register contents, the processor routes the output of the Arithmetic Logic Unit (ALU) directly to the status register (such as the FLAGS or EFLAGS register in x86 architecture). By observing the resulting status flags—primarily the Zero Flag (ZF), Sign Flag (SF), Carry Flag (CF), and Overflow Flag (OF)—subsequent conditional jump instructions can determine whether the first operand was equal to, greater than, or less than the second operand while keeping the original binary data intact.

The Binary Subtraction Mechanism

At the hardware level, the ALU performs subtraction using two’s complement arithmetic. When a program executes CMP A, B, the processor calculates \(A - B\) by converting \(B\) into its two’s complement form (inverting all bits of \(B\) and adding \(1\)) and then adding that value to \(A\):

\[\text{Result} = A + (\sim B + 1)\]

During a standard SUB A, B instruction, the ALU completes this operation and writes the resulting binary value back into the register holding operand \(A\). The CMP instruction uses the identical ALU circuitry to perform this exact binary addition, but it disables the write-back stage of the CPU pipeline. The output data bus simply discards the arithmetic result, leaving operand \(A\) and operand \(B\) completely unmodified.

Evaluating and Updating Status Flags

Even though the numerical difference is discarded, the characteristics of the calculation are captured and latched into the processor’s flag register. The primary flags updated by the implicit subtraction include:

Execution Flow and Conditional Branching

By altering only the status flags, CMP acts as a non-destructive probe into the system’s state. Conditional jump instructions (such as JE for Jump if Equal, JL for Jump if Less, or JA for Jump if Above) immediately evaluate these flag combinations to alter execution flow. For example, JE branches if ZF = 1, while JL branches if the Sign Flag does not equal the Overflow Flag (\(SF \neq OF\)). This separation of arithmetic evaluation from data modification allows programs to make control-flow decisions efficiently without requiring temporary registers to store calculation results.