My First Z80 Program
I wrote a Z80 assembly program
for my RC2014 Zed computer.
I wanted to get a complete CP/M experience,
so I used the CP/M 2.2 ASM
assembler, LOAD
relocator,
and the DDT
debugger.
I did cheat a little. Although I used the vintage RED editor for some text input, I also wrote some on my Linux laptop, and transferred to the RC2014 Zed via XMODEM.
After cutting and pasting a Z80 assembly “hello world” program into a file, and getting the very basics of assembly, loading and running down, I decide to write the equivalent of this C program:
#include <stdio.h>
int
main(int ac, char **av)
{
int h;
char *array[4] = {
"item 1 Item 1\r\n",
"Second item SECOND\r\n",
"THIRD THIRD\r\n",
"four, fourth item 4th item\r\n",
};
for (h = 0; h < 4; ++h) {
printf(array[h]);
}
return 0;
}
That is, print strings by walking an array of pointers. Doing this would get me more Z80 assembly experience, in particular, doing double indirection through an array, and doing a loop.
This is what I came up with.
org 0100h
BDOS: equ 05h
WRTLINE: equ 09h ; DE contains .String
LF: equ 0Ah
CR: equ 0Dh
mvi h,00h
TOP
lxi b,array ; bc has address of array in it
mov a,c
add h
mov c,a
ldax b
; a has lower byte of address of item 1 in it
mov e,a
inr c ; what happens when c holds 0xff and you inr it? b should get incrementd, c zeroed.
ldax b
; a has high byte of address of item 1 in it
mov d,a
push h ; save HL on stack
; de has address item1 in it
mvi c,WRTLINE
call BDOS
pop h ; get HL back off stack
; increment H
mov a,h
adi 2
mov h,a
; loop termination
cpi 8
jnz TOP
ret
item1: db CR,LF,'Item 1 Item 1',CR,LF,'$'
item2: db CR,LF,'Second item SECOND',CR,LF,'$'
item3: db CR,LF,'THIRD THIRD',CR,LF,'$'
item4: db CR,LF,'four, fourth item 4th item',CR,LF,'$'
array:
dw item1
dw item2
dw item3
dw item4
Observations
- Z80 instruction set is quirky. You can only do “compares” against the A register, among other non-orthogonalities. I’m guessing this derives from keeping the instruction set small, for densely encoded instructions, but gee whiz.
- CP/M’s
ED
text editor is unfathomable even for line-oriented editors. - You can end up with a program that works “by magic”. At one point during development, I had a wrong address for a string, but the program appeared to print the string anyway, I think because CP/M just skipped some leading non-printable characters on output.
- CPUs without a way to protect the operating system from stray writes end up running extremely fragile systems. I had some bad crashes from sending incorrect pointers to the “write to console” BDOS call.
- The old CP/M manuals exhibit a strange style.
I get a disjoint feeling from reading them.
On the first read, I would think that something was undocumented,
only to find it in “the wrong section” or finding it concealed in a pile of
other text.
I haven’t felt this way about manuals since learning Unix
troff
back in the late 80s by reading what passed for a manual for it. - I’m beginning to understand why programs coded in assembly have odd failures.
There’s only 1 “load value from memory address in a register” instruct,
LDAX
. It only loads a byte. Addresses are 2 bytes. If you want to do double-indirection, and I did, you have to load a 2-byte-address one byte at a time. That means aLDAX
from some address, and anLDAX
from some address + 1. Without a carry, the secondLDAX
, from some address + 1 will underflow. Your program might want to load one byte of an address from 0x10ff, and a second byte from 0x1100. SinceLDAX
only loads a byte at a time, you should load the byte from 0x1100 first, then the byte from 0x1100 - 1, instead of loading the byte from 0x10ff, then the byte from 0x10ff + 1. Because the registers hold 8-bit values, if you do the address increment as I did above, withinr c
, I think it’s possible to overflow the C register and load the 2nd byte from 0x1000. - I see why Windows doesn’t have a TTY device to this very day. CP/M ran on such underpowered hardware that it just let user programs do a lot of terminal control. “DOS style” text files, that have a carriage return/line feed combination at the end of every line of text are actually “CP/M style” text files.