The Need for 16-bit Comparison

The Z80 has a dedicated CP R′ (Compare) instruction, but it only works on 8-bit values. When dealing with addresses, large scores, or multi-byte numbers, you need a robust routine to compare two 16-bit pairs, such as HL′ against `DE′.

Goal: Compare HL with DE and set the flags (Zero, Carry) to indicate if HL &equals; DE&prime;, HL < DE′, or `HL > DE′.

The Comparison Strategy: Subtraction

The fastest way to compare two numbers is to subtract one from the other.

The Principle:

  • If $A - B = 0$, then $A$ equals $B$ (`Z′ flag is set).
  • If $A - B$ results in a borrow (`Carry′ flag is set), then $A$ is less than $B$ ($A < B$).
  • If $A - B$ does not result in a borrow, then $A$ is greater than or equal to $B$ ($A \ge B$).

The 16-bit Comparison Routine

We must perform the subtraction in two parts, starting with the low byte and then subtracting the high byte with the borrow (Carry flag) generated from the first operation.

Key Instructions:

  1. `CP L, E′ (Compare Low Bytes)
  2. `SBC H, D′ (Subtract High Bytes with Carry/Borrow)
CMP_HL_DE:
    ; 1. Compare the Low Bytes (Sets Carry if L < E)
    LD   A, L               ; Load L into A
    CP   E                  ; Compare A with E (&quot;A - E&quot; &minus; sets Z and C flags)
    
    ; 2. Subtract the High Bytes with Borrow
    ;    This operation finalizes the comparison using the Carry flag (borrow)
    LD   A, H               ; Load H into A
    SBC  A, D               ; Subtract D from A MINUS the Carry flag
    
    RET

Interpreting the Flags

After the routine returns, the combined flags from the final SBC A, D&prime; instruction tell you the exact relationship between HL′ and `DE′:

Condition Carry Flag (C) Zero Flag (Z) The Result
HL = DE 0 1 The numbers are equal.
HL < DE 1 0 HL is less than DE.
HL > DE 0 0 HL is greater than DE.

Usage Example: Checking if a sprite’s address (HL&prime;) has exceeded the screen boundary (DE′):

    CALL CMP_HL_DE
    JP   C, OUTSIDE_BOUNDARY ; Jump if Carry=1 (HL < DE, or HL > DE with overflow, handled by SBC)
    JP   Z, AT_BOUNDARY