Z80 Assembly 92: Block Compare with Difference (memcmp and Mismatch)

The Need for a Detailed Compare The standard `memcmp′ routine (Part 89) tells you only if two blocks are the same or different. For debugging purposes, you often need to know where the corruption or difference first occurred. Goal: Compare two memory blocks, and if they differ, return the address of the first byte that does not match. The Comparison Strategy We will modify the simple comparison loop to preserve the address and exit immediately upon the first failure. ...

September 28, 2025

Z80 Assembly 91: Fast 16-bit Block Clear (memset to Zero)

The Need for a Fast Block Clear Initializing memory to zero is one of the most common tasks in low-level programming (the equivalent of calling memset(ptr, 0, size) in C). Since the Z80 needs to clear large buffers, a highly optimized routine is essential. Goal: Fill a specified memory range (START_ADDR′ to END_ADDR′) with the byte value `00H′ as quickly as possible. The Optimized Strategy: Using LDIR The fastest method is a slight modification of the Block Fill routine (Part 85), exploiting the `LDIR′ (Load, Increment, Repeat) instruction. ...

September 28, 2025

Z80 Assembly 89: Block Search (memchr) and Compare (memcmp)

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. ...

September 28, 2025

Z80 Assembly 88: Block Move (memcpy) and Swap (memswap)

The Need for Block Operations In system programming and game development, you constantly need to move large chunks of data—transferring level data, shifting arrays, or buffering screen regions. Writing a loop for this is slow; the Z80 provides dedicated instructions for speed. Routine 1: Block Move (memcpy) `memcpy′ (Memory Copy) copies a block of bytes from a source address to a destination address. This is the fastest way to achieve the operation. ...

September 28, 2025

Z80 Assembly 85: Fast Block Fill (memset/bfill) with a Constant

The Need for a Fast Block Fill In game development and system programming, you frequently need to clear large areas of RAM—such as setting the entire screen buffer to a black background or zeroing out a data structure. Doing this one byte at a time with a simple loop is slow. Goal: Write a routine that fills a specified memory range (START_ADDR′ to END_ADDR′) with a single constant byte (`FILL_BYTE′) as quickly as possible. ...

September 28, 2025

Z80 Assembly 73: The Non-Linear Screen Memory Calculation

The Challenge of the Spectrum Screen The ZX Spectrum screen memory is not linear. To save on hardware costs, the memory map was designed to simplify the display hardware’s access but complicate the CPU’s access. The Layout: The screen is divided into three major vertical bands, and within each band, the lines are interleaved. This means to find the address of the pixel at (X, Y), you must perform a complex, multi-step calculation. ...

September 28, 2025

Z80 Assembly 55: Memory Mapping and Allocation (Keeping RAM Organized)

The Challenge of Fragmented Memory In a simple Z80 OS, as programs are loaded and unloaded, the $64$ KB of RAM becomes fragmented (broken into small pieces of free and used memory). The OS kernel must have a fast way to find a contiguous block of free memory when a new program needs to be loaded. The Free List (Simple Allocation) The most common technique is the Free List, a simple linked list (Part 33) that tracks all available blocks of memory. ...

September 27, 2025

Z80 Assembly 49: Memory Diagnostics (Testing RAM Reliability)

The Need for RAM Testing Before running any critical code, especially on vintage or newly built Z80 hardware, you must verify that the Random Access Memory (RAM) is working correctly. Faulty RAM chips can lead to unpredictable crashes and data corruption. Goal: To ensure every memory cell can reliably store both a logic ‘0’ and a logic ‘1’. The Simplest Test: The Fill Test The fastest, simplest test is to fill the entire memory block with a single value (e.g., 00H or FFH) and then read it back to verify. However, this test is weak because a faulty address line might cause two memory locations to point to the same physical chip, and this test wouldn’t catch it. ...

September 27, 2025

Z80 Assembly 43: Memory Banking (Switching ROM and RAM)

The Limitation: 64 KB Address Space The Z80 uses 16-bit address lines, meaning it can only directly address 64 kilobytes (65,536 bytes) of memory (from address 0000H to FFFFH). Since many systems (like the MSX or larger Spectrums) have $128$ KB or more of RAM/ROM, they must use Memory Banking to access it all. How Memory Banking Works Memory Banking is the technique of using an I/O port to physically switch which $16$ KB or $8$ KB block of memory is visible to the CPU at a specific address range. ...

September 27, 2025

Z80 Assembly 07: Block Transfers and String Operations

High-Speed Block Transfer Instructions The Z80 includes a powerful set of instructions designed to handle large blocks of memory quickly. These commands primarily rely on three 16-bit register pairs: Register Pair Purpose in Block Commands HL Source Address (Where to read data from) DE Destination Address (Where to write data to) BC Counter (How many bytes to move/compare) Transferring Data (Move) The LDI (Load, Increment) and LDIR (Load, Increment, Repeat) commands are used to copy blocks of memory. ...

September 27, 2025