The Need for Block Search and Compare
In system programming, you need routines to:
- Search (
memchr
): Find the first occurrence of a specific character (e.g., a null terminator, space, or command byte) within a buffer. - 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.