Z80 Programming
This article describes how to write machine code programs for the Z80.
Requirements
For writing Z80 machine code programs you will typically need an assembler (to convert Z80 assembly listings into binaries) and probably also an emulator for testing and single-stepping your code. Some emulators include assemblers although the level of usability is somewhat variable. Some popular Z80 assemblers are:
- z80asm (part of z88dk)
- binutils-z80 (GNU binary utilities, for the z80-unknown-coff target)
Z80 Machine Code Reference
Registers
The Z80 has a collection of 16-bit registers, some of which can also be accessed as pairs of 8-bit registers. (Or is it the other way round?)
The following table gives details; one-character names imply 8 bits, while two-character names imply 16 bits. (I've done this from memory, so someone should check it, particularly the Access column. Also a proper chart of all this would be good, with things like "load from [nn]" and "16-bit add to"; the current table is incomplete and changing that would clutter it enormously)
name | Description | Access |
PC | Program Counter | Write with JP/JR/CALL/RET |
A | Accumulator | All LD, 8-bit arithmetic & logic ops, IN, OUT, CPI[R]/CPD[R], DAA. As AF with PUSH/POP and EX AF,AF' |
F | Flags register | Written indirectly by most ops, directly by CCF/SCF; read with conditional ops (JP/JR/CALL/RET cc). As AF with PUSH/POP/EX |
BC | User register | Most LD, PUSH/POP, 16-bit arithmetic, block instructions, IN, OUT, EXX. As B,C with LD, 8-bit arithmetic & logic, DJNZ. |
DE | User register | Most LD, PUSH/POP, 16-bit arithmetic, block instructions, EXX, EX DE,HL. As D,E with LD, 8-bit arithmetic & logic. |
HL | User register | All LD, PUSH/POP, 16-bit arithmetic, block instructions, EXX, EX DE/SP,HL. As H,L with LD, 8-bit arithmetic & logic. |
SP | Stack pointer | Some LD, 16-bit arithmetic, EX SP,HL, write indirectly with CALL/RET/PUSH/POP. |
I | Interrupt vector | LD A,I; LD I,A |
R | DRAM Refresh register | LD A,R; LD R,A |
IX, IY | Index registers | All LD, PUSH/POP, 16-bit arithmetic, block instructions, EXX. As IXH,IXL/IYH,IHL with LD, 8-bit arithmetic & logic. |
AF' | Shadow register | EX AF,AF' |
BC', DE', HL' | Shadow registers | EXX |
Instruction Set
Anything enclosed in (brackets) refers to the contents of the memory location pointed to. So LD HL,(0x4000) will store the first two bytes of screen RAM in L and H (the order is backwards because the Z80 is little-endian). Whenever IX or IY is used as a pointer, the instruction contains a literal 'displacement' byte, which is signed. This is typically used for tables and structs.
LD (Load) - many variants, all essentially of the form LD dest,src. Reads a byte or word from src and writes it to dest. Mostly take 4 T-states plus 3 for each byte of literal plus 4 if using IX/IY plus 3 if reading/writing memory plus 8 if using IX+d/IY+d.
LD r,s Register Direct Load 8-bit - r and s are 8-bit registers; if either is I or R then the other must be A LD r,n Register Load Literal 8-bit - r is an 8-bit register, n is an 8-bit literal LD r,(hh) Register Load Indirect 8-bit - r is an 8-bit register, hh is HL, IX+d or IY+d LD (hh),r As above LD (hh),n Load Indirect Literal 8-bit - hh is HL, IX+d or IY+d, n is an 8-bit literal LD SP,hh Register Direct Load 16-bit - hh is HL, IX or IY LD rr,nn Register Load Literal 16-bit - rr is a 16-bit register (BC, DE, HL, SP, IX or IY), nn is a 16-bit literal LD rr,(nn) Register Load Indirect 16-bit - rr is a 16-bit register (BC, DE, HL, SP, IX+d or IY+d), nn is a 16-bit literal. Value is read LSB first. LD (nn),rr As above LD A,(qq) Accumulator Load Indirect - qq is BC or DE, or a 16-bit literal LD (qq,A) As above
PUSH - store a value on the stack. Action is *--SP=rrh;*--SP=rrl; (in C notation).
PUSH rr Push 16-bit value to stack - rr is a 16-bit register (BC, DE, HL, SP, IX or IY)
POP - fetch a value from the stack. Action is *SP++=rrl;*SP++=rrh; (in C notation).
POP rr Pop 16-bit value from stack - rr is a 16-bit register (BC, DE, HL, SP, IX or IY)
(Not finished, obviously)