The Need for Block Search and Compare

In system programming, you need routines to:

  1. Search (memchr): Find the first occurrence of a specific character (e.g., a null terminator, space, or command byte) within a buffer.
  2. Compare (memcmp): Verify that two large blocks of memory (e.g., two versions of a game level, or a password against a stored hash) are identical.

Routine 1: Block Search (memchr)

Block Search scans a memory area for the first occurrence of a specific 8-bit value.

Key Instruction: The Z80’s `CPIR′ (Compare, Increment, Repeat) instruction (Part 7) is perfectly suited for this, as it stops the moment a match is found.

Setup and Execution:

Register Purpose
A Value to Search For (The target byte).
HL Source Address (Start of the block).
BC Counter (The total number of bytes to check).
MEMCHR_ROUTINE:
    ; Assume A = target byte, HL = start address, BC = length
    
    CPIR                    ; Compares A with (HL), increments HL, decrements BC, repeats until A = (HL) or BC = 0.

    ; --- Result Check ---
    ; If the block was searched and the value was NOT found, BC will be 0.
    ; If the value was found, the Zero flag (Z) will be set, and BC ≠ 0.

    JP   Z, VALUE_FOUND     ; Jump if Z=1 (match found)
    
    ; If Z=0, value not found (reached end of block)
    RET

VALUE_FOUND:
    DEC  HL                 ; Decrement HL to point back to the matching byte (CPIR leaves HL pointing one byte *past* the match)
    RET

Routine 2: Block Compare (memcmp)

Block Compare checks if two blocks of memory of the same length are identical. This must be done byte-by-byte.

The Strategy: Use the `LDIR′ setup but use a custom loop to compare bytes and exit immediately upon the first mismatch.

Execution Logic:

MEMCMP_ROUTINE:
    ; Assume HL = Block 1 address, DE = Block 2 address, BC = length
    
CMP_LOOP:
    LD   A, (HL)            ; A ← Byte from Block 1
    CP   (DE)               ; Compare A with byte from Block 2
    JP   NZ, BLOCKS_DIFFER  ; If Not Zero, blocks are different → exit
    
    INC  HL                 ; Advance Block 1 pointer
    INC  DE                 ; Advance Block 2 pointer
    
    DEC  BC                 ; Decrement counter (16-bit check)
    LD   A, B
    OR   C
    JP   NZ, CMP_LOOP       ; Loop if BC is Not Zero

    ; Blocks are identical (return Z=1)
    OR   A                  ; Set Z flag (A=0)
    RET

BLOCKS_DIFFER:
    RET                     ; Return with Z flag NOT set (A ≠ 0)

Final Status: The function returns with the Zero flag (Z) set if the blocks are identical, or cleared if they differ.