Assembler Directives: Structuring Your Code
Assembler directives are commands that are read and acted upon by the assembler program, not the Z80 CPU. They organize code, reserve memory, and define data.
Directive | Action | Purpose |
---|---|---|
ORG NNNNH |
Sets the origin (starting address) where the following code should be placed in memory. | Essential for defining where your program loads. |
EQU symbol, value |
Equates a symbolic name to a numerical value. | Defines constants like port addresses or screen dimensions (SCREEN_WIDTH EQU 32 ). |
DB val1, val2, ... |
Define Byte: Reserves memory and places 8-bit data bytes (numbers or ASCII characters). | Used to define text strings or data tables. |
DW val1, val2, ... |
Define Word: Reserves memory and places 16-bit words (often addresses). | Used for jump tables or storing address pointers. |
DEFS N |
Define Space: Reserves N bytes of uninitialized memory. | Used for buffers, variables, or the stack area. |
Example: Data Definition
ORG 8000H ; Program starts at address 8000H
TEXT_START:
DB 'Z80 ROCKS!', 0
BUFFER:
DEFS 256 ; Reserve 256 bytes for a temporary buffer
Debugging and Testing Techniques
Since you are writing low-level code, effective debugging is critical.
1. The NOP Slide:
The NOP
(No Operation) instruction does nothing but take up one byte and one clock cycle. If your program is crashing or skipping a specific instruction, you can temporarily replace the suspect instruction with a sequence of NOP
s to bypass it and test the program flow.
2. Breakpoints and Watchpoints: In an emulator or debugger, a breakpoint stops the CPU when execution reaches a specific address. A watchpoint stops the CPU when a specific memory address or register value changes.
3. Using the Beeper (Hardware Trace): In retro systems like the ZX Spectrum, a common debugging trick is to strategically place code to turn the machine’s internal beeper on and off. If you hear the tone during a crash, you know the code reached