0% found this document useful (0 votes)
464 views

CrackingCodeZXSpectrum PDF

Uploaded by

Manolo Garcia
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
464 views

CrackingCodeZXSpectrum PDF

Uploaded by

Manolo Garcia
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 270

I

|
. \.;-'-_.
1 I" L 1
. ,-
|_ '.

Pan -

‘a
1

J-
_ _ 9075'"-|IEll LIBRARY _ *__ 1

__
—II|§L_

JOHN WILSON

I"""

w “

,'f‘

_z1:.,' 3- "-

:n|l- _ _ _--_ ___ ‘_€l~ __,____|_i-_ ____ ___ - _


—n

A hi.
P /Personal Computer New
C mputerLibra1y

lohn Wilson

Cracking the code


onthe
Sinclair ZX Spectrum

P n Books Lo don dSyd y


First published 1934 by Pan Books Ltd,
Cavaye Place, London SW10 9PG
in association with Personal Computer News
9 B F’ 6 5 4 3 2 1
@ john Wilson 1984
ISBN U 330 23665 X
Photoset by Parker Typesetting Service, Leicester
Printed and bound in Great Britain by
Richard Clay {The Chaucer Press) Ltd, Eiungay, Suffolk
This book is sold subject to the condition that it shall not,
by way of trade or otherwise, be lent, re-sold,
hired out or otherwise circulated without the publisher's prior consent
in any form of binding or cover other than that
in which it is published and without a similar condition including
this condition being imposed on the subsequent purchaser
j

Contents

Introduction 5
1 Chips, Registers and Numbers 7
2 Number Crunching 29
3 Rotating and Shifting 41
4 Making Comparisons and Checking Bits 51
5 Operating Logically 59
6 Block Manipulation 64
7 ASpectrum Monitor 72
8 Program Production 84
9 Using the ROM Routines 95
10 Screen and Attribute Handling 121
11 Interrupts on the Spectrum 140
12 Machine Code Miscellany 156
Appendices: 1 Z80 Instructions listed by Mnemonic 207
2 Z812) Instructions listed by Opcode 224
3 Flag operation table 241
4 Spectrum Monitor-Assembler Listing 243
Index 265
Introduction

This book is intended for people with a reasonable knowledge of


Sinclair BASIC and the Spectrum computer who now want to become
proficient in machine code programming.
Machine code is like BASIC in that it is a language for communi-
cation with the computer, but it differs in the way that precise
instructions have to be given in order to perform even the most
simple of calculations and operations. These machine code instruc-
tions and their use will be introduced and explained with the aid of
example programs, so that by the end of the book the reader and
user (a lot depends on practice!) will be a competent machine code
programmer.
The book starts by introducing the programmer to number repre-
sentation and goes on to simple loading and storing techniques. It
then proceeds through each set of instructions clearly and
methodically, with plenty of examples.
After the explanation of the instruction set the use of a monitor is
introduced and a full machine code monitor listing, which can be
utilised to enter other machine code routines in this book, is pro-
vided. This is followed by a detailed breakdown of a machine code
program.
Once these chapters have been digested the programmer can
progress to dealing with more complex techniques. These involve
using the ROM routines, screen handling, interrupts, and include a
routine to handle sprites. Finally, we have a chapter which includes
some useful machine code routines to enhance your own programs
such as a sort, music, and pixel scroll routines. In the appendices
are complete listings by Op code and Mnemonic of the Z80 instruc-
tion set.
1 Chips, registers and
numbers
The Spectrum’s central processing unit (cPu) or main control chip is
known as the Z80. This powerful little chip handles all the additions,
subtractions and logical operations with which the Spectrum
implements your BASIC and machine code programs. To communi-
cate to this chip when calculations and operations need to be done
the user can of course type instructions in BASIC. However, there are
other languages which can be used. The fastest of these is machine
code which acts directly on the Z80 chip and can be very efficient.
Machine code consists of a set of simple instructions which the Z80
CPU understands and can execute, such as addition, subtraction and
comparison. This particular chip has over 700 instructions that can
be sorted into a collection of a few different types. These instruc-
tions act upon data in the form of memory addresses and numbers.
BASIC is a very easy language in which to program due to the fact
that we write a line of BASIC almost as we would say it in English, so
that;

LET X=X+2l2l*2+1

means set the variable x equal to the correct value of X, plus twenty
times two, plus one. In machine code programming, however, we
have to give more precise instructions at a low level, and specify
each individual operation needed to perform the calculation.
The example above could be broken down to the sequence:

‘add 20 to itself’ (2*20)


‘add 1 to that resuit’ (2*20+1)
‘add x to that result’ (X+2*20+1)

‘and put the answer back in x’

It should be noted that the above is not an example of machine code


instructions but simply illustrates the precision with which machine
code operations have to be specified. Why should programmers use
this complex sequence of machine code instructions when BASIC is
8 Chips, registers and numbers

so easy? Let us look at an example to answer this question. First type


in this BASIC program and RUN it:

to FDR x=1a3e4 TD 22527


2a PDKE x,255
so next x
When RUN, the program very slowly fills the screen with ink. Now try
running an equivalent machine code program:
1 CLEAR 31999
18 FDR x=32BBB TD 32914
23 READ a: PDHE x,a
33 NEXT x
35 RQNDDHIZE USR 32360
43 DATA 33,B,b4,1,B,24,S4,255,
35,11,12B,177,32,24B,2@1

This program POKES a sequence of machine code instructions into


the Spectrum RAM. The DATA at line 60 is the machine code program
equivalent to the BASIC version given above. Each number represents
a certain instruction which the computer's ‘brain’, the ‘Z80 chip,
executes. (Don't try to understand the code yet, just type it in!)
RUN the program . . . but don’t blink, otherwise you will miss what
happens! As you can see from the example, machine code is incred-
ibly fast. An efficient machine code program can execute up to 1000
times as fast as the BASIC equivalent. What's more, machine code is
also compact. You can write machine code routines which occupy
only a quarter of the memoty that their BASIC counterparts would.
Why is BASIC so slow? Well, the reason lies in the fact that the Z80
chip (which does all the calculations for the Spectrum) can only
understand machine code. ln order for it to execute a BASIC pro-
gram, it first has to look up each BASIC keyword or token every time it
reads a line. lt then takes this token and translates or interprets it to
specify the equivalent ROM machine code routine so that it can then
perform the operation. This all takes time. Machine code, however,
is the Z80’s ‘Mother Tongue’, so no translation is needed and the
code is executed immediately.

Hexadecimal and binary


All of you should know that the Spectrum (or any other computer
for that matter) stores data in terms of ‘bytes’. A byte is an 8 bit
binary number which can have a decimal value of 0 to 255. In a 48K
Chips, registers and numbers 9

Spectrum there are 49152 locations in memory where bytes can be


stored. The value 49152 is obtained by the calculation 48*1024
because 1K=1024 bytes.
The Z8 chip stores numbers in groups of8 bits, so it is known as
an ’8 bit chip’. In this it is similar to the 6502 chip which is used in the
BBC Micro, Oric and Commodore machines. Other microprocessor
chips use 16 or 32 bits and are therefore known as ‘16 bit’ or "32 bit’
chips.
To address RAM the Z80 chip uses 2 bytes (or 16 bits) This means
that it can access 65536 characters, since the number of combi-
nations of 16 1‘s and 0's is 65536. These bits and how they represent
numbers and characters are best explained by looking at the system
known as the binary system (or ‘base two system‘).
In the real world of handling money we count in a system known
as decimal or ‘base 10 system’. We have the digits 0,1,2,3,4,5,6,7,8
and 9 which we can write to represent certain quantities.
In the decimal system we can break down the number we are
using into groups of powers of ten. That is units, tens, hundreds,
thousands, ten thousands, and soon. For example, the number 3456
can be broken down to:

3*1a00 3*10T3)
+4*100 4*10 T 2)
+5*10 5*10 T 1)
-l-0"" ‘il- -A /- .»- t.- .- I. 6*10 T 0)
In the binary system we use only two digits, these being 0 and 1. In
order to represent large numbers therefore we can only write in a
series of these two digits.
Remember that the Z80 chip represents information (numbers) in
groups of 8 bits. Each of these bits may be ‘off’ (i.e. digit 0) or ‘on’
(i.e. digit 1). The bits in a byte are numbered 0 to 7, starting from the
right.
In the binary system numbers are broken down in powers of two
(that‘s why it is also known as the base two system). That is to say we
break them down as factors of units (bit 0), two's (bit 1), four’s (bit
2), eight (bit 3), sixteen (bit 4), thirty-two (bit 5), sixty-four (bit 6) and
one hundred and twenty eight (bit 7).
Take for example the binary number 00011001, this represents the
decimal number:

$—_i_-M
10 Chips, registers and numbers

0*12a ,0*2'T7T
+0*64 at
i\-7
I)
S3
-t0*32 ,0*2 “st
__g__

+1*1s :1*2 T‘ 41»


+1*8 at-
I\-3
i>
El
-tm*4 '0*2"T2T
"-3-
-+0*2 '0*2'"1)
+1*1 ’1*2 T 0)
r

25 decimal

The maximum number that can be represented in 8 bit (one byte)


binary form is therefore 11111111, which represents 255 in decimal
('l28+64+32+'l6+8+4+2+'l).
In order to deal with larger numbers the Z80 has some 16 bit
instructions. All memory addressing is done with 16 bits, so the total
number of individual bytes that can be pointed to in memory
(addressed) should be equal to the total number of combinations of
a 16 digit binary number. This will be equal to the maximum value
+1 (since the value zero is a unique combination).
To obtain the maximum value possibIe in a 16 digit binary number
we must evaluate 1111111111111111. Th's has a value of:

1 *32768
+1 *16384 (1 *
+1 *8192
+1 *4096
*2048
024 X
\‘it
¢.lt.1L,.,l
I
to
*2ss
*12s
#64 k y

*32 *2’* 53
*6)
Q\
-1
f1*

*
-l(-
-1-
-it31-
-if'
-if')l'
‘li- >>>->-> >- 2:->
l‘\-J>l\tJIl~\J t~JlI\*>tJ 9§.‘~!9.\Q .-'5!‘2.?-*2_.le-i§1'!_"*-259.-1*"
*
'll-
-it
U1--\I~-.A>-I:=-o -=
-)i-‘if-if
-if
[1*2
+'3
:3 ——§'I—“2-K “
iiKS_i:1
:1
3'"T—i
'—i 0]
+ + -I + + + + ‘L\1-\r\
\
i
.\.\t\-.\
\e%

65536
OR 64K (1 K=1024 bytes)
Chips, registers and numbers 11

The Spectrum uses 16K of this for its BASIC ROM, which is why the
maximum amount of RAM in a standard Spectrum is 48K.
When 16 bit values are stored in memory, something strange
happens. Since 16 bit values are made from two bytes and only one
byte can be held in one memory location, It follows that a 16 bit
value must occupy two bytes in memory. The way that they are
stored is that the least significant byte (LSB), which is the right hand
group of 8 bits, is stored in the first address and the most significant
byte (MSB), which is the left hand group of8 bits, is stored in the next
address. It would appear that this was a strange way for the chip
designers to build the Z80 but the reason is that the Z80, like other
common microprocessor chips, has evolved from simpler chips that
did not have any 16 bit operations. These older chips only used 8
bits to address memory and so they could only address a maximum
-,_'—-_—

of 256 bytes (1/4 K). When the newer chips were designed the extra
work involved in storing 16 bit values for addresses etc. was sim-
plified. This was done by storing the old 8 bit address (the LSB)
followed by the rest of the new 16 bit address. This does cause some
problems for novice machine code programmers but soon you will
understand. The following diagram should simplify the explanation.

16 bit value 1010001010110101


<MSB> <.'LSB>

Address... l __ - l 10110101
Add ress+1 10100010

Address and Address+1 can be any two addresses in RAM.

Negative integer numbers


We mentioned earlier how we represent numbers on the Z80 by
having 8 binary bits to represent positive numbers from 0 to 255 i.e.
00000000 binary to 11111111 binary. To represent negative numbers
we can use a convention known as signed integer representation.
Signed integer representation uses the most significant (or leftmost)
bit of an integer to represent the sign. If the sign bit is 1 (high or set)
then the number is negative, and if it is 0 (low or reset) then the
number is positive. To get an 8 bit negative number binary repre-
sentation we subtract the equivalent positive number value from 256
So, for example, the negative number -12 is equivalent to the
number 256—12=244 decimal or 11110100 binary. Using signed
integer representation we can represent numbers from -128 to
+127 decimal. The Z80 chip, whether adding signed or normal
HI lllflll-"""“"""_'_'—" 7

12 Chips, registers and numbers

integers will deal automatically with any addition or subtraction.


The same applies for obtaining negative 16 bit values, with the
exception that bit 15 will be set to 1 if the value is negative (instead
of bit 7 as in 8 bit values). To get the 16 bit representation of -12 do
the following: 65536—12=65524 decimal or 11111111 11110100. 16
bit values can be between -3-2768 to +32767.
A quick way of finding the negative representation of an 8 bit or 16
bit integer is to use a method known as two's complement. We first
get the binary representation of the positive number and comple-
ment each of it's 8 or 16 bits and then add one to our new result.
Complementing means that we transform each 0 into a 1 and each 1
is transformed into a 0. For example, suppose we wanted to find the
binary representation of the number —180 decimal. The 16 bit binary
pattern for the number 180 is 000000010110100.The complement of
this number is:

1111111101001011
adding one + 1
1111111101001100

Since —180is outside the range of -128 to +127 this value could not
be held in a single byte.
Another number system we need to know before we go any
further is the base 16 or hexadecimal system. Base 16 refers to the
fact that this number system has 16 digits:
0,1 ,2,3,4,5,6,7,8,9,10,11 ,12,13,14 and 15.
In order not to confuse between the number 10 and the digits 1,0 we
write the five highest digits as:

Afor the number10


B for the number11
Cforthe number12
Dforthe number 13
Eforthe number 14
Fforthe number15

So the sequence of digits becomes:

0,1 ,2,3,4,5,6,7,8,9,A,B,C,D,E,F

Using the same principle as found in the base two and base 1
systems we break down the number in a hexadecimal system into
multiples of 16. Take, for example, the hex number 20 (H or h after a
Chips, registers and numbers 13

number distinguishes between hex and decimal numbers) so that


20H is clearly different from 20 decimal. This means
2*16+0*1=32+0=32 decimal.
The number AFH means 16*A+F*1. Since A in hexadecimal not-
ation is 10 decimal, and F is 15, this gives 16*10+15*1=160+15=175
decimal.
The hexadecimal notation is widely used by machine code pro-
grammers since it makes numbers easier to remember than binary
but more significant than decimal. Because the hexadecimal system
is based on 16 (10H), and 16 is 10000 in binary, there is a close
relationship between the binary system that the Z80 chip uses and
the hexadecimal notation that most programmers use. Unfor-
tunately there is no simple relationship between the decimal and
binary systems, as the table below should illustrate:

BINARY DECIMAL HEXADECIMAL


l 10101011 171 AB
I 00010010 18 12
10000001 129 81
11110000 240 F0

8 bit hexadec'mal values have up to two digits. These each represent


the value in one nybble of the byte. A nybble consists of four bits,
either the leftmost four or the rightmost four and by taking the value
of each nybble the Hexadecimal digit can be calculated. In the
example above the binary value 10101011 is shown to have a hex-
adecimal value of AB. This can be illustrated by taking the high
nybble (1010) which equals 10 decimal (A in hex) and the low nybble
(1011) which equals 11 decimal (B in hex), then combining them in
the same order to give ABI-I.
So far we have only seen machine code entered by POKEl|"|g
numbers into memory. This method of writing machine code is
tedious and makes it difficult to understand and debug the code, so
the designers of the Z80 chip developed a standard set of
mnemonics in which to write Z80 code.
These Mnemonics are English-like words which (hopefully!) sig-
nify the action a particular instruction performs. For example, the
mnemonic RET means RETUIT1 and is equivalent to the RETURN instruc-
tion in BASIC, ie. it tells the processor to continue with the main
program after a subroutine was called.
In order to translate these mnemonics into data which the com-
puter understands we will need to assemble them. This can be done
by hand but more often by a utility known as an assembler. The
14 Chips, registers and numbers

programmer first of all types in a program in standard mnemonics


and then the program assembles these instructions into machine
language. Most machine code programmers write assembly code
and use an assembler to create their machine code
When an assembler translates the RETll'|Sll'UC'[lOt1 it puts into mem-
ory the value for that instruction, which is 201 decimal, C9 hex-
adecimal or 11001001 in binary.
There are plenty of good assemblers for the Spectrum on the
market ranging in price from around £7 to £14. Most of these will
work on both the 16K and 48K models. The ‘Devpac’ package from
Hi-Soft, as an example, is at the top of this price range, but is good
value. In addition to the assembler it comes with another package
known as a monitor. Alternatively, Chapter 7 provides you with your
own monitor program for only the cost of wear and tear on the
fingertips. This is a utility which will allow you to enter and experi-
ment with the routines in this book.
A monitor program allows the machine code programmer to input
and look at a program in hexadecimal form. Other features often
included with it are utilities to set break points, look at the values
held in the registers (the Z80 ‘variables’) and to move, save and load
blocks of memory. Both the Spectrum monitor provided in this
book and the Devpac monitor have all these standard features.
Devpac’s also includes the capacity to move a single step at a time
through a machine code program. There is also a disassembler in
the Devpac package. This is a routine which is the opposite of an
assembler for it converts machine code binary data into Z80
mnemonics.
When seeking an assembler for your Spectrum you are advised to
buy one which allows you to assemble a program at different
addresses in memory. Most assemblers have a command ORG
(oRioin) which tells the assembler the start address from which to
assemble the program. This is illustrated in the assembler listings
included in this book.
There are certain features of assembler listings that need to be
explained here otherwise confusion may occur. Assemblers have a
feature which enables them to use what are known as ‘pseudo’
operators. These are used to place strings or numbers in memory
and are not standard Z80 mnemonics. They are only a feature used
in certain assemblers, including the one used for the listings in this
book.
DEFB Define Byte
Can sometimes be abbreviated to ‘DB’. This places the following
data in memory. For example:
Chips, registers and numbers 15

DB 02H,04H

would place the number 2 followed by a 4 at the location where it is


being assembled.
DEFWDefine Word
This is similar to DEFB but is used to place a two byte number in
memory. The low byte of the given number is placed in location
where it is assembled. The high byte will follow, as we explained
earlier when 16 bit values were introduced:

DEFW 7 (equivalent to DEFW 0007i-I)

is the same as:

DB 0,7 (equivalent to DB 00H,07I-I)

DEFS Define Space


The number following this Psuedo operator is the number of bytes
which we want to reserve. So the operator:

DEFS 100

Would reserve 100 bytes.


EQU Equate
This instruction is used to give values to labels. The format is a label,
followed by the EQU, followed by a number:

PLOT EQU 22E5H

The above would give the label PLOT the value 22E5 hex.
,' Comment
In most assemblers the ; is used in the same manner as the BASIC REM
to indicate a useful remark or comment. This is very useful because
without helpful comments assemble code is harder to understand
than BASIC because the operations are less immediately obvious.
Another feature of machine code assemblers is the facility to refer
to memory addresses by means of labels. Instead of entering an
instruction which says ‘Jump to Address 31000‘, we can set a label at
the address 31000. We could assign the label the name ‘Fred’, for
example, and then give an instruction ‘Jump to Address Fred‘. This
can greatly simplify our program structure and also enables mean-
ingful label names to be assigned to sections of code.
16 Chips, registers and numbers

If you use the appendices of this book you will be able to


assemble your own machine code programs. The first thing you
need to do is to write the assembly code (Mnemonics) for your
program. I have provided an example below which will go into the
printer buffer to avoid you having to CLEAR high memory space:

ORG 23296 ; Start the code at the printer buffer


LD HL,4000I-I
LD DE,4001H
LD BC,17FFI-I
LD (HL),0
LDIR
RET

The effect of this program is to remove all the ink from the screen
How it does so is not important currently because it is serving only
to demonstrate how you can get machine code to work without
buying an assembler program.
The ORG is not a part of the machine code but it shows where in
memory the machine Code must be stored. This is the address into
which we will start to POKE the data.
To obtain the data for each of the mnemonics above you will need
to look them up in Appendix 2. As an example, the entry for LD HL,
4000H will read:

Mnemonic Decimal Hex


LD HL,XXXX 33 XXX XXX 21 XX XX

In order to get the hex for LD HL,4000H the 4000H must be converted
into two bytes and reversed in order (due to the tsBiMsB storage
convention explained earlier).
So, LD HL,4000H will assemble to 21 0 40 in hex or 33 0 64 in
decimal. Since we will be using a BASIC program to POKE the code you
will need to calculate the decimal values to be placed in the data
statement. I have calculated the example for you but try to follow
through the procedure to make sure you understand the principles
involved.
Chips, registers and numbers 17

HEX DEC MNEMONICS


ORG 23296
21 00 40 LD HL,4000H
11 01 40 LD DE,4001 H
01 FF 17 1 2 U1 fiii LDBC,17FFH
LBJ G1 S S U1-l.»-"-lJ4‘l->~H EU‘!-—\$ LD (H L),0
ED B0 237 176 LDIR
D9 201 RET

Now to enter this machine code program the following BASIC pro-
gram Could be used:

10 FOR [=0 TO 703:PRll\lT CHR$(32+ll\lT (128*RND)); ZNEXT I


20 LET A=23296
30 READ B: IF B=—1 THEN GOTO 50
40 POKEA,B:LETA=A+1:GOTO 30
50 PRINT #0: "PRESS A KEY TO CLEAR":PAUSE 1 :PAUSE 0
60 RANDOMIZE USR23296
70 DATA 33,0,64,17,1,64,1 ,255,23,54,0,237,176,201,—1

As you can probably see, this would be a reasonable way to write


small programs of up to about 100 bytes but to write your first full
machine code 48K mega-game you will need an assembler to
shorten the development time. Another considerable advantage of
using an assembler program is that you can save the source code
(assembly code or mnemonics). It than can be loaded back from
tape or microdrive and errors can be corrected in the machine or
object code.

Registers
The Z80 CPU has several registers available to the programmer. These
can be used to hold numeric values similar to BASIC variables but the
programmer is limited to 22 registers. Some of these registers can be
used in pairs to hold 16 bit values. The older chips such as the 6502
are unable to do this. The Z80 registers are referenced by the
names:

A,B,C,D,E,F,H,L,lX,lY,SP,PC,l and R

From these A, B, C, D, E, H, L can all hold 8 bit values and Ix, IY, SP and
PC will hold 16 bit values. Registers SP, PC, F, I and R have specific
functions which will be explained later and are not used for holding
user data. In addition to these there is a second set ofA, B, C, D, E, F, H
18 Chips, registers and numbers

and L registers which are usually referred to as A’, B’, C’, o’, E’, F‘, H‘
and L’. These two sets of registers cannot be used at the same time,
so in order to access the alternate set a special instruction has to be
used, ‘I5xx‘ (Exchange) which flips from one register set to the other.
(Two exceptions here are the A’ and F’ registers which are exchanged
using EX AF, AF’)
As mentioned earlier, some of these 8 bit registers can be paired
off to form one sixteen bit register. The diagram below demons-
trates how this can be done:

A 9 F A’ F’
B C B’ C’
D E D’ E’
H , L A H‘ L’ I
IX
IY
SP
PC

Now let's take a more detailed look at each of the registers that we
have just introduced and their functions.
IXand lYRegisters
These are known as the Index registers. The IX and IY registers are
often used to point to tables of data and are extermely powerful
tools for accessing arrays of data by a method known as indexing.
On the Spectrum great care must be taken before using the IY index
register in your own machine code programs. A number of ROM
routines require that IY contains the value 5C3Ai-i (23610 decimal)
otherwise they will not work correctly. The Interrupt routine also
requires this value to be in IY. Therefore if you must use IY in your
machine code, disable the interrupts and make sure that IY“‘5C3AH
before calling any ROM subroutines or returning to BASIC. Disabling
interrupts and ROM subroutines are dealt with later in this book.
land R Registers
The I or Interrupt register is used in conjunction with a technique
known as vectored interrupt programming. This is the Z80’s pointer
Chips, registers and numbers 19

for alternative interrupt routines and is described in detail in


Chapter11.
The R or Refresh register is used to refresh any dynamic ram con-
nected to the Z80. The only purpose it serves for Spectrum pro-
grammers is its use in random number generation.
A Register
The A register is known as the Accumulator and is the main register
for performing 8 bit arithmetic and logical operations.
FRegister
The F or Flag register indicates the state of certain arithmetic condi-
tions after particular groups of instructions have been executed. A
large number of Z80 instructions set flags depending on the values
in various registers (usually A). When a flag is set, a bit in the F
register is set to 1. For example if the result of a subtraction was
zero the Z flag would be set to 1. That is, bit 6 of the F register would
be on. There are other instructions that will only work if a particular
flag is set. One example of this would be RET z. This means if the z
flag is setthen RET (return from subroutine), otherwise do nothing.

mxr Now ><u1 In ><t.-2 gm Z--‘L OS

The Flag register has 8 bits which can be either high or low (1 or 0).
Each of these bits is set if certain conditions exist, although bits 3
and 5 are not actually used. If you want to see the mnemonics for
each instruction and how the flags are affected you can find them in
Appendix 3.

Carry flag
The Carry flag indicates whether there was an overflow from bit 7 of
a register. It is mostly affected by addition, subtraction or shift
instructions. By overflow we mean that, for example, adding 250 to
250 would give a value of 500. However the maximum value that can
be held in 8 bits is 255 so the actual value left would be 244. Since the
Carry flag would be set we know that the real value is 244+256 (500).
The same applies to 16 bit values where a result would exceed 65535.
Some sample instructions that use the result of this flag are:
Rsrc; RETURN IF CARRY FLAG set
JP NC, ADDRESS; JUMP to Address if CARRY not set
Nflag
The N flag, know as the add/subtract flag, cannot be used directly by

Z-?____ __———~—-— -
20 Chips, registers and numbers

the programmer. It is used by the Z80 chip to record whether the


last operation was a subtraction or an addition.
Parity/overflow flag
This is a dual purpose flag. When used to indicate parity the Parity
flag is set (i.e. 1) if there is an even number of bits in the byte set to
one. It is reset (i.e. 0) if the number of bits set to one is odd.
The flag can be used to represent overflow, if it is set when an
arithmetic overflow occurs during an arithmetic operation. This
might happen in an addition or subtraction operation involving two
numbers with the same sign (i.e. both positive or both negative) and
it changes the sign in the result.
Hflag
The Half carry flag is used to indicate a carry from bit 3 of a byte to
bit 4 of a byte.

The H and N flags are used by the CPU in order to do something


known as binary coded decimal arithmetic (more about this later!)
Zero flag
The Zero flag is set by certain instructions when the result of that
execution is zero.
Sign flag
The Sign flag is set by certain instructions which show the sign of a
result i.e. if the result was negative then the Sign flag would be set.
If the result was positive then the Sign flag would be reset.
HL ’ Register pair
These are the alternate H and L registers working as a 16 bit HL’ regis-
ter. It is included here just to serye as a warning about using HL’ in
USR subroutines. HL' is used to point to the caculator stack during
USR subroutines and BASIC will probably crash if you RETURN to BASIC
with HL' changed.
PC Register
The PC, or Program Counter is a 16 bit register that holds the address
in memory of the instruction currently being executed.
The SP Register
The SP or Stack Pointer is another 16 bit register. This one points to
the current address at the top of the stack. Unlike the term queue,
which indicates that literally the first item in is the first item out, the
stack is a term used to represent data held in the reverse order, in
which the last item placed will be the first item out. (This is
sometimes known as a LIFO ‘Last In First Out‘ list).
Chips, registers and numbers 21

Imagine a pile of books onto which more books are placed. In


order to get to the bottom of the pile the last book placed on top will
have to be the first one removed. This analogy is very similar to the
way in which the stack works on the Z80.
If we wish to call a routine in machine code we use an instruction
CALL (This is similar to the COSUB instruction in BASIC). When the Z80
executes a CALL instruction it places the return address onto the
stack. The return address is always PC+3, because the CALL instruc-
tion is three bytes long and the subroutine must RETUTI1 at the start of
the next instruction after the CALL. It then gets the CALL address and
puts this into the Program Counter (PC register). You will need to
remember that the Program Counter points to the location of the
instruction currently being executed, so the program will carry on
running from that address. When the Z80 meets a RET instruction
(RETUFI1) the chip then POPS the return address from the stack and
places it back into the PC register.
This is very similar to what happens in a BASIC program when it
executes the COSUB command and then RETURNS. As well as saving
return addresses, the stack can also be used to save data. (This can
prove useful when you start to run out of registers.) For example we
can save the HL register pair by using the instruction:

PUSH HL

This means ‘PUSH the HL register pair on the stack‘. We could now
use the register pair for other calculations if we wanted to, knowing
that we have a Copy on the stack. To retrieve data from the stack we
use the instruction:

POP HL

This means ‘POP the data on top of the stack into the HL register pair‘.
It is important, however, to note the order in which we PUSH and POP
data. For example, if we use the instructions:

PUSH HL
PUSH BC
22 Chips, registers and numbers

we must remember to POP the data in the reverse order to that in


which we originally pushed them. So to place the data back into the
same registers we would need to use the instructions:

POP BC
POP HL

Ifwe popped the data from the stack with:

POP HL
POP BC

then it would become apparent that the register pairs had been
changed over. This can be a useful way of moving data within the
chip but care must be taken when using the stack. Problems will
arise when a PUSH or POP instruction is missing because a RE!‘ could
POP some data and RETurn to the wrong address. A large proportion
of machine code ‘crashes’ are caused by programmers wrongly
using the stack in this way. Remember ‘Last In First Out‘
Let us examine the following code:

LD HL,0
PUSH HL
RET

The first instruction tells the computer to load the HL register pair
with the number 0. The second is the PUSH instruction which places
the HL pair onto the stack and leaves the number 0 on the top of the
stack. The last instruction is the REIUITI instruction which retrieves
the last 16 bit number on the stack and places it into the program
counter. Since the top of the stack contains 0 the program will start
to run from address 0000 — Bad news if you have not sA\/Ed your
program!

Loading and storing


In order to manipulate information from one register to the other,
from RAM to registers and vice-versa, we need to use what is known
as loading operations. These operations can be used on both 8 bit
and 16 bit registers and constitute the major part of the Z80 instruc-
tion set. So learn them well!
First let us look at a few 8 bit LOAD operations:
Chips, registers and numbers 23

3E 16 LD A,22

The above instruction means ‘LOAD the A register with the value 22
decimal’. It does precisely what it says: it puts the value 22 into the A
register. The two digits on the Iefthand side of the operation are its
hexadecimal equivalent, which are POI<Ed into memory or typed in
using a monitor. (An assembler does automatically.) We can also
LOAD other 8 bit registers with data.
Examples

06 16 ;. B,22 ;LOAD B register with 22 decimal


06 22 '_ B,22H ;LOAD C register with 22 hex
2E 04 _ L,4 ;LOA3 L register with 4 decimal
0E 0C _ C,12 ;LOAD C register with 12 decimal
16 10 _ D,10H ;LOAD D register with 10 hex
1E FF _ E,255 ;LOAD E register with 255 decimal
26 56 _ UUUUUUU H,56H ;LOAD H register with 56 hex

Here too the hexadecimal translation is given on the Iefthand side of


the mnemonic.
If you look at the first two examples, which LOAD the B register,
you might notice something similar in their hexadecimal output.
The first byte (06H) is the same in both instances. It is not a coinci-
dence. The first byte of the instruction is known as the Op code and
tells the computer which register we are dealing with. The second
byte is the actual data which we are LOADing into the register. It is
important to note that it is not possible to have an instruction such
BS1

LD A,289
‘LoaDA register with 289 decimal’

This is because the number 289 takes more than 8 bits to represent
it. We can however LOAD register pairs with 16 bit numbers.
16 bit LOADS
As we have mentioned before the Z80 chip has the facility for pairing
off registers, a feature which gives access to some powerful 16 bit
commands.
Let us recap which registers can be paired off together:
24 Chips, registers and numbers

AF AF‘
BC BC‘
DE DE‘
HL HL'

You can see from the diagram that the registers (with the exception
of the Accumulator and Flag registers) are paired off in alphabetical
order. The Ix, IY, SP and PC registers have not been included in the
diagram as these are true 16 bit registers and are not split into two
like the others.
Let us now take a look at some 16 bit LOAD operations.

21 00 40 LD HL,16384

This means ‘LoaD the HL register pair with 16384 decimal‘ (4000r-I) If
you look at the hex translation, this time there are 3 bytes to repre-
sent the instruction. The first is the Op code for ‘Lo HL’ and the last
two are the data. The low part of the data is the second byte and the
high part is the third byte. (Remember that the Z80 stores 16 bit
values in the opposite way to which you would write them!)
Other examples of 16 bit LOAD operations are given below. (HH is
the high byte of a number in hex while LL is the low byte).
01 LL HH LD BC,HHLL
11 LL HH LD DE,HHLL
31 LL HH LD SP,HHLL
DD 21 LL HH LD IX,HHLL
FD 21 LL HH LD IY,HHLL

Loading from one register to another


As well as LoADing 8 bit and 16 bit numbers into registers it is also
possible to transfer information from one register into another.
Consider these examples:

78 LD A,B
79 LD A,C
6B LD L,E

The first example reads ‘LoaD the A register with the B register’. If, for
example, we had the instructions:

06 02 LD B,2 ;loadBregisterwith2
Chips, registers and numbers 25

and then added the following instruction:

78 LD A,B

we would find that the A register would take the contents of the B
register, thus ending up with the value 2.
The Z80 chip does not have 16 bit instructions such as:

LD HL,DE ;load HL pair with DE pair????

so in order to achieve the same effect it is necessary to use a


Couple of 8 bit transfers, like this:

62 LD H,D ;load H register with D register


6B LD L,E ;load L register with E register

Easy, isn’t it!


The only 16 bit register to register load operations allowed in Z80
code are the following which deal exclusively with the stack
pointer.

F9 LD SP,HL
DD F9 LD SP,lX
FD F9 LD SP,lY

The next mode of addressing data is very similar to the way in


which the BASIC instruction PEEK and POKE work. We are going to
look at examples which load and store from locations in RAM and
ROM.

3A 00 40 LD A,(16384)

The instruction above reads ’LoaD the A register with the contents
of the address 16384 (4000H). You can think of it as being similar to
the BASIC instruction:

LET x=PEEl((16384)

The number at the location 16384 is put into the A register. We


could also put the contents of the A register into RAM by the
instruction:

32 LL HH LD (ADDRESS),A

L —
26 Chips, registers and numbers

If we used the following instructions:

3E FF LD A,255
32 00 40 LD (16384),A

the first instruction would LoaD the A register with the value 255 and
the second would put the value of this register into the address 16384.
The Accumulator is the only 8 bit register which allows us to do this
kind of addressing. There are no instructions such as:

LD (16384)B, ;load the address 16384


with b?

One way to get over this problem would be to use the instruction:
78 LD A,B ;let A register=B register
32 00 40 LD (16384),A ; put A register in 16384

Sixteen bit addressing in this mode is quite extensive; here are some
examples of the instructions allowed.

ED 4B LL HH LD BC,(HHLL)
ED 5B LL HH LD DE,(HHLL)
ED 6B LL HH LD HL,(HHLL) ;mostassemblers use the fasterform
ofthis instruction which is 2A LL HH
DD 2A LL HH LD IX,(HHLL)
FD 2A LL HH LD IY,(HHLL)
ED 7B LL HH LD SP,(HHLL)

These instructions are 16 bit load instructions so they read two bytes
from a given address. We Could use:

2A 53 SC LD HL,(23635)

which reads ’LoaD the HL register pair with the contents of address
23635(5C53H). This would take the Contents of the address 23635 and
place them in the L register (low byte first). Finally it would take the
contents of 23635+1 (i.e. 23636) and place it in the H register.
It is also possible to save the contents of registers at a given
address, as follows:

ED 63 00 40 LD (16384),HL ;most assemblers would use the more


efficient 22 00 40 form of this
instruction
Chips, registers and numbers 27

’LoaD at the location 16384 the value in the HL register pair.‘

This instruction will put the value of the L register at the address
16384 and then put the value of H at the address 16385.

21 AA 22 LD HL,22AAh ;lOad HLwith 22AA hex


22 00 40 LD (16384),HL

The two instructions above would load AA hex at location 16384 and
22 hex at the location 16385.
Now suppose we wanted to load a value into the A register from
an address which we did not directly know. The address can be
worked out from a calculation. We would address that value by a
method known as register indirect addressing. Sounds complicated,
doesn't it? Don‘t worry, it's all very easy. All this means is that
instead of giving an address directly to load from we have that
address pointed to by a register pair, as you will see.

7E LD A,(HL)

The instruction above reads: 'LoaD the A register with the Contents
pointed by the address in the HL register pair’. If HL contained 16384
then the contents of that address would be put in the A register.
It is also possible to save using register indirect addressing, as
follows:

77 LD (HL),A
12 LD (DE),A
36 22 LD (HL),22h ;load 22h atthe addressin HL

The last instruction here is unique to the HL register pair. It is one of


the most important and powerful register pairs available on the Z80
chip.
Last, but by no means least, is the powerful index addressing
mode. These use the IX and IY registers and are extremely useful in
accessing arrays of data.
The index modes are in the form:

DD RR NN 4-» (lX+nn)
FD RR NN ‘_ (lY+nn)
DD RR NN Q IX+nn),r
FD RR NN L lY+nn),r
DD 36 Nl\’ dd lX+nn),d
FD 36 NN dd 560066 lY+nn),d
28 Chips, registers and numbers

where RR depends upon the register being used and dd represents


the data. r is any of the registers A,B,C,D,E,H,L. nn is an offset with the
value of 0 to 127 & 0 to -128. This is derived from the signed binary
value of the number, which is added to the value of the index
register. The store or load is then done at the resultant address. d is
a byte value which can be loaded and stored directly.
Consider the following:

DD 21 00 60 LD lX,6000h
DD 4E 05 LD C,(lX+05)
DD 36 00 03 LD (lX+00),03
addressdata

6000 00
6001 02
6002 04
6003 05
6005 06
6006 07

After executing the first line the Ix register is pointing to the portion
of RAM/ROM at the address 6000 hex. When the second instruction
is executed, the offset value 05 is added to the value of the IX regis-
ter, which equals 6005 hex, and the contents of this location are put
into the C register. Thus, the C register will contain the value 06.
Note that the address in the Ix register is not changed in any way.
After executing this instruction it merely accesses the contents of
that address. The last instruction:

LD (lX+00),03

goes through the similar process of working the offset address


which is 6000+0=6000 hex and this time stores the value 03 at that
address. The IY register works in a similar way . . . but a word of
warning! If you are using the IY register on the Spectrum be very
careful when mixing machine code with BASIC, as the Spectrum uses
the IY register to point to the system variables. The procedure, as
explained earlier when you were introduced to the IY register,
would have to be applied when using the IY register in your own
programs.
2 Number crunching

So far we have looked at the way the Z80 stores data and how it can
transfer values and control from one address to another. In this
chapter we Come to the actual number crunching instructions used
in addition and subtraction. As was pointed out before, the main
advantage of the Z80 chip over other 8 bit microprocessors is that it
can handle 16 bit numbers directly, making addition and subtraction
operations that much easier. To begin with let's take a look at the 8
bit arithmetic instructions.
The two simplest number crunching instructions are DEC, ‘Decre-
ment register‘ and INC, ‘INCrement register‘. These two instructions
respectively subtract or add 1 to the value in a Specified register. We
are allowed to use single registers A,B,C,D,E,L and H, with these
instructions, so the range of possible commands is:

DEC A
DEC B
DEC C
DEC D
DEC E
DEC H
DEC L ZZFZZZZnn n nci cImUnw>

The Accumulator or A register is one of the main registers in the Z80


chip and allows 8 bit arithmetic operations which can work directly
with other registers and numbers. To add to the A register a value
held in another register we use the instruction:

ADD A,r

which means ‘Add to the Accumulator the value in register r‘, where
r can be any register ofA,B,C,D,e,H or L.
If we wanted to add numbers directly to the Accumulator we
could use the instruction:

ADD A,N
30 Number crunching

where N is any 8 bit number. So for example, ADD A,5 would add 5 to
the Accumulator.
We can also use the ADD instruction in conjunction with some-
thing known as indirect addressing. The HL register pair contains an
address where the actual number which we wish to add to the
Accumulator is stored:

ADD A,(HL)

The above instruction actually performs the operation ‘add to the


Accumulator the contents of the location pointed to by the register
pair HL’. Take for example the following code:

LD A,8
LD HL,6000H
ADD A,(HL)

We'll assume we have the following data stored in memory from


address 6000 hex onwards:

Address Contents
6000H 02
6001 H 03
6002H 06
6003H 07

The first instruction would set the Accumulator to 8 decimal. The HL


register pair is then set to point to the address 6000 hex. The final
instruction then gets the value from the address at HL (i.e. 6000 hex)
and adds it to the Accumulator. This leaves it with the value 10
decimal.
Pursuing the indirect method even further, it can also be used
with indexing utilising the Ix or IY registers.
Using the same data and starting at address 6000 hex let us run
through the following example to demonstrate this:

LD A,0
LD lX,6000H
ADD A,(lX+0)
ADD A,(lX+3)

The first and second instructions are simple enough. These set the A
register to zero and the Ix register to the address 6000 hex.
Number crunching 31

ADD A,(lX+0)

The instruction above adds the index to the address in the Ix regis-
ter. This new address is then used to point to the data which we wish
to use. Since our index is zero, the address calculated is
6000H+0H=6000H. Therefore the contents are taken from this
address and added to the accumulator, leaving it with a value of 2
after the first ADD instruction. The second addition is similar but uses
the index 3, which means that the data to be added is stored at the
address 6000H+03H=6003I-I and has the value 07. When this is added
to the Accumulator the final result will be 9.
Subtraction works on the same registers as the ADD instruction,
the mnemonic being SUB. Again every operation is done on the A
register but the actual format of the mnemonic is slightly different as
it does not actually mention the A register. The operand follows the
SUB instruction directly. For example, to add the B register to the A
register we would write:

ADD A,B

but to subtract the B register from the Accumulator we would write:

SUB B

Not too confusing, hopefully!

ADD A,A
ADD A,B
ADD A,C
ADD A,D
ADD A,E
ADD A,H
ADD A,L
ADD A,(HL) HL)
ADD A, (IX+d) IX+d)
ADD A, (IY+d) IY+d)
ADD .>Z U1LfJi.D(flL i.fl£ U1i.f'tLfi fJ ("C't“.f'_ .f'{"ETf"(—_t"' CU WCD U UZI JU UC

It is useful to note that ADD A, A is a quick and efficient instruction for


doubling the value in the A register. SUBA is a quick way of setting the
A register to zero (it works nearly twice as fast as LD A,0 and only takes
up one byte instead of two).
32 Number crunching

Using the Carry flag


There is another set of 8 bit arithmetic instructions which take into
account the state of the Carry flag. These are known as the ADC (Add
with Carry) and SBC (Subtract with Carry).
In the case of addition the ADC adds the state of the carry flag as
well as the given register or data. So, for example, if the A register
contained 5 and the Carry flag was high (i.e. set to 1), if we ran the
instruction:

ADC A,2

the answer left in the A register would be 5+2+1=8. On the other


hand, if the Carry flag were to be reset we would return with the
answer 7 as with the normal addition.
When it comes to subtraction, we subtract the state of the Carry
flag from the Accumulator. So, if we had 5 in the A register and the
Carry flag was set, the instruction:

SBC A,3

would leave the answer in the Accumulator as 5-2-1 =2

ADC A,A SBC A


ADC A,B SBC A,B
ADC A,C SBC A,C
ADC A,D SBC A,D
ADC A,E SBC A,E
ADC A,H SBC A,H
ADC A,L SBC A,L
ADC A,(HL) SBC A,(HL)
ADC A,(lX+d) SBC A,(lX+d)
ADC A,(lY+d) SBC A,(lY+d)

The 16 bit increment and decrement instructions work in exactly the


same manner as their 8 bit equivalents, but on pairs as opposed to
single registers. The instruction DEC BC subtracts 1 from the value
held in the BC register pair, while the instruction INC DE adds 1 to the
De pair. Because we are dealing with 16 bit operations we also have
the option to increment or decrement the Ix, IY and SP registers.
Number crunching 33

INC BC DEC BC
INC DE DEC DE
INC HL DEC HL
INC IX DEC IX
INC IY DEC IY
INC SP DEC SP

16 bit addition is quite versatile on the Z80. It allows the user to add
(with or without Carry) other 16 bit registers to the HL, Ix or IY register
pair. Subtraction, however, is limited to subtracting the registers BC,
DE, HL and SP from the HL pair and we only have the use of the
Subtract with Carry instruction.
ADD HL,BC ADC HL,BC
ADD HL,DE ADC HL,DE
ADD HL,HL ADC HL,HL
ADD HL,SP ADC HL,SP
ADD lX,BC ADD lY,BC
ADD lX,DE ADD IY,DE
ADD lX,lX ADD lY,lY
ADD lX,SP ADD |Y,SP

16 Bit subtraction.
SBC HL,BC
SBC HL,DE
SBC HL,HL
SBC HL,SP

Let us look at a few examples using some of these instructions.

LD HL,0432H
LD BC,0536H
ADD HL,BC

The above instructions would result in the HL pair containing


0432H+0536I—I=0968r-I.
The ADD HL,HL instruction has the same effect as multiplying by 2.
Combined with additional instructions it could be used to multiply a
number by a power of two. For example, suppose we wished to
multiply the contents in the DE pair by 32. First we transfer DE into HL,
then we do five ADD HL,HL instructions in order to multiply by 32, and
finally we transfer the answer back into DE like this:
;multiply DE pair by 32
34 Number crunching

EX DE,HL ;SWOP DEANDHL


ADD HL,HL ;TlMES BY2
ADD HL,HL ;TIMES BY4
ADD HL,HL ;TIMES BY8
ADD HL,HL ;TlMES BY16
ADD HL,HL ;TlMES BY 32
EX DE,HL ;SWOP DE AND HL
;ANSWER IS NOW IN DE

The first and last instructions EX DE,HL mean ‘exchange the DE and l-IL
registers’. What they actually do is simply to swop the contents of
the DE pair for the contents of the HL pair.
As we mentioned earlier, the Add with Carry instruction ADC takes
into account the state of the Carry flag. For example, if the Carry flag
were set and we used the instruction:

LD HL,0432H
LD BC,0536H
ADC HL,BC

the HL pair would contain 0432H+0536H=0968H~I-1 (state of


Carry)=0969H. It is worth repeating that the only form of subtraction
available with the 16 bit set is using the SBC instruction which also
subtracts the state of the Carry flag to give the final result.
Therefore, it is sometimes necessary to Clear or reset this Carry flag
before executing an SBC instruction in order to obtain the correct
result. The way to do this is very simple. We use the 1 byte
instruction:

AND A

This means ‘AND the Accumulator with itself’. This is known as a


logical operation, a process which we will be looking at more closely
in chapter 5. All you need to know for now is that one of the effects
fo this instruction is to reset the Carry flag. Thus in order to subtract
0432 hex from 0563 hex we could use the following piece of code:

LD HL,0536H ;Put firstnumberin HL


LD DE,0432H ;Put second numberin DE
AND A ;clear the Carry flag
SBC HL,DE ;do the subtraction!

This should leave the result 0536H—0432H—0 (state of Carry)=14 hex


Number crunching 35

If we had not used the AND A instruction as a precaution to clear the


Carry flag and if the Carry flag was set after the execution of a
previous instruction, the result would be 0536H—0432H-1 (state of
Carry)=103H.

Jumping and calling


In Spectrum BASIC we transfer control from one part of a program to
another using the BASIC instructions GOTO and COSUB. In order to
implement transfers in machine code we use the JUMP and CALL
instructions.
The simplest of these instructions is the JUMP to address
command:

C3 00 60 JP 6000H

The above example reads ‘JUMP to the address 6000 hex‘ and it loads
the program counter with 6000 hex from where it will continue to
execute the machine code.
We can also specify the address to JUMP to by the register pairs
HL,Ix and IY. For example, if we had the instruction:

JP (HL)

This would in effect load the program counter with the HL register
pair. So if the HL pair contained 1601 hex the program would JUMP to
the address 1601 hex.
In order to implement the equivalent of the BASIC statement ‘IF
condition THEN COTO’ we have to use something known as condi-
tional jump instructions. There are eight conditions which can be
identified, all of which are indicated by bits set in the flags register
(F-register). Below we give all the conditional jump statements that
are allowed:

JP NO,address ;‘Jump if Carry flag reset (Non Carry)‘


;to the address specified
JP C,address ;’jUMP if Carry flag set (Carry)’
JP NZ,address ;‘, UMP if Zero flag reset (non Zero)‘
JP Z,address ;‘JUMP if Zero flag set (Zero)‘
JP P,address ;‘_ UMP if positive (Sign flag reset)‘
JP M,address ;‘_IUMP if minus (Sign flag set)‘
JP PO,address ;’_’UMP if Parity odd (Parity reset)’
JP PE,address ;‘, UMP if Parity even (Parity set)‘
36 Number crunching

Jump relative
There is another range of JUMP instructions available on the Z80,
known as the JUMP relative command. This instruction allows us to
specify an offset instead of an absolute address. The offset is a one
byte number and allows us to jump backwards by up to 128 bytes
and forwards up to 127 bytes, counted from the first byte after the
instruction. This is because by using signed integer representation
(see chapter 1) a byte can hold values between +127 and -128. The
actual instruction is written as follows:

28 dd JR dd

JUMP relative dd bytes, where dd is the displacement to JUMP. For


example, in the case below:

18 03 JR 03
00 NOP
00 NOP
00 NOP
3E 04 LD A,4

the code would load the JUMP past the two NOP (No operation)
instructions to the instruction which LOADS the Accumulator with the
value 4. The displacement 02 is added to the location after the JUMP
instruction. Since the JUMP relative instruction is two bytes long the
actual address to which the program is transferred is the address of
the JUMP relative instruction plus the displacement plus 2:

new address=old address+displacement+2

If you are using a monitor to type in a machine code program you


will have to work out the displacement for yourself. However, most
Z80 assemblers will let you reference addresses as labels and will
automaticcally work out the displacement needed. So you could
write the code like this:

JR Here
NOP
NOP
Here LD A,4
When assembled the displacement would be placed with the appro-
priate value.
Like the absolute JUMP the relative JUMP also has conditional
Number crunching 37

options. However, these are limited to the testing of the carry and
the zero flags:

JR C,dd ;‘JUMP relative on Carry (Carry flag set)’


JR NC,dd ;‘JUMP relative non Carry (Carry flag reset)’
JR Z,dd ;’JUMP relative on Zero (Zero flag set)’
JR NZ,dd ;‘JUMP relative non Zero (Zero flag reset)‘

The advantage of using the JUMP relative instructions as opposed to


those of the JUMP absolute lies in relative addressing. This takes only
two bytes as compared to the three needed for the absolute mode,
making a routine smaller in size. It also allows some particular
routines to be relocateable, that is, having the ability to be placed
anywhere in memory without having to be re-assembled.

DJNZ
The DJNZ ‘oecrement JUMP on non zero’ is an extremely powerful
instruction. It allows the programmer to effect a loop a specified
number of times around a portion of code, very much like the
’eoR...Nexr’ statements in BASIC. Take a look at the following
machine code program:

LD B,20H
LD HL,5800H
LD A,2
LOOP LD (HL),A
INC HL
DJNZ LOOP
RET

The first instruction LD B,20H LOADS the B register with the number 20
hex (32 decimal). The B register is used as a loop counter for DJNZ.
We then LOAD the HL register with the two byte number 5800 hex.
This is the start of the attribute file:
LD HL,5800H

The Accumulator is LOADed with the value 2, the colour code for red
1NI<, black PAPER, BRIGHT 0 and FLASH 0. The next three instructions form
the main part of the loop:
LOOP LD (HL),A
INC HL
DJNZ LOOP
38 Number crunching

The value in the Accumulator is placed at the address pointed by the


HL pair. When executed the first time round, the loop will load the
value 2 into the start of the attribute file. Next we have the
instruction:

INC HL

This means ‘increment the HL register pair by one‘ and adds one to
the HL pair so that it points to the next address in the attribute file.
Finally we have:
DJNZ LOOP
RET

The DJNZ instruction will subtract one from the B register. If the value
after this subtraction is not zero then it will JUMP relative to the
address specified. If it is zero then it will go on to the next instruc-
tion which is a RETurn.
As you can see, DJNZ is an extremely powerful instruction. It is very
much like having two instructions in one — a subtraction on the B
register and a JUMP relative on non zero.
Bearing in mind that the DJNZ instruction uses relative and not
absolute addressing we can only use it if the portion of code we are
looping around is no longer than 128 bytes.

Calling and returning


The second method of transferring the control of a program is by
using the set of CALL instructions.
There are times when a program executes the same portion of
code many times or when other portions of code closely resembling
each other are run with different parameters. Instead of having
these similar routines scattered around at various different places in
memory, you could have just one copy of this code when necessary,
call it as a subroutine, very much like setting up a subroutine in BASIC
usingthe ‘COSUB’ BASIC instruction.
You can call this piece of code by using the instruction CALL fol-
lowed by an address. The flow of the program will transfer to this
address after storing the address of the instruction following the
CALL instruction. The program is then executed normally until it
reaches a RET (return) instruction, when it returns to the next instruc-
tion after the address of the call.
The CALL instruction takes this syntax:
CD LL HH CALL HHLL
-

Number crunching 39

HH is the high byte of the address and LL is the low byte. It is possible
for CALLS to be nested, which means that one subroutine may CALL
another subroutine. If fact the number of nested callS allowed is
limited only by the amount of memory left to the programmer. A
subroutine may also call itself, a function known as recursion which
is too abstruse for us to pursue here in any depth.
Like JUMP, the CALL and Rt-;Turn instructions also have conditional
counterparts. We can CALL a subroutine or RETUTI1 from a subroutine
depending on the conditions set in the Flags register:

CALL HHLL RET


CALL Z,HHLL RET Z
CALL NZ,HHLL RET NZ
CALL C,HHLL RET C
CALL NC,HHLL RET NC
CALL PO,HHLL RET PO
CALL PE,HHLL RET PE
CALL M,HHLL RET M
CALL P,HHLL RET P

There is another range of calling instructions, known as the restart


(RST) set. They differ from the others in that they are only one byte
long and are limited to CALLlF|g one of eight addresses: 00 hex, (D8
hex, ‘I0 hex, 18 hex, 20 hex, 28 hex, 30 hex and 38 hex.
As you have probably noticed, all these addresses are in the ROM
memory map which you may not find much use as we cannot write
any code there. Well that's true, but we can CALL some of the
routines from our own programs. Below are the CALLS and the object
of the particular routines.

RST 00H ;start boot up

This is a bit like typing NEW in BASIC, so is not very useful unless you
wish to return to BASIC from a machine code program and protect the
routine from prying eyes.

RST 08H ;error restart

This routine is used by BASIC to report error messages. The error


number is the byte following the restart instruction. It will give the
error report of the data plus one. Thus:

i
40 Number crunching

RST 08H
DB 08

will generate the error message 09 ’sTOP statement’.

RST 10H ;print a character

This is an exteremely useful routine. It prints the character in the


Accumulator to the current channel. A channel outputs to a ‘device’,
which can be either the printer or various parts of the screen. We'll
see more of this in Chapter 9. A simple example for now is:

LD A,66 ;print the character B to the


RST 10H ;current channel

RST 28H ;floating point calculator

The number crunching routine above allows us easily to implement


complex floating point arithmetic routines in machine code using
the ROM functions. The floating point calculator is explained in more
detail in Chapter 9.

RST 30H ;make space

This is not a particularly useful routine. It simply creates space in the


workspace area.
Finally:

RST 38H ;scan the keyboard

This routine updates the system variable LAST-K and can be used to
ascertain which keys are depressed. lt is called 50 times a second by
BASIC. It is also sometimes known as the Mode 1 maskable interrupt
routine. We'll be hearing more about this routine when we get to
Chapter 11, which deals with interrupts and their uses.
3 Rotating and shifting

Rotating and shifting operations provide the programmer with the


means to manipulate the pattern of bits held in a register or a byte
memory. These instructions, which are most useful for multipli-
cation and division by powers of two, act on most of the 8 bit
registers. They can use both indirect and index addressing modes.
All the rotate instructions use the Carry flag (which is held in the F
register) as a ninth bit, bit 8, therefore allowing the programmer to
rotate this from the left or right through the register or memory.
This should become clearer as we run through the available
instructions.

Rotating

RLC Rotate Left Circular


This instruction rotates each bit of a given register or memory byte
to the left by one bit. Bit 7 of the register or byte specified is rotated
to the Carry flag and the same value is ‘wrapped round’ to bit 0:

Carry flag ‘L ll -""~ J"‘r:"'*—*"' ‘*~-*’€—*"


in F register

For example, if the byte on which we were operating held 18101010


the following would occur after the RLC instruction was executed.
The value of bit 7 (1) would be transferred to the Carry flag bit and to
bit 0 of the byte with each of bits 8 to 6 shifted one place to the left.
The result would be 81818101 stored in the byte, and the Carry flag
set.
The RLC instruction can act on the registers A,B,C,D,E,H,L, as well as
(HL) and (IY+INDEX) and (IX+lNDEX). There is also a RLCA instruction
which has the same effect as RLC A but is one byte shorter and twice

.;_.__ m 7
42 Rotating and shifting

as fast to execute. These additional,short-form, rotate instructions


on the Accumulator are available on all the rotate instructions.
These are as follows (note that d indicates the index value where
applicable):

RLCA RLC (HL)


RLC A RLC (lX+d)
RLC B RLC (lY+d)
RLC C
RLC D
RLC E
RLC H
RLC L

RL Rotate left
This instruction rotates the register left through all the nine bits,
wrapping around the carry bit value to bit 0.
The effect of this instruction is to take the sequence of bits in the
byte, add the Carry flag value as bit 8, and then shift all bits one
place to the left. The Carry flag value then goes into bit .Thus if we
had (1)01010101 before an RL instruction, we would end up with
(0)18181011. This would produce a result which is the original value
multiplied by two, plus the value of the Carry flag.

LH,,,,7|.i5|.i.l2].|..yl
can-Y -;,,\_ /L _/\_Jl /we J-\~ J
flag

The available instructions are:

RLA RL (HL)
RL A RL (lX+d)
RL B RL (lY+d)
RL C
RLD
RLE
RLH
RLL
—-II

Rotating and shifting 43

RRC Rotate Right Circular


The register or byte is rotated right from bit 7 through to bit 6 and so
on. Bit 8 is then rotated to the Carry flag and bit 7. This is the reverse
operation to that of RLC

RRCA RRC (HL)


RRC A RRC (lX+d)
RRC B RRC (lY+d)
RRC C
RRC D
RRC E
RRC H
RRC L

RR Rotate Right
The Rotate Right instruction has the opposite effect to that of the RL
Rotate left instruction. Bit 0 of the register or byte is rotated to the
right through the Carry, while the old Carry is rotated down to bit 7.
_ - i -- _ . —

--___..-#7‘-i-___§'\___ _j_ _..i('--___..-I'--____.I"\-___-‘I

RRA RR (HL)
RR A RR (lX+d)
RR B RR (lY+d)
RR C
RR D
RR E
RR H
RR L
44 Rotating and shifting

Shifting
As well as the Rotate instructions, there is also available a set of shift
instructions which can make registers shift either left or right. This
differs from the Rotate instruction set in that there is no ’wrap
around’ effect. Therefore one bit at either end of the byte is lost and
a zero goes into this bit. Like the Rotate set all the shifts can act on
A,B,C,D,E,H,L,(HL)(lX+d) and (|Y+d).
SLA Shift Left Arithmetic
The content of the carry bit is lost and the whole byte or register
shifts to the left. Bit seven is shifted into the Carry flag, and a 8
inserted in bit 8.

SLA A SLA (HL)


SLA B SLA (lX+d)
SLA C Sl_A (lY+Cl)
SLA D
SLA E
SLA H
SLA L

SRL Shift Right Logically


The SRL ‘Shift Right Logically' shifts the bits from the left to the right,
so is useful for dividing numbers by powers of two. Bit zero of the
register/byte is shifted into the carry bit and a zero is placed into bit

llvelliwlflflflilslili
SRL A SRL (HL)
SRL B SRL (lX+d)
SRL C SRL (lY+d)
SRL D
SRL E
SRL H
SRL L
Rotating and shifting 45

SRA Shift Right.Arithmetic


This is an odd instruction. Shift Right Arithmetic is identical to the
SRL instruction apart from the fact that bit seven is left unchanged.
This instruction is used to divide ‘signed’ numbers (i.e. numbers
-127 to +128) by powers of two as it doesn't affect the sign bit.

fiiljlilililsliliri
S SRA (HL)
is
SRA C
03> SRA (lX+d)
SRA (lY+d)
SRAD
SRAE
SRAH
SRAL

RLD (HL) ROTATE LEFT DECIMAL


This is a single instruction which acts on both the accumulator and
the contents pointed to by the HL register pair. lt actually moves ‘half
bytes’ called ‘nybbIes' from the Accumulator to a RAM location and
vice versa.

Accumulator Byte defined by {H L)


[ IF

--I-7-I"---W-—

Bie-.l7'6J5|4l3|2l'l Ill), Bits \l A C $


J__.. _._ FY ts: .4

-1- I 0*i ->U.‘ ‘us -—-_ »<—-

As you can see from the diagram the bottom four bits (bits 3-0) of
the location pointed by the HL register pair are shifted to the top four
bits positions (7~4). The original top four bits are placed in the lower
half of the accumulator with the original contents placed in the
bottom four bits of the RAM location. If, for example, we had the HL
pair containing 6000 hex, this byte holding CB hex, and the accumu-
lator containing 2A:
46 Rotating and shifting

Address Contents Accumulator


6888 2A CB

Then after executing the instruction

RLD (HL)

We would find that the contents of location 6888H and the accumu-
lator would be Changed to:

Address Contents Accumulator


6000 AB C2

The instruction RRD (HL) has the opposite effect, as shown in the
diagram below:

Accumulator Byte defined by (HL)

ii" ll “Ll
65432 'ts l\.J ._t S
-iii. ‘*-—-W _iL

l ., l
As already indicated, the shift instructions are very useful for multi-
plying and dividing by powers of two. If, for example, the Accumula-
tor contained the value three and we had the instructions:

SLAA
SLAA

Then the result remaining in the Accumulator would be 12. Remem-


ber that the shift instructions affect the Carry flag, so if we had
executed the instructions:

LD A,128
SLA A

the bit pattern for 128 is 1088800. Therefore when the SLA A instruc-
tion is carried out, the top bit of the Accumulator would be shifted
into the Carry flag. Zero remains in the A register leaving the Carry
flag and Zero flag set. lt is easy to write small routines to multiply
Rotating and shifting 47

registers by numbers which are not multiples of two. For example to


multiply a number by 18 simply split the calculation into two parts.
First multiply the number by eight and then add twice the original
number.

MULT18

SLA A ;LET A=2*A


LD B,A ;LET B=A (2*original A)
Sl_A A ;LET A=2*A (4*original A)
SLA A ;LET A=2*A (8*original A)
ADD A,B ;LET A=A+B (10*original A)

The first two instructions:

SLA A
LD B,A

multiply the Accumulator by two and save the result in the B register.
Remember, the instruction

LD B,A

has no effect on the Accumulator but copies its contents into the B
register. Therefore at this point we have double the original number
in both the A and the B registers.

SLAA
SLAA

The two other shift instructions multiply the number by eight.


Finally, the last instruction:

ADD A,B

adds the contents of the B register, which contains twice our original
number, to the A register. This leaves the desired answer.
This method of multiplication would only work for numbers in the
range of 0 to 25. Any larger number would result in a number greater
than 255 which we are unable to fit into an eight bit byte. To perform
multiplication on two byte numbers, using shifts, we have to take
into account that a Carry may occur from the lower half of a register.
This must be shifted to the high part. Therefore to multiply the HL
register pair by two we use the instructions:
48 Rotating and shifting

SLA L ;multiply lower part by two


RL H ;rotate putting carry into bit
;0 in high register.

Ifwe wanted to multiply the HL register pair by ten we could write:

SLA L 1
RL H ;2*HL
LD E,L
LD D,H ;Savein DE.ie DE=2*HL
SLA L
RL H ;4*HL
SLA L
RL H ;8*HL
ADD HL,DE ;HL=8*HL+2*HL=10*HL

Of course it would be much easier to use the aoo instruction to


perform the multiplication.

ADD HL,HL ;2*HL


LD E,L
LD D,H ;DE=2*HL
ADD HL,HL ;4*HL
ADD HL,HL ;8*HL
ADD HL,DE ;18*HL

This piece of machine code is much faster and more concise to use
than the previous example. However, this is not always the case.
Suppose we wanted to multiply the Ht pair by 128. The first thing that
you thought of was probably to use the series of ADD instructions.

ADD HL,HL ;2*HL


ADD HL,HL ;4*HL
ADD HL,HL ;8*HL
ADD HL,HL ;16*HL
ADD HL,HL ;32*HL
ADD HL,HL ;64*HL
ADD HL,HL ;128*HL

A lot of instructions!
lf we take a look at the bit pattern of a two byte number when we
multiply be 128 we might be able to use shift and rotate instructions
to our advantage. Let's look at the bit pattern we must get in order to
multiply a two byte number by 128:
Rotating and shifting 49

I I raiiig,
High Register Low Register, L

I315 b14lb13lb12lb11lb1Gl bg | bt| b7l b6 lbs | b. | b3 lbzl b


“""“C\’ ;““""“‘y’""“""'
The top seven bits of the low byte need to be shifted into the bottom
seven bits of the high byte. Bit 8 of the low byte will be shifted up to
bit seven and bit seven of the high byte is lost.
If we represent the bit patterns by having hn representing bit n of
the high byte and In to represent bit n of the low byte then before
we perform the multiplication we have the pattern:

h7 h6 h5 h4 h3 h2 h1 h0 highbyte
I7 I6 I5 I4 I3 I2 I1 I0 lowbyte

After multiplying a two byte number by 128 we end up with the bit
pattern:

h0 I7 I6 I5 I4 I3 I2 I1 highbyte
I0 0 8 8 0 0 0 0 lowbyte

Notice that the first seven bits of the low byte will always be set to
zero. Looking at the pattern we can see that we can get the new high
byte pattern by shifting the old low byte to the left one. Before we
do this we can put h0 into the Carry flag using the instruction:

SRL H

Now we have bit 0 of the H register i.e. h0 in the Carry flag. We can
now get the pattern we need for our new high byte in the low byte L
register by using the instruction.

RRL

This puts the Carry (containing the old value h0) into bit seven of the
low byte. All the other bits are shifted to the right forcing the carry
into the topmost bit. We now have the pattern we want for the H
50 Rotating and shifting

register in the L register, so we transfer this by a simple LOAD


command:

LD H,L

Finally, we set bit seven of the low byte to the contents of the Carry
which is the bit I0. We do this by first setting the L register to zero
and then rotating the Carry through to bit seven:

LD L,8
RR L

So our code for multiplying the HL register pair by 128 looks like this:

MULT128: SRL H
RR L
LD H,L
LD L,8
RR L

The code is much smaller and faster to use than the series of ADD
instructions. This portion of code is as much as 58% faster than the
equivalent shown earlier. Arithmetic using bit manipulation is a little
difficult to grasp at first but its implications are enormous. Screen
addresses, for example, can be calculated much faster, giving games
of infinite quality. Therefore it's very worthwhile to take some time
to learn. Meanwhile, I'll end the chapter by giving you a routine to
divide the HL register pair by 128 and let you find out how it works.

Dl\/128: SLA L
RL H
LD L,H
LD H,8
RL H
4 Making comparisons
and checking bits
The Compare Instruction
A COMPARE instruction operates in a similar fashion to a subtraction
operation, except that the Accumulator is not changed. Instead,
various flags are set or reset according to the result.
This instruction is most useful when used in conjunction with the
Z88’s conditional CALL and JUMP instructions and can be used to
implement machine code equivalents of such BASlC statements as:

IF X>-N THEN GOTO ADDR


IF X<N THEN GOTO ADDR
IF X: THEN GOTO ADDR
IF X-<‘.>-8 THEN GOTO ADDR

The COMPARE instruction is limited to Comparisons between eight bit


numbers specified directly, indirectly, or Contained in registers.
Suppose we wanted to COMPARE the current value held in the Accu-
mulator with the number 128 decimal.
We would use the instruction:

CP 128

which reads ‘ComPare the current Accumulator value with the


number 128'. This will set the Zero flag if the number in the Accumu-
lator is equal to 128. The Carry flag will be set and the Zero flag reset
if the number is greater than 128. Both the Carry flag and Zero flag
would be reset if it was less than 128.
The following routine is a good example of the use of the COMPARE
instruction with conditional branches to simulate the BASIC language
IF . . .THEN . . . ELSE structure. The routine compares the A register with
the B register and branches off to certain addresses, depending on
whether the A and B registers are found to be equal, greater than, or
less than A.
52 Making comparisons and checking bits

CP B
JR Z,EQUAL
JR C,BGREAT
LESSA:

The first instruction 'ComPare the B register with the A register’ sub-
tracts the B register from the A register. The actual result is not
updated to the accumulator and only affects the flags.
If the A register was equal to the B register then the Zero flag
would be set, causing the program to jump to the address labelled
EQUAL. If the they were not equal, then the program would carry on
to the next instruction:

JR C,BGREAT

If the Carry flag was set this would indicate that the B register was
greater than the Accumulator, causing a branch to the label BGREAT. If
no branch occurred this would mean that the B register was less than
the A register, causing the program to arrive at the label LESSA.

CP n CP (HL)
CP A CP (IX+dd)
CP B CP (lY+dd)
CP C
CP D
CP E
CP H
CP L

Set Bit and Reset


There are other bit instructions in the Z80 set which allow us to set,
reset or test individual bits in a byte.
The $ETinstruction
The ‘sat’ instruction allows us to sEr a particular bit in a byte. We can
test individual bits in a register or a RAM location. The format of the
set instruction can be any of the following forms:
Making comparisons and checking bits 53

SET n,r
SET n,(HL)
SET n lX+dd)
SET n lY+dd)
1-.we .- '\./'- t.

where n is the bit number we wish to test 0-7 and dd is an offset in


the range -127 to 128

For example, the instruction:

SET 4,A

would set bit 4 of the Accumulator.


We can also use the indexing addressing mode to set and reset
bits. If, for example, thew register pointed to the address 6000H and
the contents of its adjacent memory locations were as below:

Address Contents
60001-I 22H
6882H 88H
6802H 88H

Then the instruction scr 4, in/+2) would have the following effect:

address contents
6888H 22H
6881 H 88H
6882H 13H

The contents of location 6802 hex are Changed to 18 hex=24 decimal


The RES instruction
This has the opposite effect to the SET instruction; it REsets a bit in a
byte or RAM location.
The Bflinstruction
The bit instruction allows us to test for individual bits of a register or
byte. The results of the test are signified by resetting or setting the
Zero flag. If the bit tested was zero then the Zero flag would be set
and, if not, the Zero flag would be reset.

BIT 7,A

The above instruction would read ‘test BIT 7 of the A register’.


Therefore, if the A register contained 128, which is 10808888 binary,
** T

54 Making comparisons and checking bits

then the instruction would reset the Zero flag as bit seven is set to 1
If, however, we used the instruction:

BIT 0,A

with the same contents in the accumulator the Zero flag would be
set, as bit 8 is zero.
The BIT instruction is very useful because it does not corrupt
anything we are testing. Similar to the COMPARE instructions, It affects
the bits in the flag registers only.

Spectrum lNs and OUTs


The Z88 Chip needs to interface to other devices such as the
keyboard and a cassette recorder so that the user can communicate
with the computer. There are two methods what we can use to
communicate to these devices. One is known as memory mapprng
that is PEEI<ing or Poxting, the other is by PORT addressing. A PORT Is a
gateway to these devices which can be read by using the instruction
'IN' or written to by using ‘OUT’. There are 256 of these PORTS on the
Sinclair computer. Most can be used by electronics buffs, to lInk up
to devices such as speech synthesisers and sound chips.
There are two instructions in BASIC, ‘IN’ and ‘OUT’ which allow us to
gain access to these ports. Frequently, these instructions are used to
scan the keyboard or output to the speaker to produce noises
The keyboard is divided into 8 rows of_5 keys each and the actual
syntax of Spectrum BASIC to read the keyboard uses a two byte
number. For example:

LET X=lN 61438

scans the keys 0 to 6 on the top row of the keyboard. The other
addresses and the keys they scan are given below:

ADDRESS HEX KEYS SCANNED


32766 7FFE SPACE,SYMBOL SHlFT,M,N,B
49158 BFFE ENTER,L,K,],H
57342 DFFE P,O,l,U,Y
61438 EFFE 8,9,8,7,6
63486 F7FE 1,2,3,4,5
64518 FBFE Q,W,E,R,T
65822 FDFE A,S,D,F,G
65278 FEFE CAPS SHIFT,Z,X,C,V
Making comparisons and checking bits 55
.-

So if we wanted to scan for the bottom row of keys from SPACE to the
letter B we would use the BASIC instruction:

LET X= I N 32766

A value is returned in the variable X depending on which keys are


pressed. There are five bits which represent the state of each row on
the keyboard. If a particular bit is low (i.e. 8) then this means that a
key is depressed, and if no keys were depressed then all bits would
be high. In the table above the key values have been given in bit
order, so if we were scanning the keys 1 to 5 then bit 8 would
indicate the state of the key1 ,bit1 the state of key 2 and so on.
The other 3 bits returned when scanning the keyboard are not
used and are unpredictable (mainly because of the different models
of spectrums available) so it is wise not to compare the values read
unless you mask out the first five bits. Masking means removing bits
according to a pattern. To mask the top three bits you would have to
do RES 7, r RES 6, r and RES 5, r to set them all to zero.
The IN instruction
In machine code to read a PORT we use the instruction:

IN A,(port)

The value port is the PORT address which is a one byte number in the
range 8-255. This port is read and the value is returned in the
Accumulator. How do we use this instruction to scan the various
lines on the keyboard? Well, if you look closely at the address which
you scan in BAsIC to read a particular row you will notice that the low
bytes of each address are all FE hex,254 decimal. The port address
and the high bytes all differ from each other.
To read a set of keys in machine code we first LOAD the Accumula-
tor with the high byte of the line we wish to read and then execute
the instruction:

IN A,(8FEH)

So for example, if we wanted to scan the keys 8 to 6, we would write


the following code:

LD A,8EFH ;SELECT LINE8—6


IN A,(8FEH) ,:READ PORT

Now, if we wanted to test if the key 8 was pressed we could use the
BIT instruction:

T A
56 Making comparisons and checking bits

BIT 8,A ;Test for"8”

This would set the Zero flag if the key was pressed or reset the flag if
it was not pressed.
It is an easy matter to read a set of keys by using the compare
instruction:

LD A,8FBH ;seIect keys Q to T


IN A,(0FEH) ;read key board port
AND 31 ;mask off lower 5 bits

This portion of code sets the Zero flag if all the keys Q,W and E are
pressed.
There is another form of the IN instruction which allows us to
specify the port by the value in the C register. The registerin which
the value is read can also be chosen from the set A,B,C,D,E,H or L.
Thecode:

LD C,8FEH
LD A,8FBH
IN E,(C)

reads the line Q to Tand places the value read in the E register.
The OUTinstruction
The ‘OUT’ instruction is often used to generate sound and output to
the cassette system. The port which controls the small pisa speaker
is at the address 0FEh,254 decimal. This also has the ability to change
the screen border colour. The values of output to this port is in the
format shown below:

Speaker Border

I -—---—-
\l @ U1 -lb U-J l\-‘J S

_._..-_._...__,‘it + C W? -T
T
Unused Microphone

PORT 254

The first three bits (bits 8-2) of the byte are used for the border
colour. Bit 3 is used to control the EAR and MIC sockets so that data
Making comparisons and checking bits 57

can be sent and read to and from a cassette unit. Bit 4 is used to
pulse the (so-called!) speaker in the Spectrum.
Sound generation on the Spectrum is a simple matter of pulsing
bit 4 of port 254 high and then low for a short period of time. We
would set bit 4 (i.e. to 1) and hold it high for a short time and then
set it low (0) and hold it at this level for the same period of time. The
delay we have between ‘flipping’ bit 4 of the port determines the
frequency or note we get from the speaker. A long delay produces a
low frequency and a short delay a high frequency. To output the
value in the Accumulator to a port we use the mnemonic:

OUT (addr),A

This simply reads ‘Output the value in the Accumulator to the port
add ress’ So to turn the speaker on we would use the instructions:

LD A,'l6
OUT (8FEH),A

Notice how we first LOAD the Accumulator with 16. All this does is to
set bit 4 high, which when sent to the port turns the speaker on. The
following program demonstrates how the OUT instruction can work
to generate sound. Both the assembler mnemonic listing and a BAsIC
listing have been given, with which the machine Code can be
loaded. Line 20 of the BAsIC program changes the low bytes of the
values for the duration and the frequency.
Assembler Listing

ORG 28880
JP NOISE IJUHP TO MAKE A NOISE
SOUND:
LD A,1OH IHASK SPEAKER
ISO BIT 4 IS HIGH
OUT (BFEH),A :TURN ON SPEAKER
CALL DELAY :AND KEEP HIGH
;FOR A SHORT HHILE
XOR A ITURN BIT 4 OFF
OUT (OFEH)IA ;TURN SPEAKER OFF
CALL DELAY ;AND KEEP‘ IT OFF
;FOR A SHORT HHILE
RET
58 Making comparisons and checking bits

DELAY:
LD H,D ;TRANFER DE TO
3BC REGISTER PAIR
LD C,E ;IE.PLACE DELAY IN
IBC REGISTER

LOOP:
DEC BC :DECRENENT BC REGISTER PAIR
LD A,B ;AND REPEAT
OR C
JR NZILDOP :UNTIL BC PAIR IS ZERO
RET IRETURN AFTER FINISHING
FDELAY

DELA EOU IOO FDELAY


DURAT ERU 188 ;DURATION

NOISE:
LD DE,DELA ;GET DELAY
LD HLIDURAT FGET DURATION
BUZZ: CALL SOUND :HAKE A SOUND USING
;DELAY AND DURATION
DEC DE :5UBTRACT ONE OFF DELAY
DEC HL ISUBTRACT ONE OFF DURATION
LD A,L
OR H
JR NZ,BUZZ :REPEAT SOUND UNTIL
;DURATION IS ZERO.
RET

END

BASIC Program Listing

ID FDR fi=1 TD IBB


26 PDKE 2B@29,H: PDHE 2B@2b,fi
38 FDR X=1 TD QB
4B RANDDHIZE USR ZBBBB
SB NEXT X
66 NEXT A
5 Operating logically

There are three logical operations available in the Z88 instruction


set: AND, OR and xoR. These are all 8 bit operations which are best
explained by looking at a series of diagrams and what are known as
‘Truth Tables’. As explained in Chapter One numbers are repre-
sented in the computer by a series of 8's and 1's called bits and the
Z88 groups 8 of these bits together to form a byte. Logical opera-
tions are performed on all 8 bits of a byte, and transform their values
as described below.

AND Operations
The AND function operates on the corresponding bits of two bytes. If
both corresponding bits were 1, then our result (another byte) after
’ANDlrIg’ these two bytes would set that bit to 1. If either or both of
the bits were zero then the resulting bit would be zero. Look at the
simple Circuit diagram below:

Light l3ulb@
—I

Power -'~—-
SUPPIY —

I/.. .C._Switch A swirgh B


(open.=0) (closed,=l)

This diagram has two switches, labeled A and B, a power supply and a
light bulb. If we take the state of a closed switch as representing1
and the open state as ,then in order to switch the light on we have
to have both switches on, i.e. then are both set to 1. We can
represent the possible combination of the switches and their effec-
tive result on the light bulb by a truth table. The final result is 1 if the
light bulb lights and 0 if it doesn't.
60 Operating logically

AND TRUTH TABLE


A B A AND B

._I. _I.@@ _t5_.t@ -5333

As you can see Switch A and switch B have to be closed to make the
light bulb light up.
When we do a logical operation in machine code all the opera-
tions act on the Accumulator. The AND operator is useful for picking
up bits which we want to examine. This is known as ‘masking’. If we
had the code:

LD A,81881818B
AND 888881113

Since the data is in binary we require the ‘B’ suffix after the numeric
value. The second operation is the AND function. It takes each bit of
the data and AND’s it with the corresponding bit in the accumulator:

81881 818
AND 88888111
iii

88000010=2 decimal

AND instruction set

AND (HL)
AND (IX+dd)
AND (lY+dd)

> > >?>/./ /.£ZL’/ U U CJU CJ I—I 'nQ(1UJ>3

OR Operations
The OR function is analagous to the circuit diagram below:
Operating logically 61

—.l_-
Switch A

Switch B

As you can see either one of the switches can be on to set the light
on. Now looking at the possible combinations of switching in this
circuit we get the following truth table:

OR TRUTH TABLE
A B AORB

Aiifi ~—\S- ‘IS _.I _:r._I.@

The OR operator is useful to set a series of bits in the Accumulator

LD A,18181181B
OR 111888888

The above code would set the top three bits in the Accumulator.

18181181
OR 11188888

11181181 =237 decimal


62 Operating logically

OR instruction set

OR n OR (HL)
OR A OR '(IX+ddl
OR B OR (lY+dCll
OR C
OR D
OR E
OR H
OR L

XOR Operations
The xOR ‘exclusive OR’ operator is a little more difficult to explain
with the aid of a circuit diagram but is just as easy to understand. It is
similar to the OR operator but either, not both bits, may be high to
give a high output
xon TRUTH TABLE

A B A XOR B

_\_:@g —‘~S-AS S-‘-—iS

The xOR operator is used to complement bits in the Accumulator and


is sometimes known as toggling. What was previously on would be
turned off, and what was off would be turned on. This instruction
would be ideal for turning lights on and off connected to a com-
puter. lf, for example, we had the location at the address labelled
LICI-IT linked to some hardware which turned on a light if it contained
1 and turned the light off if it contained a zero, then the following
program would generate a flashing strobe:

LD B,0 ;set delay


LD A,1 ;set state of switch
TOG: XOR 1 ;toggle switch
LD (LIGHT),A ;turn light on or off
DELAY: DJNZ DELAY ;short delay
IR TOG

The B register is loaded with zero which is used as a counter in a


delay loop to hold the light on or off for a short period of time.
Operating logically 63

Because the DJNZ instruction will decrement B before testing it,


giving B a start value of 8 causes 256 loops round the DJNZ.

LD A,1

The Accumulator is then set to 1 and toggled, leaving zero in the


Accumulator since 1 xOR1=8

TOG: XOR 1
LD (LlGHT),A

The LOAD instruction turns the light on or off according to the result
in A, so first time round this would turn the light off. We now leave
the light in this state for a period of time using a DJNZ instruction
which counts from zero to 255 then back to zero again:

DELAY: DJINZ DELAY


We now come to the last instruction which transfers program con-
trol back to the address Too:

IR TOG

This time, with A register containing zero the exclusive OR function


will set the A register to one, producing a strobing effect.
XOR instruction set

XOR n XOR (HL)


XOR A XOR (lX+dcl)
XOR B XOR (lY+dd)
XOR C
XOR D
XOR E
XOR H
XOR L
-- L

6 Block manipulation

Block instructions give the Z88 the ability to move or compare


blocks of data automatically or semi-automatically. A feature not
found on any other 8 bit microprocessor on the market today.
A common use of block move instructions is to reduce screen
flicker in games. A technique I will show you later. First, let us look
at the block compare instructions. There are four instruction con-
cerned with searching for a particular value (‘key’) in a block of data.
To search for this key we can use any one of the following
instructions:

CPIR
CPDR
CPI
CPD

CPIR
The A register is LOADed with the value which we are searching for
(the 'key’). The HL register pair is LoADed with the address of the start
of the block we wish to search, and the BC register pair is set up to
contain the number of bytes we want to search through. The CPIR
instruction is used to automatically go through all the data, com-
paring the contents at each address until it either finds the key it is
searching for or until it has exhausted the search. This is signified by
the BC register containing 8.
If the key is found then the Zero flag is set and the HL register pair
points to the next address after the key. So the CPIR can be thought
of as three instructions INC HL, CP (I-IL) and DEC BC.
Take a look at the following example:
Block manipulation 65

' STRING: DEFM "ABCDEFGH"


SEARCHFORWD: LD HL,STRING
LD BC,8
LD A,"G”
CPIR
JR ZTOUND
NOTFOUND: .

FOUND: DEC HL

The first line contains the assembler psuedo operator DEFM ’DEFine
Message‘ which tells the assembler to place the string “ABCDEFGH" in
memory when the program is being assembled. As you can see the
HL is LOADed with the start of the string and BC the number of bytes
we wish to search through. The Accumulator contains the key “C”,
which we want to seek. The CPIR instruction will find this key (as it is
contained within the string) and cause the program to jump to the
address at the label FOUND. At this point we subtract the HL register
by one to point to the actual address where the key is.
CPDR
The CPDR instruction is similar to the CPIR instruction but the HL regis-
ter pair points to the end of the block of data and the search is made
backwards. This time when a key is found the Zero flag is set as
before, but the HL register pair will point to one less than the address
where the key was found.

STRING: DEFM ”ABCDEFGH”


SEARCH BACK: LD HL,STRING+8
LD BC,8
LD A,”G”
CPIR
JR Z,FOUND
NOTFOUND: .

FOUND: INC HL

As you can see, our Code for searching for a key is similar to the last
subroutine SEARCHFORWD. However we start off with LoAoing the HL
register pair with the address of the end of the string:

LD HL,STRING+8
66 Block manipulation

This kind of instruction is allowed on most assemblers and all it does


is to add the offset (+8) to the address of the label to get the
resultant address. When the key is found it arrives at the label
FOUND. However, this time the HL register pair will point to the
character “F” so to correct this we amend the HL register pair with
instruction:

FOUND: INC HL

CPIand CPD
These are known as semi-automatic instructions. If we use a CPI
instruction then it will compare the A register with the contents of
the HL register. The HL register pair will be incremented and the
contents of the BC pair will be decremented. Flags will be set accord-
ing to the result of the comparison and the subtraction of the BC
pair. The two most significant flags to test are the Po flag (Parity Odd)
and the Zero flag. If the key is found then the Zero flag is set. On the
other hand if the search is exhausted and the key is not found then
the P/V flag is set. These instructions are useful when we are search-
ing through non-continuous data. For example, if we wanted to
search though a string and the data we are seeking occurs every
three bytes of the string, then we could use the following code:
LD HL,STRING ;SET OF START OF STRING
LD BC,LENGTH ;SET LENGTH
LD A,KEY ;KEY TO SEARCH FOR
LOOK: CPI ;COMPARE (HL) WITH A REG
;DECREMENT BC
;AND INCREMENT HL
JP Z,FOUND ;FOUND KEY
IP PO,NOTFOUND ;EXHAUSTED SEARCH,NOT FOUND
INC HL ;SKlP PASS
INC HL ;UNWANTED DATA
JR LOOK ;KEEP SEARCHING

The routine will exit to the memory address specified by the label
FOUND if the key is in the string or to that given by label NOTFOUND if
the key is not in the string. Notice that there are only two INC I—IL
instructions, not three. This is because the CPI instruction has
already incremented the HL pair.

Block transfer
The Z88 is unique amongst 8 bit microprocessor Chips in possessing
a set of block transfer instructions. These allow blocks of data to be
Block manipulation 67

moved around within memory utilising just four instructions. The HL


register is LOADed with a 16 bit address which points to the start of
the block to be moved. The BC register contains the numbers of
bytes in that block which we wish to move. The DE register contains
the destination address where the first byte of data is to be stored.
After setting up these registers we could use any one of four block
move instructions. Like the Block Compare set of instructions the
Block Transfer possibilities allow for two automatic and two semi-
automatic instructions. The two instructions LDIR (LoaD Increment
and Repeat) and LDDR (LoaD Decrement and Repeat) are the two
automatic block instructions. They allow us to move whole blocks of
memory simply by executing the instruction once.
LDIR
The LDIR instruction is used to move data which is held in a contin u-
ous sequence of memory locations. The HL registers are set up to
point to the start of the data block, the DE pair is set up to point to
the start of the destination and the BC register the number of bytes
to move. When executing the LDIR instruction the contents of the
location pointed by the HL pair is Copied to the location pointed to
by the DE pair. Both the HL and the DE register pairs are incremented
to point to the new data and destination locations while the BC regis-
ter pair is decremented. This transfer continues until the BC register
pair reaches zero, then the Z88 goes onto the next instruction.
I -I—HL
P l

I
| _._

DE—I-_

Block move instruction LDIR instruction


LDDR
The LDDR instruction is similar to the LDIR but the HL register pair and
ll-'-‘H:-‘.*“'

68 Block manipulation

DE register pair point to the end of the block and destination


addresses. The transfers are made as with the LDIR instruction but
the HL and DE pairs are decremented to point to the new data and
destination addresses. Again the BC is decremented and the transfer
continues until the BC register has reached zero.
|"' _I

I

1 T
-II

<4
"' 14‘. ,

bb—-.' TH.
I
I I‘
L
. ‘ T j

,_.___I__
i_V -1 I

- _-- A-l—HL
LDDR instructIon
Most games programmers use the block move instructions to move
vast amounts of data to the screen. When a lot of information is
needed to be drawn to the screen this can result in the TV display
flickering. To reduce this flicker it is possible to draw the data on a
dummy screen unseen by the player. This dummy screen can then
be moved to the actual screen using the block move instruction.
If you imagine that we have set up a screen full of data at the
address C888 hex and we wish to move it to the screen which is at
the address 16384 or 4888 hex. We might use the following code:

;set up dummy screen

LD HL,C088H ;HL points to dummy screen


LD DE,4888H ,-DE points to real screen
LD BC,1B08H ;BC contains number of bytes
LDIR ;move it!

The HL register points to the start of the dummy screen which is C880
hex and the DE is set up to point to the start of screen. The BC register
is set up to contain 1B88 hex or 6912 decimal, the number of bytes
Block manipulation 69

contained in the display file. When we execute the LDIR instruction it


moves 6912 bytes starting from the location C888 hex to the screen,
reducing screen flicker to a minimum.
The two semi-automatic instructions LDI (LoaD and Increment) and
LDD (LoaD and Decrement) are used similarly to the CPI and CPD
instructions when the data is non-continuous or we wish to stop
moving data on certain conditions.
The parity odd flag is affected by the two instructions indicating that
BC has reached zero when the PARITY ODD flag is set. If we wanted to
write a routine which would move a block of data to the screen from
C888 hex. until we reach a zero byte, then the following code could
be used:

LD HL,C888H ;point to start address


LD DE,4888H ;point to destination address
LD BC,1B88H ;maximum number of bytes to move
MOVE: LDI ;move one byte (HL)-—>(DE)
;DE=DE+1:HL=HL+1:BC=BC—1
RET PO ;PARITY ODD FLAG set, all done
LD A,(H L) ; get next contents
AND A ;test for zero
IR NZ,MOVE
RET ;retu rn we have reached a zero!

The routine will move at least one byte as the test for a zero byte is
made after the LDI instruction. The transfer is complete if the PARIW
ODD flag is set, indicating that we did not encounter a zero byte in
the dummy screen and the BC register reached zero. It will exit when
we reach the first zero byte. The AND A is used here to test for zero. A
more obvious method would be CP8(COmPE1I'e with zero) but AND A is
more efficient as it is faster to execute and uses less memory space.
The AND A will leave the contents of A unchanged since any bit that is
AND’ed with itself will remain unchanged (see the Truth Table for AND
in chapter 5). The AND instruction will set the flags according to the
eventual contents of A so this is an easy way of setting flags. OR A
would be equally suitable for this purpose but xORA would clear the
A register to zero.

Miscellaneous instructions
The next (and last) batch of five instructions that will be explained in
this book all operate on the Accumulator or flag register, so they
have been grouped

------~ I.-----I---I
we

70 Block manipulation

CPL complement accumulator


The Complement instruction simply replaces 8's for 1's and vice
versa.
For example:

LD A,187 (18111811 binary)


CPL
The A register will contain 68 (01088180 binary) after executing the
Complement instruction.
NEG Negate accumulator
The Negate instruction has the effect of multiplying the number by
-1. It changes the number's sign (not just the sign bit!)
For example:

24 hex (36 decimal) becomes DC hex (-36 decimal)

This instruction performs the ’two’s complement’ on the contents of


the Accumulator. It is directly equivalent to the pair of instructions:

CPL
INC A

CCF Complement Carry Flag


This changes the Carry flag to a1 if it was a 0 and vice versa.
SCF Set Carry Flag
This instruction forces the Carry flag to a 1.
DAA Decimal Adjust Accumulator
This instruction is used to add numbers which are represented in
Binary Coded Decimal (BCD) form. The decimal numbers 8 to 99 can
be represented in one byte by splitting it into two sets of4 bits each,
called nybbles. The left nybble is the number of tens in the number
and the right nybble represents the number of units. For example,
the number 29 can be represented by the BCD number 88181801 (the
8 bit binary number has been split into two nybbles to make it easier
to read.)
When we want to add or subtract two BCD numbers we use the
normal ADD or SUB instructions followed by the DAA instruction. The H
and N flags are used by the DAA to adjust the result to BCD.
For example:
Block manipulation 71

LD A,29H ;LOAD A with 29 hex 41 decimal 29 BCD


LD B,24H ;LOAD B with 24 hex 36 decimal 24 BCD
ADD A,B ;ADD B register to A register
DAA ;decimal adjust

This piece of code would leave the result 53 hex in the A register (not
4D hex as with normal addition).
The way that DAA works is that after an arithmetic operation it
checks whether the low nybble is in the range 0 to 9. Ifthis is not the
case, it will add 6 to the low nybble, which causes the high nybble to
be incremented. Then the high nybble is checked. If it exceeds 9
then 6 is added to the high nybble, which will overflow into the
Carry flag.
In the example the Accumulator will hold the value 4DH before
DAA is executed.
Here is the flow of logic for DAA in this case:

(a) Low nybble=DH


(lo) This is greater than 9 so add 6 to the low nybble to give temp.
result of13I-I.
(C) replace the low nybble of temp. result to leave 10H or the high
nybble equal to 1.
(d) Add the high nybble of the temp. result to the high nybble of the
accumulatorto give:

4+1 =5

(e) 5 is less than 9 so replace high nybble in accumulator.


(f) The Accumulator now contains 53H,this is the correct BCD result of
29+24
7 A Spectrum monitor

This chapter presents a program which will allow you to write, run
and debug machine code programs. It can be entered into your
Spectrum using the BAsIC machine code loader given as Listing 1
below. After keying in and sAvEing the BAsIC program on tape, begin
the program by entering the start address at which the machine
code program will start to be built up. Then INPUT the hexadecimal
data which makes up the program as given in the hexadecimal listing
(Listing 2). If at any time you wish to correct a mistake there are edit
facilities to help you (see below). Typing ss when prompted for a
hexadecimal byte allows you to change the address at which the
next piece of data is to be placed. To quit the program, type in a
double hash ## when prompted for hexadecimal data. After this has
been done the program allows you to store the machine code using
the SAVE command.
For anyone interested in the way in which the monitor was written
the corresponding assembly mnemonic listing has been included in
Appendix 3. At the moment don’t worry about understanding how it
works, just type in the data. Onceit is up and working you can use it
to enter the other machine code programs which are given. In this
book each functional program, other than illustrative examples, has
two listings. One is in mnemonic form which is easier to read and
follow. This can be used by those of you that have full assembler
programs available. The second listing is the hexadecimal equiva-
lent. This is the portion of memory of your Spectrum which holds
the program. It is displayed as a hexadecimal dump and can be
reproduced by keying in the appropriate value for each memory
location using the hex monitor. You could, of course, use the BASIC
monitor to input the machine code listings. However, as you will see
this is not as powerful as its machine code counterpart.
The monitor program has been assembled at the address 25500.
This allows us to write machine code programs higher up in mem-
ory, giving more free space in which to RUN both BAsIC and machine
programs. The monitor offers the machine code programmer eleven
functions. These are: Dump, Edit, Fill, Goto, Hunt, Identify, Load,
Move, Print, Register and Save.
A Spectrum monitor 73

More commands can easily be added by changing a command


table to point to the routine which deals with the new command.
After the monitor has been typed in usin_g the BASIC loader the
machine code can be sAvEd by typing:

SAVE "SMON” CODE 25588, 1588.

The Spectrum is then cleared by switching the machine off and on


again. Next the monitor can be loaded by typing in:

CLEAR 24999:LOAD ’”’ CODE: RAN DOMIZE USR 25588.

The monitor should then welcome you with a ’>' prompt, inviting
the input of one of the eleven commands.
Daddress (Hexadecimal dump)
Type in ‘D’ followed by a two byte hexadecimal number. The moni-
tor then displays the contents of memory from the given address in
a hexadecimal format. The routine will keep dumping the memory
contents until a key is input other than a carriage return. For
example:

>D 8188

The above command will display 64 bytes of memory from the


address 8108 hex.
Eaddress (Edit)
This allows you to edit or modify a byte in memory. To execute the
command, type in ‘IE’ followed by a two byte address which you wish
to start modifying. The monitor will then show the address which is
being modified and the contents of that address. Then type in a one
byte hexadecimal number to change that location. After the modifi-
cation has been given the monitor will automatically go onto the
next location to be edited. The routine can be exited by typing in a
non-valid hexadecimal digit. eg:

>E C080
C080 FF 3E
C801 00 2A
C002 80 C9
C083 88 <ENTER>

Pressing <ENTER:> will exit from the edit command.


Ir l|_HLI'II

74 A Spectrum monitor

F start address end addres byte (FILL memory with byte value)
To FILL a block of memory with a given byte, given the start address,
end address and byte value to where the byte is to be filled. For
example:

>F 4888 5888 2A

This will fill the memory from 4000 hex to 5880 hex with the byte 2A
hex.
G address or G address, breakpoint address (GOTO address)
This command allows execution of a portion of code from a given
address. A second parameter can be given which allows you to give
a break point where the register values will be displayed.
To give a breakpoint type in a ’,’ after the first address and then
type in the breakpoint address.

>6 C800
The above example will cause the monitor to execute from address
C888 and will RETURN back to the monitor after a RET instruction is
met.

>G C888 ,C884

This second example will cause the monitor to execute from the
address C000 with a breakpoint at C084. If the code flows through
this address then it will return to the monitor displaying the Break-
point address and the contents of the registers. Such an example
could be as follows:

*C884

AF BC DE HL IX
2A3 E 22AA 8808 DE F8 D D FE
8888 8888 2232 2312

H start address end address byte value (HUNT fora byte)


The HUNT command will allow you to search for a specific byte
through a given set of addresses. Type in ‘H’ and then give the start
address, the end address and the byte value for which you wish to
search. The routine will then display each address where that byte is
found, pausing for you to type in ENTER. To exit from this routine
before the search is exhausted, any other key may be pressed.

‘ .
A Spectrum monitor 75

I>H 88 8188 2A
888
8818
8831
883A
8868
887A
>

The above example will search for the byte 2A hex. From the address
8880 to 0188 hex. When the search is exhausted the monitor returns
with the prompt.
Istring (Identify file name)
This command is used in conjunction with the SAVE and LOAD com-
mand identifying the file name to be LOADed or sAvEd.
Type in '1‘ and then input a filename consisting of no more then
ten letters of the alphabet. Lower case letters will be ignored.

>l SPECMON

The example above will set the identifier to the string 'sPEcMON’.
L start address,-number of bytes (Load file)
The LOAD command will wait for the filename given by the identifier
(see the ‘I’ command) and once found on the tape will start to LOAD it
at the given address. The second parameter (also a two byte
nu mber) specifies the number of bytes to LOAD. The LOAD command
will read in each file of the tape and display its header to the screen.

>l SPECMON
:>L C008 0188
Waiting for SPECMON

The commands above will LOAD the file ‘SPECMON’ to the address C888
hex. The number of bytes to be LOADed is 256 (i.e. 0108 hex). To exit
from the LOAD command at any time press both the <cAPs 5HlFT> and
the <BREAI<> keys.
M start address, end address, destination address (MOVE Block)
This command will MOVE blocks of data to a given address. You need
to specify the start address, end address and the destination
address.

>M C888 DB88 4888


76 A Spectrum monitor

The above example will MOVE data from the address C808 up to DB88
hex to the address 4008 hex.
Paddress (PRINTASCH)
The PRINT command is similar to the DUMP command except that it
displays the contents of the memory in ASCII code form rather than
hexadecimal. For example,

>-P 0690
will PRINT the ASCII contents from the address 8690 hex. To continue
the listing press <ENTER:>, otherwise press any other key.
R or R r or R ’r (REGISTER modify)
The REc;IsTER command allows you to examine or modify any register
r, where r can be any of the following:

modifies the AF register pair


modifies the BC register pair
modifies the DE register pair
modifies the HL register pair
><IU='=> modifies the Ix register pair
To examine the contents of the registers type in the command ‘R’
and the <ENTER>.

>R ENTER

AF BC DE HL IX
F F3E 8888 8888 F22A 8888
8888 8888 8888 882A

The second value under each register pair is the contents of the
alternative register set. The IY register is not shown as this is used by
the BASIC system.
To modify a register, you can simply type in the register pair you
wish to modify, after typing in the command ‘R’. The monitor will
then display the current value of the register pair, waiting for an
INPUT of the new value. To modify the alternative set, type a ' before
entering the register pair. For example:

>R H 882A 2FFF


>R ’D 8808 2A33

This will change the contents of HL register pair to the value 2FFF
hex, and the alternate DE register pair to 2A33 hex.
A Spectrum monitor 77

S start address ,number of bytes (SAVE)


The sAvE command is used to sAvE machine code to a tape recorder.
The start address and the number of bytes to sAvE are the parameters
that you will need to specify with this command. The monitor will
then prompt you to get the tape recorder ready and sAvE the portion
of code on tape. The file name is set by using the ‘I’ (Identify)
connnand.Forexannfle:

>l FRED
>5 4008 1B88
Press any key when ready

These will sAvE the 6912 bytes from the address 16384 to the tape.
The file will be sAvEd as ‘FRED’.
The listings follow below.

Listing 1: BAsIC Hex Monitor

1B CLEAR 25499
2B BLS : GU SUB 168
36 LET a=x
4B GD SUB 32B: PRINT x$;":";
SB FDR 2=1 TO B: BU SUB 9B: IF
a$="$$" THEN ED TD 1B
63 LET a=a+1: NEXT 2
76 PRINT
BB LET x=a: BO TD 4B
RB INPUT "hex :"; LINE ai: IF
LEN a${}2 THEN GD TU RB
IBB IF a$="$$" THEN RETURN
113 IF a$=“##" THEN STOP
128 BB SUB 253
133 IF e=1 THEN BU TD 90
146 PDKE a,x: PRINT a$;" ";
156 RETURN
166 INPUT "addr:"; LINE bi: IF
LEN b$€}4 THEN ED TD lbfl
17B ED SUB 253
188 IF e=1 THEN GD TD 163
19E LET x=t*256+x: LET a=x
2Bfl RETURN
21B REM two byte hex input
223 LET a$=b$(1 TD 2)
Iii '_jj|III

78 A Spectrum monitor

236 GD SUB 256: LET t=x


245 LET a$=b$(3 TD 4)
256 REM one byte hex input
266 LET e=6
276 LET I=FN x(2): IF 1}15 THEN
LET e=1
286 LET h=FN x(1): IF h}15 THEN
LET e=1
296 LET x=h*16+1
366 RETURN
316 DEF FN x(n)=CDDE a$(n)—4B—(
CODE a$(n)}57 RND CODE a$(n)<71)
*7—(CUDE a$(n)}R6 AND CODE aitn)
€163}*39
326 REM two byte input
336 LET h=INT (xf256): LET 1=x—
h*Q56
346 LET x=h: BU SUB 376
356 LET x=1: GU SUB 386
366 RETURN
376 LET R$=""
386 LET p=INT (x716): GU SUB 39
6:LET p=x—(INT (x/16))*16
396 REH hex
466 IF p}? THEN LET a$=CHR$ (p+
CODE IlAll___1@)

416 IF p<=9 THEN LET a$=CHR$ (p


+CDDE "6")
426 LET x$=x$+a$
436 RETURN

Listing 2: Spectrum Monitor Hexadecimal Listing

639C C3 36 64 3E FF CD C2 G4
63A4 C9 37 3E FF CD 56 65 C9
63AC 11 11 66 DD 21 66 69 AF
6354 37 CD 56 65 3A 11 69 4F
63BC 3E 24 32 11 69 CD CD 68
63C4 11 67 69 CD 2C 64 3E 26
63CC CD 22 64 EB 71 23 23 23
63D4 7E CD 92 66 2E 7E CD 92
A Spectrum monitor 79

63DC 66 28 3E 26 CD '2'?
.n...|... 64 7E
63E4 CD 92 66 28 7E CD 92 66
63EC CD CD 68 C9 11 11 86 DD
63F4 21 66 69 AF CD C2 84 C9
63FC E5 C5 D5 CD A7 64 3A 38
6464 5C CB 6F 28 F9 C8 AF 32
646C 38 5C D1 C1 E1 C9 CD FC
6414 63 3A 68 5C CD on
11.11. 64 C9

641C 3E 62 CD 81 16 C9 F5 F5
6424 AF 32 8C 5C F1 D7 F1 C9
642C 1A FE 24 C8 CD 22 64 13
6434 18 F6 31 6E 69 CD 1C 64
643C 11 B6 65 CD 2C 64 11 44
6444 65 CD 2C 64 CD CD 68 31
644C 6E 69 3E 68 32 6A 5C 21
6454 6F 69 36 48 23 36 64 28

645C 22 3D 5C 21 5F 64 E5 CD
6464 CD 68 3E 3E CD 22 64 CD
646C 12 64 D6 41 D8 FE 13 D8
6474 87 21 B1 64 5F 16 66 19
647C 5E 23 56 E8 E9 83 66 83
6484 66 83 66 1A 66 83 64 E1
648C 66 17 67 8F 68 5E 68 83
6494 66 83 66 FC 64 33 68 83

649C 66 83 66 5A 66 83 66 E2
64A4 67 85 65 61 68 88 11 88
64AC 48 21 86 48 ED B6 C9 CD
6484 EE 64 CD 8D 66 3E 28 CD
64BC 22 64 7E CD 92 66 3E 28
64C4 CD 22 64 E5 CD 81 66 E1
64CC 77 23 CD CD 68 18 E6 CD
64D4 D6 66 E5 3E 26 CD 22 64

64DC CD D6 66 E5 D1 E1 C9 CD
64E4 D3 64 E5 D5 CD EE 64 D1
64EC E1 C9 3E 26 CD 22 64 CD
64F4 D6 66 E5 C1 CD CD 68 C9
64FC 3E 28 CD 22 64 CD D3 64
6564 22 46 65 78 82 CA AE 66
656C ED 53 42 65 11 7D 65 CD
6514 2C 64 11 17 69 CD 2C 64
||||_|

80 A Spectrum monitor

651C CD 4C 63 11 E7 69 21 17
6524 69 86 G4 14 CB 4F 4E CB
652C 49 89 28 EC 23 13 18 F3
6534 ED 58 42 65 DD 24 48 65
653C CD 45 63 C9 88 88 88 G8
6544 8D 24 53 42 55 47 24 28
654C 28 43 29 28 44 6F 68 6E
6554 28 57 69 6C 73 6F 6E 28
655C 31 39 38 34 2E ED 24 8D
6564 58 72 65 73 73 28 61 6E
656C 79 28 68 65 79 28 77 68
6574 65 6E 28 72 65 61 64 79
657C 24 8D 57 61 69 74 69 6E
6584 67 28 66 6F 72 28 24 8D
658C 52 4F 55 54 49 4E 45 28
6594 4E 4F 54 28 49 4D 58 4C
659C 45 4D 45 4E 54 45 44 24
6544 8D 24 24 45 52 52 4F 52
654C 24 24 8D 24 16 81 81 ED
6584 24 3E 28 CD 22 64 CD D3
658C 64 22 13 69 78 B2 C4 4E
65C4 66 ED 53 11 69 11 63 65
65CC CD 2C 64 CD 47 64 CD 47
65D4 64 CD 47 64 CD 12 64 3E
65DC I3 11 86 69 21 17 69 12
65E4 13 81 G4 88 ED 88 CD F8
65EC 63 CD 47 64 CD 47 64 CD
65F4 47 64 DD 24 13 69 ED 58
65FC 11 69 CD 9F 63 C9 E5 CD
6684 92 66 3E 28 CD 22 64 E1
668C C9 86 88 7E CD 52 66 23
6614 18 F9 CD CD 68 C9 3E 29
661C CD 22 64 CD EE 64 8E 88
6624 CD 8D 66 3E 28 CD 22 64
662C CD 22 64 CD 8D 66 8D 28
6634 EF CD CD 68 CD CD 68 CD
663C 12 64 FE 8D 28 E8 C9 86
6644 15 7E FE 28 38 84 FE 88
664C 38 82 3E 2E CD 22 64 23
6654 15 EF CD CD 68 C9 3E 28
A Spectrum monitor 81

665C CD 22 64 CD EE 64 8E 88
6664 CD 8D 66 3E 28 CD 22 64
666C CD 22 64 CD 43 66 8D 28
6674 EF CD CD 68 CD CD 68 CD
667C 12 64 FE 8D 28 E8 C9 88
6684 D5 11 88 65 CD 2C 64 D1
668C C9 7C CD 92 66 7D 5F C8
6694 3F C8 3F C8 3F C8 3F CD

669C 41 66 78 E6 8F C6 38 FE
6644 34 F4 44 66 C6 87 CD '3'?
A-aha

664C 64 C9 C3 48 64 CD 12 64
6684 CD C8 66 5F CD 12 64 CD
668C C8 66 C8 23 C8 23 C8 23
66C4 C8 23 83 C9 47 DE 38 FE
66CC 84 D8 47 DE 87 FE 18 38
66D4 D9 C9 CD 81 66 F5 CD 81

66DC 66 6F F1 67 C9 3E 28 CD
66E4 22 64 CD D3 64 3E 28 CD
66EC 22 64 E5 E8 47 ED 52 D4
66F4 4E 66 C4 4E 66 E5 C1 E1
66FC E5 D1 13 E5 D5 CD 81 66
6784 D1 E1 77 ED 88 CD CD 68
678C C9 D1 21 44 67 E5 D5 CD
6714 64 67 C9 3E 28 CD 22 64

671C CD D6 66 E5 3E 28 CD 22
6724 64 CD 12 64 FE 8D 28 E1
672C FE 2C C2 4E 66 CD D6 66
6734 E5 11 81 69 81 83 88 ED
673C 88 E1 36 CD 23 36 7E 23
6744 36 67 CD 64 67 C9 ED 73
674C 84 69 31 81 69 88 D9 E5
6754 D5 C5 F5 D9 88 DD E5 E5

675C D5 C5 F5 ED 78 84 69 C9
6764 ED 73 84 69 31 EF 68 F1
676C C1 D1 E1 DD E1 88 D9 F1
6774 C1 D1 E1 88 D9 ED 78 84
677C 69 C9 CD 44 67 E1 28 28
6784 28 CD CD 68 3E 24 CD 22
678C 64 CD 8D 66 E8 21 81 69
6794 81 83 88 ED 88 CD 84 67
ll lll.|_|_U"'LL_|" Ll_LLL_l_1 ' QLHJ _

82 A Spectrum monitor

679C C9 86 84 5E 23 56 E8
6744 CD 8D 66 3E 28 CD J81 -GL4 64
674C CD 22 64 E1 23 18 EC C9
6784 CD CD 68 11 D3 68 CD 2C
678C 64 21 EF 68 CD 9D 67 CD
67C4 CD 67 CD CD 68 CD 9D 67
67CC C9 7E F5 23 7E CD 92 66
67D4 F1 CD 92 66 23 3E 28 CD

67DC '17’?
4.4.. 64 CD "1 '1
4'... AL- 64 C9 3E 28
67E4 CD 22 64 CD 12 64 FE 27
67EC 28 85 CD 12 64 C6 88 21
67F4 24 68 81 89 88 ED 81 C2
67FC 84 67 28 11 24 68 47 ED
6884 52 11 EF 68 C8 25 19 23
688C 3E 28 CD 22 64 7E CD 92
6814 66 28 7E CD 92 66 23 3E

681C 28 CD 22 64 CD 81 66 77
6824 28 CD 81 66 77 C9 41 42
682C 44 48 58 49 44 4C 58 3E
6834 28 CD ‘D’?
awn“ 64 CD E3 64 E5
683C 47 ED 52 38 84 E1 E8 18
6844 F6 E8 C5 D5 C1 D1 F1 E5
684C 47 ED 52 E1 38 83 ED 88
6854 C9 89 28 E8 89 28 E8 ED

685C 88 C9 3E 28 CD 22 64 CD
6864 12 64 FE 88 C8 FE 41 D4
686C 4E 66 21 17 69 86 84 8E
6874 28 71 23 18 FC 21 17 69
687C 86 89 77 85 C8 23 CD 12
6884 64 FE 8D C8 FE 41 D4 4E
688C 66 18 EF 3E 28 CD 22 64
6894 CD D3 64 E5 E8 47 ED 52

689C D4 4E 66 C4 4E 66 E5 C1
6844 E1 3E 28 CD 22 64 E5 D5
684C CD 81 66 D1 E1 8E F5 28
6884 8D CD CD 68 CD 8D 66 CD
688C 12 64 FE 8D 28 89 23 88
68C4 78 81 28 83 F1 18 E6 F1
68CC C9 3E 8D CD 22 64 C9 41
68D4 46 28 28 28 28 42 43 28
A Spectrum momtor 83

éBDC 2E 26 EB 44 45 29 29 29
68E4 25 48 4C 26 28 EB 28 49
6BEC 58 BD 24 HQ BB BB BB B8
é8F4 GB EB BB G5 IQ BE QB HQ
68FC H8 HG BE BB BB HG BB E9
6934 EB EB GB H5 G5 E8 BB 99
698$ BB BB BB BB BB BB B9 BB
6914 GE EB BE GB BB BB HQ BB

691C EB BB BB EB BB BD 24 QB
6?24 BE EB EB BB GB EB BB BE
692C BB GB B6 BB BB QB 69 B6
6934 BB Q8 QB BE BB BE BB @@
693C BB 68 QB BB EB 89 QB EB
$944 QB QB 98 G6 EH E8 @@ QB
694C BB HE B8 EB EB BB B8 QB
é?54 BB EB 55 BB QB QB QB @@
8 Program production

In this chapter we will go step-by-step through an example machine


code program looking at the different sets of instructions and how
they are assembled into machine code by the assembler. You may
remember that in the first chapter we explained that there are
several ways of writing machine code programs. One method is to
use a professional assembler such as HI—SOFT'S ’DE\/PAC’. Another is to
use a monitor which allows us to INPUT machine code by its hex-
adecimal values.
Using an assembler is the best method of writing machine code as
it is written in the mnemonic type instructions which are so easy to
learn. When a program is in the process of being assembled the
assembler goes through each mnemonic converting it to its machine
code equivalent into another part of memory. Most assemblers on
the market provide the option of seeing the mnemonic files trans-
lated to their hexadecimal equivalents and the addresses where
each particular instruction is to be stored in memory.
Below is an example of an assembled listing:

ORG 16384
4000 3E 21 LD A,33
4002 C9 RET
-END

The first instruction ‘ORG’ (0Rioin) is not a Z80 instruction but is used
to tell the assembler at what address to place the first instruction in
memory. Our example shows that the origin is set at 16384 decimal
so that the first instruction will be assembled at 16384 or 4000 hex.
The assembled listing shows mnemonics to the right of the listing
and the address and hexadecimal Op codes to the left. Why are
hexadecimal values displayed and not decimals? Well why not?
Hexadecimal number are used for convenience sake only. They use
fewer digits to represent the decimal numbers 0-255 and are easier
to read . . . well they should be easier to read after a bit of practice!
The first address is 4000 hex which is 16384 decimal. At this
address the Op code for to A, (LOAD the A register) is placed. The
Program production 85

content of the address 4001 hex (16385) is the data byte 33. This is
shown by its hexadecimal equivalent 21 hex. Since the first instruc-
tion was two bytes long the next instruction will be placed at the
address 4002 hex or 16386 decimal. This is the RETurn instruction
which is only one byte long and has the value C9 hex or 201 decimal.
The last instruction ‘END’ is also not aZ80 instruction. This is used by
most assemblers to signify that there are no more instructions to
assemble. Now armed with this information we can now go through a
short assembled listing looking at each instruction and the effect it
has. Also listed is a hexadecimal dump of the program which can be
used with the BASIC monitor or machine code monitor listed in this
book. instruction will be given on how to INPUT the machine code
using the BAsIC monitor. First of all let's go through the overall effect
of the program.
The machine code routine enables you to enhance your programs
by having a scrolling attribute BORDER along the edges of the screen. A
coloured BORDER is produced along the screen by POI<Eing the attribute
file with random PAPER colours. Then the routine begins to move the
whole BORDER in a clockwise direction. The whole program comes in
two parts: a BAsIC listing (listing 1) and the machine code (listing 2).
The BASIC program does the easy work. lt draws a random Coloured
BORDER along the Spectrum screen. Line 10 sets the variable x to the
address of the start ofthe attribute file 22528 and this is used to place a
random line of PAPER colou rs along the top of the screen. Lines 20 to 40
produce the top BORDER by POI<Eing a random PAPER colour (The PAPER
colour is produced by multiplying a random number from 0 to 7 by 8).
The lines 50 to 100 produce two coloured BORDERs along the side of
the screen and finally, lines 110 to 140 produce the BORDER for the
bottom of the screen. After the BORDER is produced the machine code
routine is executed by the BASIC line 150 'RANDOMlZE usR 30000’. The usR
command is used by BASIC to call a machine code routine in memory.
The add ress following the USR instruction is the address to where BASIC
will jump. lt executes our machine routine which will shift the whole
BORDER clockwise by one attribute. After the machine code routine
has been executed and returns back to BASIC (by using a REr instruc-
tion) the line following the BASIC call will be executed. Line 160 is used
to slow down the scroll by pausing for1 second. Line 170 jumps back
to 150 to call the machine code routine again and again until the user
breaks out by pressing <cAPs SHlFl'> and <:BREAl< SPACE:> together.
Type in the BASIC program and SAVE it by typing sAvE “DEMO”. DO
NOT RUN it at this point, as we have not yet typed in the machine code
routine. RUNl‘liflg the program will probably result in the Spectrum
crashing and losing the BAsIC program!
86 Program production

With the BASIC program safely sAvEd on a cassette, you should now
key-in the assembler listing on page 91. To do this you will, of
course, have to LOAD your assembler first. When this listing has been
entered into the Spectrum you should sAvE the source code, again
onto a cassette, using the appropriate command for your assembler.
Next, CLEAR the memory of the machine by switching it off and then
on again.
Then LOAD up the BASIC ‘DEMO’. Before re-LoADing the machine
code program type in CLEAR 29000. This will re-set RAMTOP to protect
our machine code program. LOAD the machine code routine from
the tape into the Spectrum by typing LOAD ”DEMOC” cODE and
<EI\iTER>. After it has LOADed, RUN the program and we should get a
coloured BORDER scrolling around the screen in a clockwise direc-
tion. If the program does not scroll the border then probably you
have mis-typed the machine code routine. Re-type the routine again
using the BAsIC monitor.
Now let’s look more closely at the machine code routine and see
how it works:

ORG 30000

The first line tells the assembler where the origin of the machine
code is to be assembled. Since our program is to be placed at the
address 30000, this number is placed after the ORC instruction.

ATTRADD EQU 5800H

The next instruction is like the ORC instruction in that it is not a Z80
one. lt is used by the assembler to produce a table of Strings
(symbols) which hold one or two byte numbers. The string ‘EOU’
stands for EQuate and produces the string and gives it the value
following the EQuate. ln this way the above line will produce the
symbol ArrRADD with the number 5800 hex (22528 decimal].
The symbol ATTRADD now holds the address of the attribute file.

LD HL,ATl'RADD+31 ;POlNT TO RIGHT HAND SIDE OF ATTR


LD DE,ATTRADD+30 ;DE POINTS TO THE NEXT ATTR

The next two instructions are at the start of the machine code
program. These use the value ArrRADD contained in the assembler’s
symbol table. The HL register pair is LOADed with the address of 5800H
Program production 87

plus 31 decimal and the DE pair is LOADed with the address 5800i-I+ 30
decimal. The assembler will automatically calculate the two results
and place the address in the source output.
The HL register pair contains the address of the far right hand
corner of the top row of the attribute file. The DE register pair holds
the address of the attribute location to the left of the top right hand
corner (it points to the left of the HL register pair).
The object of the first portion of code is to move each of the 31
attributes of the top line of the screen one character along to the
right. This is done by repeatedly replacing the attribute byte pointed
to by the DE pair and placing it in the location pointed to by the HL
pair. Then make the two pointers point to the next locations.
The loop DOTOP, therefore, is used to scroll the top attribute line
from the left to the right:

LD A,(HL) ;SA\/E FIRST ATTRIBUTE


PUSH AF ;ON THE STACK

Before going into this loop we have to SAVE the attribute in the top
right hand corner. This will be over-written with the new attribute to
its left.
The first part of the code LD A,(HL) LOADS the contents of the
address pointed to by the HL pair. This is the top right hand corner of
the attribute file and places the value into the A register. The second
instruction PUSH AF pushes this attribute onto the stack, where it will
Stay until we need it. This has the effect of saving the first attribute
onto the stack.

LD B,31 ;LOAD B WITH COLUMN COUNTER

We now set up a loop counter needed to scroll the top line of the
attribute file. This is done by LOADing the B register with the value 31
decimal, which is the number of characters we have to scroll across.

DOTOP: LD A,(DE) ;GET NEXT ATTRIBUTE


LD (H L),A ;AND PLACE IT TO THE ATTRIBUTE
;TO THE LEFT
DEC DE ;POlNT TO THE NEXT ATTRIBUTE
DEC HL
DJNZ DOTOP ;REPEAT UNTIL ALL COLUMNS DONE

The content of the DE register pair is LOADed into the A register with
_..iI T

88 Program production

the instruction LD A, (DE). This instruction is used to force the new


byte to be scrolled to the right. This new attribute is placed to the
right by LOADing it to the address pointed to by the HL pair, per-
formed by the instruction LD (I-IL) ,A (LOAD into the address pointed by
the HL pair the contents of the A register). The attribute, pointers are
then moved to the left by one attribute by subtracting one from each
of the pointers. The DECrement instructions DEC DE and DEC HL are
used to implement this. The last instruction of this portion of code is
the branch instruction DJNZ ’DEcrement and Jump if Not Zero‘. This
instruction takes the B register from our column counter and sub-
tracts one from it. If the result is not zero (if the B register does not
contain a zero) then a relative jump is made to the address DOTOP.
Remember, a relative jump differs from an absolute jump in that an
offset number of bytes is given to where the program must jump
instead of a two byte address. The assembler has the job of cal-
culating this offset. It does this by working out the number of bytes
between the lable DOTOP and the instruction DJNZ DOTOP.
After leaving this loop the program has to deal with the coloured
borders along the Iefthand side of the attribute file. Since the HL pair
has been decremented 31 times in the loop it will now point to the
start of the attribute file 5800 hex. The DE pair will point to the
address 57FFH:

LD BC,32 ;LET HL POINT ONE ROW DOWN


ADD HL,BC ;BY ADDING 32
INC DE ;DE NOW POINTS TO START
;OFATTRlBUTE FILE IE. 5800H

The HL pair is adjusted to point to the second attribute row by the


adding of 32. This is done by the two instructions LD BC, 32 (LOAD the
Bc pair with 32) and ADD HL, Bc (ADD to the HL pair the contents of the
BC pair). The DE is adjusted to point to the start of the Attribute file.
Since its value is 57FFH then it is a simple matter of adding one to get
the desired result. Therefore we use the instruction which incre-
ments the DE pair by one: ‘INC DE‘.
Now we come to the portion of code which deals with scrolling
the attributes from the bottom left hand side to the top left hand
side:

LD B,21

The B register is set with the row counter and the loop DOLE!-T is then
entered. This time the HL register pair points to the new attribute
and the DE pair points one row up to the old attribute. Like the first
Program production 89

portion of code which dealt with the scrolling, the top row of the
contents of the new attribute address is placed into the old attribute
address. The pointers are then updated to point to the next
attributes. Since we are going down the attribute file we must add an
offset of 32 to both the DE and I-IL register pairs. The BC register pair is
placed onto the stack, which saves the row counter from being
corrupted. The BC pair is then LOADed with 32 which is the offset
needed to point to the next row down. This is added to the HL pair so
that it now points to the next row down. It is then exchanged with the
DE pair so that it too can be updated. The instruction Ex DE,HL (Exchange
the DE pair with the HL pair) is used because there is no such
instruction as ADD DE,BC. Therefore we swap the two pairs and update
the other pointer with a second ADD I-IL,BC instruction. To restore the
registers to their new values we have to use the Exchange instruction
once more. The row counter is then restored by the instruction POP BC
(POP the top of the stack to the BC pair) which is decremented and
tested to see if we have moved 21 bytes in the DINZ instruction.

DOLEFT:LD A,(HL)
;GET ATTRIBUTE BELOW
LD (DE),A
;AND PLACE ON OLD ONE.
PUSH BC ;SA\/E ROW COUNTER
LD BC,32;NEXT ROW OFFSET
ADD HL,BC,'HL NOW POINTS TO NEW ROW
EX DE,HL;SWOP FOR DE
ADD HL,BC;WHAT WAS DE NOW POINTS TO NEW
;ROW
EX DE,HL ;RESTORE BACK TO NORMAL
POP BC ;RESTORE ROW COUNTER
DJNZ DOLEFT ;REPEAT UNTIL ALL ROWS DONE

After executing the above loop the DE pair points to the bottom
Iefthand side of the attribute file. We now need to scroll the bottom
line from the right to the left. Therefore, we need the HL pair pointing
to the attribute to the right of the DE pair.

LD H,D ;PLACE DE INTO HL


LD L,E

The DE pair is first copied into the HL pair by the two instructions
LOADing the high part ofthe DE pair (the D register) into the high part of
the HL pair (the H register). This is performed with the instruction LD
H,D (LOAD into the H register the contents of the D register). Then the
low part is copied by using the instruction LD L,E (LOAD the L register
with the contents of the E register).
II.i.II.IIII "" '

90 Program production

Now that the HL pair is also pointing to the bottom left hand
corner, point it to the right of the DE pair by incrementing it by one
using instruction INC HL (lNCl'ElT1€I'1l the I-IL pair by one).

INC HL ;HL POINTS ONETO RIGHT OF DE

The next portion of code is very similar to the DOTOP but this time we
are scrolling the attributes in the opposite direction. Notice that we
are incrementing the pointers instead of decrementing them.

LD B,31 ;LOAD B REG WITH COLUMN COUNTER


DOBOT: LD A,(HL) ;GET DATA FROM THE ATFR ON RIGHT
LD (DE),A ;AND PLACE IT IN THE LEI-T
INC HL ;POINTTO NEW ATFRIBUTES
INC DE ;TO THE RIGHT
DJNZ DOBOT ;REPEAT UNTIL DONE 31 TIMES

After scrolling the bottom portion of the attributes we now deal with
the scrolling of the right hand side of the attributes.
First, we adjust the HL register pair to point to one row above the
DE pointer. The instruction LD BC,—32 is the one used. The final
portion of code is similar to the loop DOLEFT but this time we are only
scrolling 20 rows as the second row from the top has its new
attribute sAvEd on the stack.

DEC HL
;RE-ADIUSTHL BACK ONE
LD BC,—32
;AND MAKE IT POINT TO ONE
ADD HL,BC
;ROW ABOVE DE
LD B,20
;THlS TIME ONLY DO 20 TIMES
;AS LAST ATFRIBUTE IS HELD ON
;THE STACK
DORIG: LD A,(HL) ;GET THE ATTRIBUTE ABOVE
LD (DE),A ;AND PLACE IT TO THE ATTRIBUTE
;BELOW
PUSH BC ;SAVE ROW COUNTER
LD BC,—32 ;LOAD BC WITH OFFSET
ADD HL,BC ;MAKE HL POINT TO ONE ROW ABOVE
EX DE,HL ;SAVE TEMP IN THE DE PAIR
ADD HL,BC ;MAKE OLD DE POINT ONE ROW ABOVE
EX DE,HL ;AND RESTORE BACK DE AND HL
POP BC ;AS WELL AS THE ROW COUNTER
DJNZ DORIG ;REPEAT UNTIL ALL ROWS DONE

Finally, we ‘POP’ off the first attribute that we saved and place it to

.-__
Program production 91

the last attribute on the second row of the screen. The RETurn
instruction then RETURNS control back to the BASIC program.

POP AF ;GET AITRIBUTE VALUE ON STACK


LD (DE),A ;AND PLACE IN NEW POSITION
RET ;AND RETURN

ENE)

ORG 30006

ATTRADD EOU SBDOH

LD HL,ATTRADD+31 ;POINT TO RIGHT HAND


ISIDE OF ATTR
LD DE,ATTRADD+3O ;DE POINTS TO THE NEXT ATTR
LD A,(HL) ;SAUE FIRST ATTRIBUTE
PUSH AF ION THE STACK
LD B,31 ;LOAD B UITH COLUMN COUNTER
DOTOP: LD A,(DE) ;GET NEXT ATTRIBUTE
LD (HL),A ;AND PLACE IT TO THE
;ATTRIBUTE TO THE LEFT
DEC DE IPOINT TD THE NEXT
;ATTRIBUTES
DEC HL
DJNZ DOTOP IREPEAT UNTIL DONE
l ALL COLUMNS

IHL NOH POINTS TD SBOOH IE TOP


JLEFT HAND CORNER OF ATTRIBUTES

LD BC, 32 ;LET HL POINT ONE RDH DOIIIN


ADD HL, BC IBY ADDING 32
INC DE ;DE NON POINTS TO START
IOF ATTRIBUTE FILE IE SBOH

LD B,21
Ill llllllllll|"llI|

92 Program production

DOLEFT LD A,(HL) GET ATTRIBUTE BELOU


LD (DE),A AND PLACE ON OLD ONE.
PUSH BC SAUE RON COUNTER
LD BCI32 NEXT ROH OFFSET
ADD HL,BC HL NOH POINTS TO NEH RON
EX DE:HL SNAP FOR DE
ADD HLIBC HHAT HAS DE NOU POINTS
TO NEH ROH
EX DEIHL RESTORE BACK TO NORMAL
POP BC RESTORE ROU COUNTER
DJNZ DOLEFT REPEAT UNTIL DONE ALL ROHS

LD FPLACE DE INTO HL
LD fi1CI
INC IIF'II FIE‘I IHL POINTS ONE TO
FRIGHT OF DE

LD B,31 ;LOAD B REG UITH COLUMN


ICOUNTER

DOBOT: LD AIIHL) GET DATA FRON THE ATTR


ON RIGHT
LD (DELA AND PLACE IT IN THE LEFT
INC HL POINT TO NEH ATTRIBUTES
INC DE TO THE RIGHT
DJNZ DOBOT REPEAT UNTIL DONE 31 TIMES

DEC HL RE-ADJUST HL BACK ONE


LD Bcr_32 AND HARE IT POINT TO ONE
ADD HLIBC RON ABOVE DE

LD B,20 THIS TINE ONLY DO 25 TIMES


AS LAST ATTRIBUTE
IS HELD ON THE STACK
Program production 93

DORIG I LD A,(HL) GET THE ATTRIBUTE ABOVE


LD (DE) I A I AND PLACE IT TO THE
I
ATTRIBUTE BELON
PUSH BC 1 SAVE RON COUNTER

LD BCI-32 LOAD BC NITH OFFSET


ADD HLIBC MAKE HL POINT TO ONE
RON ABOVE
EX DEIHL SAVE TEMP IN THE DE PAIR
ADD HLIBC MAKE OLD DE POINT ONE
RON ABOVE
EX DEIHL AND RESTORE BACK DE AND HL
POP BC AS NELL AS THE RON COUNTER
DJNZ DORIG REPEAT UNTIL DONE ALL RONS

POP AF GET ATTRIBUTE VALUE


ON STACK
LD (DEJIA IAND PLACE IN NEN POSTION
RET ‘AND RETURN

5 CLEfiH,2999B:BDHDER B GL5
1B LET X=E25E8
EB FUR F=X TD 1+3
33 PDHE F,B*RND*?
43 NEXT F
53 FDR 5=1 TU E1
ED LET fi=X+3E*5
?fl PURE fi,B*RND*7
BB LET fi=fi+31
SB PDHE fi,B*RND*7
lflfl NEXT 5
113 FDR X=232B1 TD _32B1+IB
133 PURE X,B*RND*7
14D NEXT X
15B HANDUHIZE USR EBBBB
163 PAUSE 13
173 GD TD 156
|||| lll |
jLI|II

9 Using the ROM


roufines
The ROM (Read Only Memory) is a permanent program built into the
Spectrum. It handles the interpretation and execution of BASIC and
controls the operating system. It is contained in the first 16k of the
Spectrum's memory map and enables you to RUN and edit BASIC pro-
grams. The ROM manages sound, graphics and Communication
between the cassette port and the keyboard.
It is worthwhile looking at some of the routines contained in the
ROM as these can be used by the programmer when memory space is
scarce. They can also be utilised if a complex arithmetic routine is
needed or a particular function of the Spectrum is to be used. Each
ROM routine is found at a particular memory location and we need to
know the correct sequence of operations and the values that must
be placed in selected registers.

PRINT and CHANNEL routines


The following routine allows the user to PRINT characters to what are
known as streams via channels. A channel is the route by which
input and output are effected to the various devices on a computer.
Examples of such devices on the Spectrum are the keyboard, the
printer and the screen. There are seven channels on the Spectrum,
the most useful ofwhich are given below:

Channel 0 or Channel K (used for input and output to bottom part


of screen)
Channel 1 or Channel K (as Channel 0)
Channel 2 or Channel S (used for printing to the screen)
Channel 3 or Channel P (used for printing to the printer)

Before we PRINT to a Channel we must indicate to the Spectrum


which stream we wish to use. This is known as ‘Opening a Channel’.
When we use the ROM routines to PRINT a character the output will go
to the currently selected channel until we open another channel. To
open a channel we LOAD the A register with the channel number we
wish to use. We then call the ROM routine at address 1601 hex which
Using the ROM routines 95

will ‘open’ that channel. Any PRINTing done by means of the ROM
routines would now send the output to the channel selected.
Therefore, if we wanted to start PRINTing to the screen we would
open channel 2:

LD A,2 ;seIect screen


CALL 1601H ;open channel

Now to start PRINTing a character to the currently selected channel


we can use a routine at the address 10 hex. The A register is LOADed
with the ASCII value of the character we wish to PRINT. We use the
call instruction:

RST 10H ;print the character in A reg


;to the current channel

The RST 10 subroutine is extremely useful when PRINTing to the


screen because it automatically updates the system variables by
updating the print co-ordinate of the next character position. It can
also handle all the control characters, thus enabling us to simulate
the PRINT AT ,TAB,lNK,PAPER,OVER,INVERSE,BRlCHT and FLASH BASIC com-
mands. Given below is a table of the control characters and their
Code values:

Character ASCII value (decimal)


INK 16
PAPER 17
FLASH 18
BRIGHT 19
INVERSE 20
OVER 21
AT 22
TAB 23

Therefore if we wished to PRINT the character ‘A’ on the screen at Y


position 10 and X position 10, in blue INK yellow PAPER we would use
thecode:

LD A,2 ;first open channel 2


CALL 1601H
LD A,22 ;PRlNT AT
RST 10H
LD A,10 ;PRlNT AT10
RST 10
ILIII Ill T

96 Using the ROM routines

LD A,10
RST 10H PRINT AT 10 10,
LD A,16 ;lNK
RST 10H
LD A,1 LOAD A WITH CODE FOR BLUE
RST 10H BLUE INK
LD A,17 PAPER
RST 10H
LD A,6 ;YELLOW PAPER
LD A,‘A‘
RST 10 ;PRlNT CHARACTER

PRINT STRING-203C hex


This routine can be used to print a string of characters. The DE regis-
ter pair is set up to contain the address of the start of the string that
we wish to print, the BC register contains the number of characters
in the string. As an example we have taken the last routine but this
time all the characters have been put into a string:

LD A,2
CALL 1601H ;open Channel 2
LD DE,string ;point to string
LD BC,8 ;number of chars in string.
CALL 203CH ;print string.
RET ;and return
string: DB 22,10,10,16,1,17,6,‘A’

Printing numbers
PRINT LINE NUMBER - IAIBH
This is a simple routine which is used by the ROM to PRINT line
numbers in BASIC therefore it is limited to PRINTing numbers from 0 to
9999. The BC register pair is set up with the number we wish to PRINT;

LD BC,400H
CALL 1A1 BH ;print1024 decimal
RET

PRINT LINE NUMBER2 - 1A28H


This routine is identical to the one above except that the number is
pointed to by the HL pair.
Using the ROM routines 97

LD HL,6000H address contents


CALL 1A28H 6000b 03H
RET 6001 h CAH

This section of code would result in the number 970 decimal being
PRINTed to the current channel. You may notice that the two bytes
that make up the number are stored in memory in the reverse
manner to that usually used by the Z80 (i.e. MSB, LSB). This is due to
the line numbers being held the ‘wrong way’ round in memory.

SCREEN ADDRESSING
Screen addressing routines in the ROM are used for PRINTing and
PLOTting. When we PLOT a point using the Spectrum BASIC the screen
is split into a grid of 176 lines by 256 points with the co-ordinate 0,0
starting at the bottom left hand side. There are 16 remaining lines at
the bottom of the screen which are used by the BASIC operating
system for INPUT, error messages, etc.
These routines may be used if required. However if you wish to
PLOT or PRINT to any part of the screen, including the 16 ‘unusable’
lines, I suggest you use my PLOT routine described in chapter 10 on
the display file.
CHAIRADD- 0E9BH
This routine can be used to find the address on the screen for a
given character line number 1-24. The first line starts at the bottom
of the screen. The B register is LOADed with the line number of which
we want to find the address. After calling the routine the HL register
pair is RErLIRNed with the address of the first character line.

LD B,1
CALL 0E9BH ;find address of line 1

IPIXADD - 22/IAH
This routine is used to find the address of a point on the screen. The
B register is set with Y Co-ordinate and the C register with the x
Co-ordinate, the address of which we wish to find. On REruRNing
from the subroutine the HL register pair contains the screen address
and the A register the bit position of the screen which is 0-7. Note
that this is inverted and refers to the bit sequence left to right, not
right to left. Therefore ifA returns 0 then the leftmost bit, bit seven is
referred to and if A gives 2 then bit five (the third from the left) is
referred to, etc.
98 Using the ROM routines

Beeper routine - 03 B5
The BEEPer routine is called by LOADing the DE register with the
duration, which is the frequency of the note multiplied by the
number of seconds we wish the note to last. The pitch is LOADed into
the HL register pair and we call the BEEPer routine at address 0385 hex.
The notes and their corresponding pitch values are given in the
table below. For example, if we wanted to play middle G sharp for
half a second (i.e. G#4) we would LOAD the DE register pair with
0.5*415=CF hex (415=19E hex), LOAD the I-IL pair with 3FF, and then call
theroufine:

;play middle G sharp


;for half a second
LD DE,0CFH
LD HL,19FH
CALL 03B5H
Table of duration and pitch values for musical notes

Note Freq Dur Pitch Note Freq Dur Pitch


(Hz) (sec) (H2) (sec)
(hex) (hex) (hex) (hex)
C 0 16.35 6868 A 1 55.00 37 'IEF4
C#0 17.32 A
I 628D A#1 58.28 3A " D34
D 0 18.35 SD03 B 1 61.74 3D " B90
D#0 19.44 44‘
I 57CB C 2 65.40 41 TA03
E 0 20.60 -H
52D7 C#2 69.20 45 188C
F 0 21.83 4E2B D 2 73.40 49 "72A
F#0 23.12 49CC D#2 77.76 4D ’;5DC
G 0 24.50 -4.
45A3 E 2 82.40 52 ”49F
G#0 25.96 41B6 F 2 87.32 57 T374
A 0 27.50 3E06 F#2 92.48 5C 125C
A#0 29.14 Iilfi
J-\.\..lL
.4
U ;JI.O \IU'-I=LsJI\—i® 3A87 G 2 98.00 62 T152
B 0 30.87 "E 373E G#2 103.84 67 1057
C 1 32.70 20 3425 A 2 110.00 6E F6B
C#1 34.64 22 3137 A#2 116.56 74 EBB
D 1 36.70 24 2E72 '23.48 7B DB8
D#1 38.88 26 2BD6 130.80 82 CF2
E 1 41 .20 29 295(I 738.56 8A C37
F 1 43.66 2B 2706 146.80 92 B86
F#1 46.24 2E 24D7 155.52 9B ADF
G 1 49.00 31 22C2 "6480 A4 A40
G#1 51.92 33 20CC " " ‘UU('3fiW ‘*"‘F"iI=.ILo&cI.>i-I 174.64 AE 9A8
Using the ROM routines 99

Note Freq Dur Pitch Note Freq Dur Pitch


(HZ) (sec) (Hz) (sec)
(hex) (hex) (hex) (hex)
F#3 1 84.96 B8 91 F A 5 880.00 370 " D3
G 3 196.00 C4 89A A#5 932.48 3A4 '1 B7
G#3 207.68 CF 81 C B 5 987.84 3DB 19C
A 3 220.00 DC 7A6 C 6 1046.40 41 6 “.83
A#3 233 .12 E9 736 C#6 1108.48 454 16C
B 3 246.96 F6 6CD D 6 T 174.40 496 156
C 4 261 .60 105 66A D#6 1 244.1 6 4DC 141
C#4 277.12 115 60C E 6 ’ 318.40 526 12D
D 4 293.60 125 5B3 F 6 1397.1 2 575 11 B
D#4 311 .04 137 560 F#6 7479.68 5C7 109
E 4 329.60 149 511 G 6 1568.00 620 F8
F 4 349.28 15D 4C6 G#6 ’ 661 .44 67D E9
F#4 369.92 "71 480 A 6 T 760.00 6E0 DA
G 4 392.00 "88 43D A#6 1864.96 748 CC
G#4 415.36 19F 3FF B 6 1975 .68 7B7 BF
A 4 440.00 TB8 3C4 C 7 2092.80 82C B2
A#4 466.24 "D2 38C C#7 2216.96 8A8 A7
B 4 493.92 ‘ED 357 D 7 2348.80 92C 9C
C 5 523.20 20B 326 D#7 2488.32 9B8 91
C#5 554.24 22A 2F7 E 7 2636.80 A4C 87
D 5 587.20 24B 2CA F 7 2794.24 AEA 7E
D#5 622.08 26E 2A1 F#7 2959.36 B8F 75
E 5 659.20 293 279 G 7 3136.00 C40 6D
F 5 698.56 2BA 254 G#7 3322.88 CFA 65
F#5 739.84 2E3 231 A 7 3520.00 DCO 5E
G 5 784.00 310 20F A#7 3729.92 E91 57
G#5 830.72 33E 1 F0 B 7 3951 .36 F6F 50

As a demonstration the program below plays a well known tune


which true Spectrum owners should recognise. The program reads a
series of pitch and duration values which are passed to the BEEPer. To
finish the tune we use the byte 0FF hex. If you are really into music a
more sophisticated version of PLAY is given in Chapter 12.
100 Using the ROM routines

Assembler Listing

ORG 320000
BEEPER EOU 03B5H

PLAY:
LD IXIFRERE IPOINT TO START OF HUSIC
GETV: LD L,(IX+0) ;LOAD L NITH LON PART
IOF THE PITCH
LD H,(IX+1) ;LOAD H NITH HIGH PART
IOF THE PITCH
INC H IIF H IS OFF HEX THEN
IEND OF MUSIC
RET Z ISO RETURN
DEC H IRESTORE HIGH PART OF PITCH
LD EI(IX+2) ;LOAD E NITH LON PART
IOF DURATION
LD DI(IX+3) ;LOAD D NITH HIGH PART
;OF DURATION
PUSH IX ISAVE NUSIC POINTER ON
;THE STACK
CALL BEEPER ICALL BEEPER ROUTINE IN
;THE RON
POP IX IRESTORE IX
LD DE,4 ;LOAD DE NITH 4
ADD IXIDE ;AND POINT TO NEXT
IPIECE OF MUSIC
JR GETV ;GET NEXT PIECE OF MUSIC

FRERE:

DEFN 66AH
DEFN 105H
DEFN 5B3H
DEFN 125H
DEFN 56@H
DEFN 9BH
DEFN 5B3H
DEFN 92H
DEFN 66AH
DEFN 105H
Using the ROM routines 101

DEFN 66AH
DEFN 105H
DEFN SBZH
DEFN 125H
DEFN 560H
DEFN 9BH
DEFN 5B3H
DEFN 92H
DEFN 66AH
DEFN 105H

DEFN 560H
DEFN 137H
DEFN 4C6H
DEFN 15DH
DEFN 43DH
DEFN IBBH

DEFN 560H
DEFN 137H
DEFN 4C6H
DEFN 15DH
DEFN 43DH
DEFN IBBH

DEFN 43DH
DEFN 126H
DEFN 3FFH
DEFN 67H
DEFN 43DH
DEFN 0C4H
DEFN 4C6H
DEFN OAEH
DEFN 560H
DEFN 9BH
DEFN 5B3H
DEFN 92H
DEFN 66AH
DEFN IGSH
[l_l_jI;lilIII "

102 Using the ROM routines

DEFN 43DH
DEFN 126H
DEFN 3FFH
DEFN 67H
DEFN 43DH
DEFN 0C4H
DEFN 4C6H
DEFN 0AEH
DEFN 560H
DEFN 9BH
DEFN 5B3H
DEFN 92H
DEFN 66AH
DEFN 105H

DEFN 66AH
DEFN 105H
DEFN B9AH
DEFN OCAH
DEFN 66AH
DEFN ZQAH

DEFN 66AH
DEFN 105H
DEFN S9AH
DEFN 0C4H
DEFN 66AH
DEFN 20AH
DEFN OFFFFH
END

Hexadecimal Listing

7D@0 IDD 21 21 17D IDD I00 l)D


7DG8 I66 O1 241 I38 .25 SE1 O2!
7D10 IJD 56~ I33 IJD EEI BEI I33
7D18 IDD E1 11 O41 EEI 19 18
7D2O IE3 ISA Oéi 055 01 OEI EEI
7D28 01 ~60 OEI 9E! I89 I35 92
7D3fl OE! 6A 06» I85 O1 06- 05
7D38 01 I33 05 I25 01 I05 9E!
Using the ROM routines 103

7D40 0 E13 05 913 I-3 6-A 06> 05


7D48 1 I60 05 37 1 C6 04 Elf)
7D50 01 3D O4 88 I31 60 O5 37
7D58 01 C6 04 SD E11 3D 04 88
7D6fl 1 3D 4 26 01 FF 013 67'
FDOB 0 CED 04 C4 El C6 04 AE
7D7O 00 I50 05 ‘PEI 00 E13 05 9.2
7D78 O0 ISA I36 05 I81 3D 04 1336

7DBO 01 PF 3 67 B0 ZKII) 04 C4
7DBB 00 ca I34 AE 00 60 05 ‘PEI
7D90 BB as 5 92 00 6A 06 05
YDRB 01 BA 0:5 05 01 ‘YA 08 C4
7DAB 0 BA 06 BA 02 6-A <5 055
YDAB O1 SPA 8 C4 I30 ISA 06 BA
7DB@ 0133 FF FF 05 01 6A 06 5
YDB8 1 B3 05 25 I231 60 05 9E!

FDCO 00 E13 O5 9.2 00 OA 06 05


7DC8 1 60 5 37 1 C6 04 SD
7DDO 1 3D 4 88 E11 OI-3 0'5 37
7DDB 01 C6 04 53D 01 3D 04 88
7DEO 01 3-D 04 26 01 FF 03 67
TDEB 0 3D 04 C4 0 C6 04 AE
FDFB I50 0'5 ‘PEI EII-3 E13 I-35 92
7DF8 ISA 6 E15 1 ZED E14 2.6

TAPE LOADING AND SAVING


The following routines can be used in programs to enable the user
to sAvE and LOAD data to cassette. When you sAvE or LOAD data in BASIC
it comes in two parts. The first part is a ‘header’ containing informa-
tion about the file, its name, the length of the file, and its start
address. The two main routines are sAvEDATA, at address 04C2 hex,
and LOADDATA at 0556 hex. These routines are called with the ix regis-
ter pair containing the address where the data is placed or sAvEd
from and the DE register containing the number of bytes we wish to
SAvE or LOAD. We LOAD the A register with 0 if we are dealing with the
header section or 0FF hex if we are dealing with a data block. When
LOADing a file the Carry flag is set when actually LOADing data but it is
reset if we want to VERIFY data.
Below is a set of routines which the programmer can use with the
Cassette.
Hl|| Iii T T T T

104 Using the ROM routines

SAVEBYIES:
LD DE,NBYTES ;number of bytes to save
LD IX,START ;start of block
LD A,0FFH ;saving a data block
CALL SAVEDATA ;save bytes
RET

SAVEHEADER:
LD DE,17 ;save 17 bytes length of header
LD IX,START-OF-H EADER ;point to start of header info
XOR A ;signify header.A=0
CALL SAVEDATA ;save header
RET

LOADBYTES:
LD DE,NBYTES
LD IX,START
LD A,0FFH
SCF ;signify loading
CALL LOADDATA
RET

LOADHEADER:
LD DE,17
LD IX,START-of-HEADER
XOR A
SCF
CALL LOADDATA
RET
VERIFYBYTES:
LD DE,NBYTES
LD IX,START
LD A,0FFH
AND A ;reset carry flag
CALL LOADDATA
RET

VERI FYHEADER:
LD DE,17
LD lX,START—of-H EADER
XOR A ; reset carry flag and
CALL LOADDATA ;set A=0
RET

1-.
Using the ROM routines 105

The following program uses these routines to make backup copies


of most tapes. Please do not infringe copyright by using this to copy
protected tapes!
Assembler Listing

ORG 32000
JP START

NEH EOU 23900


PRXSTRING EOU 203CH

HEBS1: DEFN 22,1,0,‘FILENANE: ‘


SIZ1 ERU 13
MESS2: DEFN 22,3,0,’PROGRAN TYPE: ’
SIZ2 EOU 17
MESS3: DEFN 22,6,0,‘LENGTH: ‘
S123 EOU 11
HESS4: DEFN 22,9,0,’START: ‘
S124 EOU 10
IHESSS DEFN 22,12,0,’BASIC LENGTHI‘
ISIZ5 EOU 16
HAITP: DEFN 22I10I0I' NAC NAITING FOR HEADER. ’
DEFN 22,13,0,’ COPYRIGHT J.K NILSON 1983. ‘
SIZNP EOU 62

TBASIC DEFN iaasrci


TNUH: DEFN ’NUHER‘
TCHAR: DEFN ‘CHARA‘
TCODE: DEFN ’BYTES’
SAVER: DEFN 22I21I0, ‘Do you want a copg?’
SIZO EOU 22
SAVER: DEFN 22,21,0,'Press ENTER when readg.‘
SIZR EOU 26
BLANKH DEFN 22,21,0,‘ '
SIZB EOU 26
106 Using the ROM routines

ERRXSP EOU 23613 ISYSTEH VARIABLE


IERROR STACK POINTER
LOADBTS EOU 0556H ;LOAD BYTES RON ROUTINE
SAVEBTS EOU 04C2H ISAVE BYTES RON ROUTINE

NUNTA: IBASE TEN TABLE


DEFN 10000
DEFN 1000
DEFN 100
DEFN 10
DEFN 1

NUHB: DS 5 INUMBER BUFFER

OUTXNUNI
LD IXINUMTA IPOINT TO TABLE
LD DEINUHB DE POINTS TO BUFFER
DIGIT: LD c.i1x+aI GET LON BYTE OF BASE 10
LD a,i1x+1I GET HIGH BYTE OF BASE 10
LD A,'r'-1 IA REGISTER =30 HEX
AND A CLEAR CARRY
FIN:
INC A CALCULATE NUMBER OF
SBC HLIBC NULTIPLES OF TENS UNTIL
JR NCIFIN CARRY FLAG IS SET
ADD HL,BC IRESTORE NUNBER
LD (DELA PLACE ASCII NUMBER
IN BUFFER
DEC C TEST TO SEE IF FINISED
INC DE IBUNP BUFFER POINTER
JR ZIOUTP IFINISHED OUTPUT NUMBER
TO CURRENT CHANNEL
INC IX POINT TO NEXT
INULTIPLE OF 10
INC IX
JR DIGIT FIND NEXT ASCII DIGIT
DUTPI LD DEINUNB INUHBER BUFFER
LD BC 5 LENGTH OF STRING
CALL PRXSTRING IPRINT IT!
RET ;AND RETURN

1-.
Using the ROM routines 107

IHEAD GETS HEAD INFORMATION FROM TAPE


I17 BYTES OF INFORMATION ARE PASSED TD STARTING ADDRESS IX
INS. DE MUST BE LOADED NITH 17
l

I0—1-2-3-4-5 6 7 O-9-10-11-12—13-14*15-
1 1 1

: _ _ _ - n - _ - -- i-tiill jjjiijiji

ITIIXIIXFILENAMEXIXXXXXIXLENBIXSTRXIIPRGXI
I i j i j j i i 1 it Iijjjliii

iT=TYPE 0 IBASIC PROGRAM


1 I NUMERICAL ARRAY
Ed
1.
2 ICHARACTER ARRAY
3 I BLOCK OF CODE
QI5,‘

IFILENAME :NO MORE THAN TEN BYTES


I
I

;LEN=LENGTH OF CODE IF TYPE 3


I
I

:STR=START ADDRESS OF CODE OR LINE NUMBER


I
II

tPRG=LENGTH OF PROGRAM AREA

HEADER: OS 17

TYP EOU HEADER+0 TYPE OF PROGRAM


FILE EBU HEADER+1 FILENAME
LEN EOU HEADER+11 LENGTH OF CODE
STR EBU HEADER+13 STARTING ADDRESS

HEADIN: SCF SET CARRY FLAG


LD A,0
LD IX,HEADER IX POINTS TO HEADER BUFFER
LD DEI17 17 BYTES OF INFORMATION
CALL LOADBTS LOAD BYTES
RET

HEADOUT:
LD A,0 SET A TO ZERO
LD IXIHEADER POINT TO HEADER
LD DEI17 17 BYTES TO
CALL SAVEBTS
RET
108 Using the ROM routines

SAVECODE:
LD A,0FFH
LD IXIMEM POINT TO RAM
LD DEIILEN) GET LENGTH FROM HEADER
CALL SAVEBTS AND SAVE
RET

LOADCODE:
SCF SET CARRY FLAG
TO SIGNIFY LOADING
LD AIBFFH A REG LOADED NITH
TYPE OF DATA
LD IXIMEM POINT TO START OF CODE
LD DEIILEN) PUT LENGTH OF CODE INTO DE
CALL LOADBTS DO LOADING
RET

CLS:
LD HLI4000H CLEAR SCREEN
LD DEI40@1H
LD BCIB¥32¥24—1
LD (HLLO
LDIR
LD DEIHOME {AND PLACE CURSOR
LD BCI3
CALL PRXSTRING IAT HOME
RET

HOME: DB 22,0,0

DISPLAY:
CALL CLS CLEAR SCREEN
LD DEIMESS1 PRINT FILENAME STRING
LD BCISIZ1
CALL PRXSTRING
LD DEIFILE
LD BCI10 PRINT
CALL PRXSTRING FILENAME

M-__
__.. ,

Using the ROM routines 109

LD DEIMESS2 PRINT TYPE STRING


LD BCISIZ2
CALL PRXSTRING

LD HLITBASIC
LD AIITYP)
LD E;A SAVE TYP IN E REG
SLA 2¥TY
SLA 4#TYP
ADD 4¥TYP+TYP=5#TYP
LD
LD F'P‘F’=>=P s::>rn PUT OFFSET IN DE
ADD HLIDE
IHL POINTS TO STRING
EX DEIHL
LD BC,5 NUMBER OF BYTES TO PRINT
CALL PRXSTRING TYPE

LD DEIMESS3 PRINT LENGTH STRING


LD BCISIZ3
CALL PRXSTRING
LD HL,(LEN)
CALL OUTXNUM NUMBER OF BYTES

LD DEIMESS4 STARTING LINE/ADDRESS


LD BCISIZ4
CALL PRXSTRING
LD HL,(STR)
CALL OUTXNUM
RET

START:
LD SPISTACK
LD A32 OPEN CHANNEL ‘S’
CALL 1601H

ll'lI
110 Using the ROM routines

ERRORS
LD SPISTACK
LD HLIERRSP IERROR STACK
LD (HL)ILON(ERRORS)
INC HL
LD (HL)IHIGH(ERRORS)
DEC HL
LD (23613I,HL

NEXT:
CALL NAITM NAIT FOR HEADER MESSAGE

CALL HEADIN GET HEADER


CALL DISPLAY DISPLAY INFORMATION
CALL LOADCODE LOAD CODE
CALL NANT DOES HE NANT TO SAVE THIS?
JR NZINEXT
ACOPY: CALL SAVEMESS ASK HIM IF HE IS READY
TO SAVE ETC ETC.
CALL HEADOUT OUTPUT HEADER
CALL PAUSE NAIT
CALL PAUSE
CALL SAVECODE SAVE CODE
CALL NANT DOES HE NANT TO MAKE
ANOTHER COPY?
JR ZIACOPY YESINELL MAKE ANOTHER ONE
JR NEXT
NAITM:
CALL CLS CLEAR SCREEN
LD DEINAITP TELL THEM
LD BCISIZNP NE ARE NAITING
CALL PRXSTRING
RET

NANT:
LD DEISAVEO IPROMPT FOR ANSNER
LD BCISIZO
CALL PRXSTRING
Using the ROM routines 111

NAITK: CALL KEY GET KEYBOARD STATUS


JYI
CP
JR ZIRSZ IF YES RETURN NITH A
lg!
CP
JR ZIRSZ ZERO
{NI
CP
JR ZIRSZ-1 INON ZERO
In!
CP
JR NZINAITK
AND A NON ZERO FLAG RESET
RSZ: PUSH AF SAVE FLAGS
BLK: LD DEIBLANKM BLANK OUT BOTTOM MESSAGE
LD BCISIZB
CALL PRXSTRING
POP AF RESTORE FLAGS
RET
PAUSE:
CALL PAUSE2 NAIT A NHILE
PAUSE2: LD HL,0
LD DE,@
LD BCIDFFFFH
LDIR
RET

SAVEMESS:
LD BCISIZR PRINT MESSAGE
LD DEISAVER TO PROMPT FOR ENTER
CALL PRXSTRING
ENT: CALL KEY
CP GDH
JR NZIENT NAIT FOR ENTER
CALL RSZ BLANK OUT BOTTOM SCREEN
RET

FLAGS EOU 23611 ISTATE OF KEYBOARD


LASTXK EOU 23560 ILAST KEY PRESSED
112 Using the ROM routines

KEY:
DEPR:
LD AIIFLAGSI ILOOK AT STATUS OF KEYBOARD
BIT iA
JR ZIKEY INAIT FOR A KEY
ITO BE PRESSED
RES EA
LD (FLAGSIIA
LD A,(LASTXK) ;GET KEY VALUE
RET
DS 100 ISTACK SPACE
STACK: DB 0
ERRSP: DEFN 0 IERROR STACK SPACE

Hexadecimal Listing

YDBB C3 C3 7E 16 01 00 46 4?
7D08 4C 45 4E 41 4D 45 3A 20
7D10 16 03 00 50 52 4F 47 52
7D18 41 4D 20 54 59 50 45 3A
7D20 20 16 06 00 4C 45 4E 47
7D2B 54 48 3A 20 16 09 00 53
7D3@ 54 41 52 54 3A 20 16 BA
7D38 00 20 20 20 20 4D 41 43

7D40 20 57 41 49 54 49 4E 47
7D48 20 46 4F 52 20 48 45 41
7D5@ 44 45 52 2E 20 16 OD BO
7D58 20 43 4F 50 59 52 49 47
7D60 48 54 20 4A 2E 4B 20 57
7D68 49 4C 53 4F 4E 20 31 39
7D70 38 33 2E 20 42 41 53 49
7D7B 43 4E 55 4D 45 52 43 48

-__
Using the ROM routmes 113

7D8E 41 52 41 42 59 54 45 53
7D88 16 15 G8 44 6F 28 79 6F
7D98 75 28 77 61 6E 74 28 61
7D98 28 63 6F 78 79 3F 16 15
7Dfi8 85 58 72 65 73 73 28 45
7Dfi8 4E 54 45 52 28 77 68 65
7DB8 6E 28 72 65 61 64 79 2E
7DB8 16 15 E8 28 28 28 28 28

7DC8 28 28 28 28 28 28 28 28
7DC8 28 28 28 28 29 28 28 28
7DD8 28 28 18 27 E8 83 64 88
7DDB 8A 88 81 88 88 88 88 88
7DE8 88 DD 21 D2 7D 11 DC 7D
7DE8 DD 4E 88 DD 46 81 3E 2F
7DF8 A7 38 ED 42 38 F8 89 12
7DF8 8D 13 28 86 DD 23 DD 23

YE88 18 E6 11 DC 7D 81 85 88
7E88 CD 3C 28 C9 88 88 88 88
7E18 88 88 88 88 88 88 88 88
7E18 88 88 88 88 88 37 3E 88
7E2E DD 21 8B 7E 11 11 88 CD
7E28 56 85 C9 3E 88 DD 21 EC
7E38 7E 11 11 58 CD C2 84 C9
7E3B 3E FF DD 21 5C 5D ED 58

7E48 17 7E CD C2 84 C9 37 3E
7E4B FF DD 21 5C 5D ED 58 17
7E58 7E CD 56 85 C9 21 88 48
7E58 11 81 48 81 FF 17 36 88
7868 ED BB 11 6C 7E 81 G3 88
7E68 CD 3C 28 C9 16 88 88 CD
7878 55 7E 11 83 7D 81 8D 88
7E78 CD 3C 28 11 GD 7E 81 84

7E88 88 CD 3C 28 11 18 7D 81
7E88 11 88 CD 3C 28 21 74 7D
7E98 38 8C 7E 5F CB 27 CB 27
7E98 83 5F 16 88 19 EH 81 G5
7EH8 GE CD 3C 28 11 21 7D 81
7Efi8 88 88 CD 3C 28 24 17 7E
7EB8 CD E1 7D 11 2C 7D 81 88
7EE8 E8 CD 3C 28 29 19 7E CD
114 Using the ROM routines

7EC8 E1 7D C9 31 CF 7F 3E 82
7EC8 CD 81 16 31 CF 7F 21 D8
7ED8 7F 36 C8 23 36 7E 28 22
7ED8 3D 5C CD 81 7F CD 1D 7E
7EE8 CD 6F 7E CD 46 7E CD 8E
7EE8 7F 28 EF CD 46 7F CD 28
7EF8 7E CD 37 7F CD 37 7F CD
7EF8 38 7E CD 8E 7F 28 EC 18
7F88 D9 CD 55 7E 11 36 7D 51
7F88 3E 85 CD 3C 28 C9 11 88
7F18 7D 81 16 88 CD 3C 28 CD
7F18 55 7F FE 59 28 8D FE 79
7F25 28 59 FE 4E 28 84 FE 6E
7F28 28 ED Q7 F5 11 88 7D 81
7F35 19 58 CD 3C 28 F1 C9 CD
7F38 35 7F 21 88 88 11 88 88
7F48 81 FF FF ED 88 C9 81 1A
7F48 58 11 9E 7D CD 3C 25 CD
7F58 59 7F FE 8D 28 F9 CD 28
7F58 7F C9 88 3A 38 5C C8 6F
7F68 28 F8 C8 HF 32 38 5C 38
7F68 88 5C C9 88 88 58 58 88
7F78 88 88 88 85 85 88 88 88
7F78 88 85 85 88 88 88 88 85

7F88 88 58 88 88 88 88 88 58
7F88 88 88 58 55 88 58 88 88
7F98 88 88 88 88 88 88 88 88
7F98 88 88 88 85 88 88 88 88
7FA8 85 88 58 58 88 88 85 88
7FA8 58 88 88 88 88 88 88 58
YFB8 88 88 85 88 88 88 88 88
7FB8 88 58 88 88 88 88 88 88
7FC8 85 88 88 88 88 88 88 88
7FC8 88 58 85 88 88 88 88 88
7FD8 88 88 FE 8D 28 F9 CD 28
7FD8 7F C9 88 38 38 5C C8 6F
7FE8 28 F8 C8 AF 32 38 5C 38
7FE8 58 5C C9 88 88 88 88 88
7FF8 58 88 88 88 88 88 88 88
7FF8 88 88 88 88 88 88 88 88
Usingthe ROM routines 115

FLOATING POINT CALCULATION ROUTINES


The floating point calculator is used by the BASIC interpreter to
handle calculations on floating point numbers and strings. Numbers
in BASlC are represented by 5 bytes. The way these bytes represent a
floating point number is shown in the Spectrum user's manual
(chapter 24).
When the Spectrum is interpreting BASIC calculations it uses some-
thing known as a calculator stack which stores the interpreted calcu-
lation in a series of numbers, strings and operators. The way this line
is interpreted is known as REVERSE POLISH NOTATION or RPN.
Numeric expressions in BASIC consist of operands, variables and
operators or functions. ln an algebraic expression operators are
placed between two operands. For example, in the expression x+v
the operator is +, and the operands are x and Y. The principle of RPN
is to place the operator after the operands. Thus X+Y is written as xv
-l-.
the larger algebraic expression:

A*B+C*D/2

could be written as:

A B * C D 2/ * +

To READ a RPN expression we use the following technique. Reaping the


expression from left to right any values or operands would be
pushed onto a stack. When we arrive at an operand or function the
appropriate number of data is PoPped off the stack and that opera-
tion or function is executed with the data. The ‘new’ value is then
pushed onto the stack. This is repeated until we have reached the
end of the expression:

24*382/*+

For example, for the above RPN expression we go through the opera-
tions shown below. On the Iefthand side of the diagram I have given
the operations we use as we read the expression from left to right.
On the righthand side the current status of the stack is shown. The
top of the stack is the rightmost digit.
116 Using the ROM routines

Operation Stack
stack 2 2
stack 4 2 4
operator
stack 3
stack 8
stack 2 |\-7
operator / -50000
operator SUJUJL»-JLU
operator -11-_|_-1+ léOOOOOOOOOOOD

The answer left on the stack is 20.


The Spectrum has a calculator stack where numbers can be
manipulated in the same way as we would deal with an RPN expres-
sion. Groups of numbers can be pushed onto a stack and routines
can be called to do various operations such as add, subtract and
multiply. We can push numbers onto the stack by calling routines
within the ROM which allow us to SAVE the numbers in 1 byte, 2 byte
or 5 byte form.

STACKA-2D28H
LD A,20
CALL 2D28H ;STACl( NUMBER 20

This routine will convert the one byte number contained in the
Accumulator to its five byte floating format which is then pushed
onto the calculator stack.
There are two other routines which are similar to the last routine.
They allow us to stack a two byte integer in the BC register pair and a
five byte floating point number contained in the A,E,D,C,B registers.
The routine at the address 2D2B hex (STACKBC) will convert a two byte
integer into five byte floating point format and push this on the
calculator stack. Likewise the routine at the address 2AB6 hex
(STACK5) will push the floating point number in the registers A,E,D,C
ands.
To retrieve numbers from the stack we have routines which can
pop them off and convert them into one byte, two byte or the
normal five byte form. The addresses are given below:
UNSTACKA —2D5DH will convert the floating 5 byte number on top
of the calculator stack to its equivalent one byte integer and place it
in the accumulator.
UNSTACKBC —-ZDZAH will remove a five byte floating point number
from the stack, convert it and place it in the BC register pair.
Using the ROM routines 117

UNSTACK5 — 2BF1H. This routine is used to place a floating point


number from the stack into the registers A,E,D,C and B.

There are two routines which are very useful to the programmer
when handling floating point numbers. The routine at the address
2DE3 hex (PRINTFP) will take the top number on the calculator stack
and PRINT it to the current channel selected. The second routine at
2C9B hex (ASCTOFP) enables us to convert a number from a string to a
floating point number which is pushed to the calculator stack. Look
at the following program:

LD HL,STRING ;put to start of string.


LD (5C5DH),HL ;save in system variable CH-ADD
LD A,(HL) ;get first character in A reg.
CALL 2C9BH ;convert ascii number to fp.
CALL 2DE3H ;printfp number
RET
DEFM 2.31693
DB (DDH ;carriage return.

The HL register pair is set up to point to the start of the string. This is
stored in the system variable CH-ADD which usually holds the address
of the next character to be interpreted when Rurvning Spectrum
BASIC. The A register is LOADEC1 with the first character and the routine
ASCTOFP is called. This leaves the binary floating point number at the
top of the calculator stack so when we call the routine PRtNTFP
(2DE3H) the number 2.31693 will be printed out. The end of the
string is signified by a carriage return.
To start the floating point calculator we call the routine at address
28 hex with the one byte instruction RST 28H. The data following the
call instruction indicates which operations the calculator must per-
form. The calculator goes through each operation automatically
pushing and popping data until it reaches the data 38 hex which
signifies the end of the calculation. Some of the most useful codes
are given below:

data Name Action


code
(hex)
01 exchange Swops the two topmost floating numbers.
G2 delete Deletes top number on stack.
03 subtract Subtracts second number on stack from first
84 multiply Multiplies the two topmost numbers.
05 divide Divides the first over the second number.
iv"

118 Using the ROM routines

data Name Action


code
(hex)
06 power Ra'ses the first to the power of the second
1B negate Changes the sign of the top number.
1F sin Caicufates the sine ofthe top number.
20 cos Ca-cu-ates the cosine of the top number.
21 tan Cacul ates the tangent of the top number.
22 arcsin Cacuates the Arcsine of the top number.
23 arccos Calculates the Arccosine of the top number.
24 arctan Cacujates the Arctan of the top number.
25 log2 Ca cuLates the Log of the top number.
26 exp Cafcu'ates the exponential of the top number.
27 integer Calculates the integer of the top number.
28 square root Calcur ates the square root of the top number.
29 sign Places the sign of the top number on stack
2A absolute Converts the top number to its absolute.
2B peek Places the contents of the address at top of stack
2C in Scans address at top of stack.
31 duplicate Duplicate the top of the stack.
38 Endcalc End of calculation.

The calculator has five constants available in the ROM used for cal-
culating sines and cosines:

Data Name Action


code
(hex)
A0 stack 0 Place the number 0 on the stack.
A1 stack 1 Place the number1 on the stack.
A2 stack 1/2 Place the number 1/2 on the stack.
A3 stack Pl/2 Place half of Pl on the stack.
A4 stack 10 Place the number10 on the stack.

There are six memory locations used by the floating point calculator
in order to SAVE numbers on top of the stack. The data codes CU hex
to C5 hex are used to SAVE the topmost number on the stack to one
of the six memory locations. The other codes Etil hex to E5 hex are
used to place numbers from one of the memory locations to the top
of the calculator stack.

I-__
Using the ROM routines 119

Data Name Action

store 0 ace the number on the stack in memoiy 0.


store 1 ace the number on the stack in memory 1.
store 2 ace the number on the stack in memory 2.
store 3 ace the number on the stack in memory 3.
store 4 ace the number on the stack in memory 4.
store 5 ace the number on the stack in memory 5.
Stack mem El ace the contents of memory 0 on the stack.
Stack mem 1 lace the contents of memory1 on the stack.
Stack mem 2 "Z-o'°I .'° _'°ace
."~3"°. the contents of memory 2 on the stack.
Stack mem 3 Pace the contents of memory 3 on the stack.
Stack mem 4 P’ ace the contents of memory 4 on the stack.
Stack mem 5 Pace the contents of memory 5 on the stack.

The following program demonstrates how we use the floating cal-


culator to multiply the numbers 2342 (926 hex) and 156 (9C hex).

LD BC,926H
CALL STACKBC ;STACK NUMBER
LD BC,9CH
CALL STACKBC ;STACl( NUMBER
RST 28H ;START CALCULATION.
DB B4 ;MULT|PLY
DB 38H ;END OF CALC.
CALL PRINTFP ;PRlNT ANSWER
RET

The second example shows us how we can convert fairly complex


algorithms into machine code. lt PLOTS a sine wave on the screen.
The BASIC routine takes 17 seconds while the machine code equiva-
lent takes 14 seconds. The reason why the machine code routine is
not significantly faster is because the sine calculations inside the
ROM are fairly slow.

1n FDR x=o To 255


em LET Y=1@B+5B*SIN(X*PI/23)
so PLOT x,v
4a NEXT x
120 Using the ROM routines

The equivalent machine code program would be:


ORG 9

PLDTXY EBU 22EEH


STACKA EBU 2D28H
UNSTACKA EBU 2DD5H

XDR A ;SET X CD-DRD TD B


SINE PUSH AF ;SAUE X CD—DRD UN STACK
LD Ailflfl ;STACK 196 DECIMAL
CALL STACKA
LD A,5B
CALL STACKA ;STACK SB DECIMAL
PDP AF ;GET X CD-DRD
PUSH AF ;AND SAUE
CALL STACKA ;PLACE X UN FP STACK
RST 28H ;START CALCULATION
DB BASH ISTACK PI/2
DB BA4H ;STACK 15 DECIMAL
DB BSH ;DIVIDE (PI/2 BY 1B)
DB 34H FHULTPLY (FIXED BY X)
DB 1FH ;SINE (SINE(PI¥X/25))
DB 54H FHULTIPLY
;(SB¥SINlPI¥X/26))
DB BFH FADD

i1BB+5B¥SIN(PI¥X/28)
DB 38H ;END DF CALCULATION
CALL UNSTACKA ;GET Y CD-DRD IN A REG
LD B,A ;AND SAVE IN B

PDP AF ;GET X CD—DRD OFF STACK


PUSH AF ;SAUE AGAIN

LD C,A JPLACE X CD-DRD IN C REG


CALL PLDTXY ;PLDT A POINT AT X,Y
POP AF ;GET X REGISTER
INC A ;INCREASE X CD-DRD
RET Z ;DDNE 256 TIMES SD RETURN
JR SINE ;KEEP PLDTTING
END
10 Screen and
attribute handling
The screen display is used in order to communicate information to
the user. To PRINT information to the screen is a fairly simple and
trivial matter in BASIC. However, when we delve into the realms of
machine code accessing the screen becomes more complicated due
to the complex screen lay out. The display file is split into two
sections; the actual screen display file and the attribute file. The
attribute file is easy to access because the data held in this file is
organised sequentially. The attribute file consists of a 32 by 24 byte
array. Each byte contains the information relating to a particular
character position on the screen and tells the Spectrum what PAPER
and INK colours to use for the display and whether the character is
FLASH andror BRIGHT.

The Attribute File


The number to be stored in the attribute file can be calculated by
using the following method:
First set your total to zero.
Add 128 to your total ifyou want it flashing.
Add 64 to your total if you want it bright.
Add 8 times the PAPER colour you want.
Add the INK colour you want.
The value of the colours are:

0 Black
1 Blue
2 Red
3 Magenta
4 Green
5 Cyan
6 Yellow
7 White

if 1-u--rt
122 Screen and attribute handling

The bit pattern of an attribute byte is set up like this:

E I-I‘
-'~\I CFO"- -gm 134:- -go.» _.N _._, _.®

Where f is the FLASH bit, b is the BRIGHT bit, p is PAPER number, i is INK
number. So if, for example, we wanted the colour code for red INK
on white PAPER with the BRIoHTness set on we would put the value
64+8*7+2=122 in the appropriate location.
The address of the start of the attribute file is 22528 or 58% hex. It
can be represented by a grid of 32 column by 24 rows. The start of
the file being in the top left-hand corner. If we wished to find the
address of a given pair of co-ordinates (row O, column O is in the top
left-hand corner), then we could use the following piece of code:

1#118#88¥#¥¥¥¥¥¥$¥¥¥¥$¥¥¥#¥$¥#
; FIND ATTRIBUTE ADDRESS
t B CONTAINS THE ROH NUMBER
3 C CONTAINS THE CDLUNN NUMBER
; ON EXIT HL CONTAINS ADDRESS
CL-ATTR: LD L.B
LD H,D
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL ;FIND ROU TIMES 32
LD B,O
ADD HL,BC ;ADD COLUMN OFFSET
LD BC,58OOH :START OF ATTRIBUTES
ADD HL,BC IADD START OF ATTRIBUTES
RET TADDRESS NOH IN HL
As you can see we multiply the row number by 32 and by a series of
ADD HL, HL instructions. Finally, we add the column offset. This isn't
the quickest way of calculating the address but it is the easiest. if
you read the chapter on shifting and rotating you way wish to
calculate another way of finding the address using bit manipulation.
This routine can be used for PEEI<ing or PoKEing at the attribute file. If
we wanted to look at the contents of a given row and column we
could use the code:
PEEK: CALL CL-ATTR ;CALCU LATE ADDRESS AT
;ROW B,COLUMN c
LD A,(HL) ;PUT CONTENTS IN A REGISTER.

n-_
__-

Screen and attribute handling 123

If we wanted to POKE red INK, green PAPER at column 22, row 5 we


could write the code:

POKE: LD A,22H ;CODE FOR RED lNK,GREEN PAPER


LD BC,O5'l 6H ;SET BC TO ROW 5,COLUMN 22
CALL CL—ATl'R ;FlND ADDRESS
LD (HL),A ;POKE VALUE IN.

The Screen File


The screen file is a little more complicated than the attribute file! lt
consists of three sections of 8 character rows. Each character row is
made up of 32 characters split into 8 pixel lines. Since we are
working with eight bit bytes the resolution of the screen is 256 by
192. The resolution of a screen determines the number of little dots
that make up the data on the screen. The higher the resolution, the
more detailed the pictures on the screen. To determine an address
on the screen for a given pair of co-ordinates is not an easy matter. If
we look at the bit pattern for a screen address:

O10sslll rrrccccc

ss is the section number, O being the top third, 1 being the middle
and 2 the bottom third.3 indicates an address in the attribute file. lll
is the pixel line number (0-7) within a character. rrr is the line
number within a section (0-7) and ccccc is the column number
(O~31).
Using this pattern we can determine an address anywhere on the
screen, even down to one single bit. The section number is con-
tained in the top two bits of the row. The pixel line number is also
contained in the row, this time in the middle three bits. The pixel
line number is the last three bits of the row. The column is repre-
sented by a number 0-255. The range 0 to 255 is used because the
routine is designed to give the address and bit position of any pixel
on the screen. The data for the routine is as follows:

row ssrrrlll
col cccccbbb

where all the letters have their previous meanings and bbb is the bit
position of the pixel.
Now let’s look at the routine to calculate the screen address for
any given row and column. The B register is LOADed with a row
124 Screen and attribute handling

number in the region 0-191, where row 0 is at the top of the screen.
The c register is LoAoed with the column number in the range of
0-255. After executing the routine the HL pair will contain the
address on the screen, and the A register will contain the bit position
(0-7) within that address.

FIND PIXEL ADDRESS


5Q@- B CONTAINS Y COORD
C CONTAINS X COORD
ON EXIT HL CONTAINS ADDRESS
‘WI
EI
flu A CONTAINS PIXEL NUMBER
PIXADD:
LD A,B ;GET Y REGISTER
RRA
SCF
RRA
RRA ;X1x.. MOVE DOHN SECTION
AND SSH TMASK OFF SECTION. OIBSS
LD H.A ;SAVE IN H REG
LD A,B ;GET Y AGAIN.
AND 7 ;HORK OUT PIXEL LINE UITHIN
ICHARACTER
ADD ;ADD PREVIOUS RESULT
LD iSAVE IN H REG
r-CD PF? r: >:
RRCA
RRCA
RRCA

LD IMOVE DOWN COLS O-31


LD ;GET ROU NUMBER
AND ;MASKING OFF ROlvl NUMBER
ADD
ADD
OR
LD
LD In5-1-IyFIIP
n.in
um $$'I@D‘I ;GET BIT NUMBER
\lbI_T"$' l'-h|$|-‘I-1 FA CONTAINS BIT NUMBER
FUD
11>VIZ
ZQ '-I?

This routine could be used to PLOT points on the screen since the
PLOT command in BASIC is limited to accessing only 256 by 176 points.
To do this we call the PIXADD routine then rotate the pixel to the bit

1-.
Screen and attribute handling 125

position we want. S0 our program to PLOT a point at the co-ordinates


in the Bc register pair would be:
I PLOT A PIXEL AT THE COORDINATES
:X.Y
: B=Y COORD AND C=X COORD
PLOT:
CALL PIXADD ;Find address for co-ords BC
LD B,A ;Put bit position in the B
;register
INC B ;nou in the range 1-8
XOR A ;set A to zero and clear
;carrg flag.
PIX:
RRA
DJNZ PIX ;nove pixel dot to position
;required
XOR (HL) ;and place it at the address
LD (HL),A
RET

As seen l have used an Exclusive OR to place the dot on the screen.


This has the effect of turning a pixel on if there wasn't already a dot
at the calculated address or turning the pixel off, if it was already set.
When we PRINT a character onto the screen within a character
boundary the offset for each byte of data which makes up a charac-
ter is 256 so it is a simple matter to have a loop such as:

FDE POINTS TO DATA UHICH HE HANT TO PRINT


FHL POINTS TO SCREEN ADDRESS.TOP OF CHARACTER
IBOUNDARY
LDC B,8 TB BYTES OF DATA
NXTPL: LD A,(DE) ;GET DATA
LD (HL),A IPLACE DATA ON SCREEN
INC DE IPOINT TO NEXT DATA
INC H TPOINT TO NEXT PIXEL LINE
DJNZ NXTPL ;DO NEXT PIXEL LINE

The INc I-I_ instruction is the same as adding 256 to the HL register pair
and has the effect of getting the next pixel line address below. The
offset is always 256 only if we are within a character boundary. If this
is not true we have to use the following routine below which l have
C3HEdlNCYI
126 Screen and attribute handling

INCY:
INC
LD
AND
RET ;lIlITHIN CHAR BOUNDARY
LD
SUB
LD
LD
ADD ? ;w?§~?=IlZ.r~l'-DP-J INEXT CHAR LINE DOHN
HHITHIN SECTION)
JADD 32 DECIMAL
LD L,A
RET NC IDEF HITHIN SECTION
FNEXT SECTION DOWN
LD A,H
ADD A,B
LD H,A
XOR 58H TOIOIIOOO BINARY
RET NZ ;IS THERE A HRAPAROUND
INEEDED?
LD H, ASH
RET

The routine could be written to run a little quicker. It seems a waste


of time to first subtract eight from the H register if we have gone over
a character boundary and then to add eight back. The reason we
have done this is to incorporate a wrap around effect. This means
anything which is printed over the bottom of the screen will appear
on the top.
There is also a relationship between the address of the attribute
file and the screen file. Study the bit patterns for the high byte of the
start of each section on the screen file and the corresponding bit
patterns on the attribute file. The table below shows how the high
bytes of the addresses relate:

screen addr screen bit pattern attr addr attr bit pattern
40 H 01000OOO 58H O10110lilO
48 H 01001 (BOO 59H 016111001
50 H 01010000 5AH 0101101 O

To get the corresponding attribute address from a given screen


address shift down the high byte to the left three times and then set
bits three and four of the high byte.

n-_
Screen and attribute handling 127

ITHIS PIECE OF CODE GIVES


;THE ADDRESS OF THE ATTRIBUTE FILE IN THE
FHL REGISTER PAIR
IFOR A GIVEN ADDRESS ON THE DISPLAY FILE
;IN THE HL REGISTER PAIR.
LD A,H FOIOSSOBO
SRA A ;OO1OSSOO
SRA A TOOOIGSSO
SRA A IBOOOIOSS
OR SOH IOIOIIOSS
LD H,A
RET
ANIMATION

Using the INCY routine we can write another routine which allows us
to PRINT a character at any pixel position on the screen. Usually when
we PRINT a character in BAsIC the character is placed on the standard 32
by 24 grid. Therefore there are only 768 positions at which we can
place that character. If we were to write a game using the BASIC PRINT
statement movement of characters is limited to moving horizontally
eight bits at a time and vertically eight pixel lines at a time. The
following machine code routine will demonstrate how to move
objects around the screen smoothly using pixel movement.
The routine in the ROM which deals with PRINTing characters in BASIC
calculates the screen address for a given pair of co-ordinates. It is
then a simple matter of lacing the eight bytes of data which make up a
character onto the screen. The screen is constructed in such a way
that each vertical line, where the character is to be placed, is 256 bytes
below the last pixel line. However, this offset changes when we are
PRINTing over a character or section boundary. If we wanted to draw a
character on any of the 192 pixel lines we would need to keep using
the INCY routine to find the addresses of successive pixel lines.
Therefore if our character stayed within a character boundary
vertically then the following routine would print a character togthe
screen. The screen address is pointed to by the HL register pair and
the character data is pointed to by the DE register pair.

BOUNDH: LD B, 3 ;GET DATA COUNT


NXC: LD A,(DE) ;GET CHARACTER DATA
LD (HL),A ;AND PLACE ON THE SCREEN
CALL INCY ;NEXT PIXEL LINE DOWN
INC DE ;POINT DE TO NEXT
‘CHARACTER DATA
DJNZ NXC IDO B TIMES
128 Screen and attribute handling

As you can see this portion of code is similar to the first routine we
used to PRINT a character to the screen. The exception is that the INc H
instruction is replaced by calling the routine INCY which calculates
the address of the next pixel line down.
The next problem we have to overcome when PRINTing a character
on the screen is to deal with its horizontal position. When we want
to print an eight bit character, at any of the 256 bits, we may
sometimes overlap between two character boundaries. This means
that if we can calculate the bit position where the object is to be
placed within one of the 32 horizontal positions on the screen we
can scroll the eight bit number which makes up one line of the
character through two bytes which we then PRINT onto the screen.
Look at the following two diagrams. Diagram A shows a space ship
being PRINTed within a character boundary. The data only occupies
one byte for each horizontal line. When we wish to PRINT an eight by
eight bit object at any horizontal pixel position then we could get an
overlap onto the adjacent character position as shown in diagram B.
An overlap will occur seven in every eight horizontal bit positions.
To find a character's bit position simply get it's x co-ordinate and
mask off the bottom three bits by ANDing it with seven. Remember,
that this ‘bit position’ is different from the one we use to describe bit
instructions such as SET,RESET and BIT. This time the bit position starts
from the left hand side of the byte.

-%— Character -2;-I


Boundary
01234567
if T -7

8 by8 pixel character


y within boundary

-__
Screen and attribute handling 129

-"‘=— Character —%---=';—i Character i—'3=-y


Boundary Boundary

8 by 8 pixel character over boundary

If given the bit position in which a character lies, then to obtain its
two byte equivalent, get the object data to be printed and scroll it
from left to right within two bytes. This ‘scrolling’ from left to right
of a 16 bit number is identical to dividing the number by 2. This was
explained in the chapter on rotating and shifting. The following
piece of code divides a two byte number in the A register (the high
part) and the C register (the low part) by 2.
LD C,iil ;clear low byte first
SRL A ;scroll A reg from left to right into carry
RR C ;scroll c register from left to right through
;carIy

Notice how we clear the low byte of the number by I_oAoing the c
register with O. We would of course do this scrolling until we reach
the bit position which we require. Therefore, if the B register con-
tained the bit position we would find the two byte number by using
the code:
3 B REGISTER CONTAINS THE BIT POSTION
LD A,B ;PLACE B REGISTER INTO
;THE A REGISTER
AND A ;TEST FOR BIT POSTION=O

JR Z. BOUND IHITHIN ONE CHARACTER


JBOUNDARY SO DEAL UITH
TTHIS CASE AT LABEL BOUND
130 Screen and attribute handling

LD C,O ;CLEAR RIGHT BYTE FIRST

GETB: SRL A TSCROLL A REGISTER


RR C ;RIGHT THROUGH THE
;C REGISTER
DJNZ GETB ;UNTIL lIlE GET INTO
;THE REOUIRED BIT
JPOSTION

Notice that before we scroll the character we test that the bit posi-
tion is zero. lf the bit position was zero then this means that our
character is within a boundary so we deal with this at the lable
BOUND. If we did not do this and carried on through to scroll the data
then we would find that we would end up scrolling the data 256
times.
After we have our two new characters which make up the object
then it is simply a case of placing them on the screen. If, for
example, the HL register pair was pointing to the screen address
where we wanted to place the character then we would place the
data at HL and HI+1
IDRAIII OBJECT ONTO THE SCREEN
;AT THE ADDRESS IN THE HL PAIR

LD (HL),A ;PLACE LEFT HAND SIDE


;OF THE OBJECT
INC HL IPOINT TO NEXT CHARACTER
;BOUNDARY
LD (HLLC ;PLACE RIGHT HAND SIDE
TOF THE OBJECT

To animate, simply DRAW the object onto the screen and to move it,
remove the object from its previous position. Then update its new
position and DRAW it to the screen. The following machine code
routine DRAWS and animates nine space ships on the screen. Each
one follows a movement pattern. The object can move in any one of
four directions. Direction one indicates that the ship is moving
right, two left, four down and eight up. The movement pattern
DIRTAB is a table of directions which the ship follows and ends with
255 or FF hex. The ships start at different locations in the table so that
the movements are not synchronised.
Each ship has three bytes of data starting from sHIPTB, to represent
its x and Y co-ordinates and an offset position or vector count
Screen and attribute handling 131

pointing to a direction within the movement table. lf a ship had a


starting offset of 12 the first direction it would use is at the address
DIRTAB+12. This contains a one and means that the ship would move
right. When the ship comes to the end of the direction table (sig-
nified by the byte FF hex) it resets its vector count to zero thus
pointing to the first byte of the direction table.
The lY register is used in this routine to point to each of the ships
data. At the start of the program the ships are first drawn onto the
screen. The main routine which deals with drawing characters uses
the ROM routine PIxADD (22AA hex). When given the x and Y co-
ordinates on the screen it will RETURN the screen address in the HL
pair and the A register holds the bit position within Na byte. The
co-ordinates x=0, Y=Ii) start the A register at the left hand side of the
screen 22 lines from the top. Therefore, we only have 176 pixel lines
vertically to which to DRAW the objects. Of course if you wanted you
could us my PIxADD routine which makes full use of the 256 by 192
screen.
Notice in the routine PRTCHR how instead of IoADing in the data
character bytes directly I first exclusive OR the data with the contents
of the screen. This is extremely useful for I can if l wish MOVE over
‘background objects’ on the screen without corrupting the data. It is
like using the OvER 1 command in BASIC. As well as leaving the
background it also serves a useful purpose for effacing the ship from
the screen when Moving it to a new position. Since we are using the
xOR instruction this will turn off any bits that are all ready on and turn
on bits already off.
Assember Listing

MOVEMENT ROUTINE

‘IIInn
\-

I
I
I

IEXAMPLE OF PIXEL MOVEMENT

ORG ZOOOD
JP START ;START THE PROGRAM
132 Screen and attribute handling

SHIP: DB 22,255,22,15,15,22,255,22
IDATA FOR SPACE SHIP

PRINOBJ: ;SUBROUTINE PRINT OBJECT


IPRINTS AN OBJECT AT XIY
TB REG=Y VALUE
TC REG=X VALUE

PUSH BC
CALL PRTCHR
POP BC
RET

PRTCHR: IPRINTS A SHIP ON ANY


;PIXEL POSTION

LD IXJSHIP

CALL 22AAH IFIND PIXEL ADDRESS

iROUTINE AT ZZAAH FINDS THE ADDRESS ON SCREEN FOR A


FGIVEN X,Y CO-ORDS IN C REG AND B REG
;THE A REG IS RETURN NITH THE START OF PIXEL POSTION
TUITHIN THAT BYTE THIS ROUTINE IS ONLY LIMITED FOR Y
FBEING BETHEEN O AND 175 INSTEAD OF THE EXPECTED O~191
FALSO THE CO-ORD BIB START IN THE BOTTOM LEFT HAND SIDE

LD E,A ;SAVE BIT POSTION IN E


IREGISTER
LD D,B TPIXEL LINE COUNT
AND A ;TEST FOR ZERO PIXEL
FPOSTION
JR Z,HBOUND THITHIN BOUNDARY SO JUMP

L__
Screen and attribute handling 133

LINE: LD B,E 5 GET BIT POSTION IN


B REGISTER

:SCROLL DATA B TIMES INTO REGS A AND C


LD A,(IX+B) GET DATA
LD C,O CLEAR RIGHT HAND SIDE

SCROLL:
SRL A SCROLL DATA DOHN TO BIT
POSTION
RR C
DJNZ SCROLL

XOR (HL) MERGE LEFT HAND PART OF


DATA IN!
LD (HLLA

INC HL TO THE RIGHT MARCH!


LD A,C GET SECOND CHAR
ONE: XOR (HL)
LD (HLLA MERGE SECOND CHAR IN.
DEC HL
INC IX BUMP NEXT DATA
CALL INCY FIND ADDRESS OF NEXT
PIXEL LINE
DEC D HAVE HE DONE THE O BYTES?
JR NZ,LINE NO! SO DO NEXT LINE
RET YES THEN RETURN.

HBOUND: LD B,D LOAD B NITH B


(PIXEL LINE COUNT)
XBOUND:
LD A,(IX+O) GET DATA
XOR (HL) MERGE IN NITH DATA
LD (HLLA ALREADY ON THE SCREEN
CALL INCY NEXT PIXEL LINE DOUN
INC IX NEXT DATA BYTE
DJNZ XBOUND REPEAT S TIMES
RET
LIA

134 Screen and attribute handling

INCY: FINDS ADDRESS OF NEXT


PIXEL LINE ON THE SCREEN
INC H
LD A,H
AND 7
RET NZ WITHIN CHAR BOUNDARY
LD A,H
SUB 8
LD H,A

LD
ADD ?’3* oar- hJ=2 NEXT CHAR LINE DOWN
(WITHIN SECTION)
LD L,A
RET NC CHAR WITHIN SECTION

NEXT SECTION DOWN

LD A,H
ADD A,B
LD H,A
XOR BB OIOIIOOO
RET NZ
LD H.4BH WRAP AROUND EFFECT
RET

DIRTAB
DB
DB
DB
DB rrr? were rrr? rrr? rare I"-J-§Il- ‘I-@

DB ever? grrrr -Qrrrrer


PP?P r r @P“-.J-bl-\@“-. _ DIRECTION TABLE

_-__
Screen and attribute handlIng 135

GETDIR
LD HL DIRTAB POINT TO DIRECTION TABLE
LD E (IY+VECTCN) GET SHIPS POINTER
LD
ADD HL DE POINT TO DIRECTION
LD A (HL) GET DIRECTION
CP IFFH IS THIS THE END OF
THE TABLE
JR NZ MOVEIT NO THEN MOVE SHIP‘
XOR SET A TO ZERO
LD (IY+VECTCN) A SET VECTOR COUNT TO ZERO
RET

MOVEIT
INC (IY+VECTCN) INCREASE VECTOR COUNT
FOR NEXT GO
CP GOING UP
JP Z UPD
CP
JP Z DOWND GOING DOWN
CP
JP Z RIGHTD GOING RIGHT
CP
JP Z LEFTD GOING LEFT
RET

UPDAA
CALL PRINOBJ REPRINT SHIP
AT NEW POSTION
LD (IY+XPOS) C SAVE NEW XPOSTION
LD (IY+YPOS) B SAVE NEW YPOSTION
RET

LEFTD
CALL PRINOBJ
DEC
JP UPDAA

RIGHTD
CALL PRINOBJ
INC C
JP UPDAA

‘E
I

136 Screen and attribute handling

UPD:
CALL PRINOBJ
DEC B
JP UPDAA

DOWND:
CALL PRINOBJ
INC B
JP UPDAA

XPOS EBU O XPOS OFFSET


YPOS EOU 1 YPOS OFFSET
VECTCN EOU 2 VECTOR COUNT OFFSET

NUM EOU 9 NUMBER OF SHIPS


LEN EGU 3 LENGTH OF DATA FOR TABLE

ISHIP TABLE
:3 BYTES PER SHIP
FIST BYTE =X CO-ORD
i2ND BYTE =Y CO-ORD
;3RD BYTE =VECTOR COUNT

SHIPTB:
DB 100r10@:B
DB 12BJ8al7
DB 55:45.14
DB 3O,3BI2@
DB 43,3911
DB 130.130,24
DB 14@:14B,2O
DB 140,11B,2
DB [email protected]

1;_
-_|

Screen and attribute handling 137

START:
DI FDISABLE INT
LD B,NUM ;LOAD B REGISTER WITH
TNUMBER OF SHIPS
LD IYISHIPTB IIY POINTS TO START
FOF SHIP TABLE
DRAW: PUSH BC TSAVE SHIP COUNTER
LD B.(IY+YPOS) ;GET Y CO-ORD
LD C,(IY+XPOS) FGET X CO-ORD
CALL PRINOBJ ;AND PRINT
LD DE,3 TDE CONTAINS OFFSET
ADD IY,DE ;POINT TO NEXT SHIP’S DATA
POP BC ;RESTORE COUNTER
DJNZ DRAW TDRAW NEXT SHIP

MOVE:
LD IY.SHIPTB IPOINT TO SHIP TABLE
LD BIND" INUMBER OF SHIPS
NXT:
PUSH BC ;SAVE COUNTER
LD B.(IY+YPOS) ;GET Y CO-ORD
LD CI(IY+XPOS) ;GET X CO-ORD
CALL GETDIR ;GET DIRECTION AND MOVE
LD DE,3 IPLACE OFFSET IN DE
ADD IY,DE ;AND POINT TO NEXT SHIPM DATA
POP BC FRESTORE SHIP COUNTER
DJNZ NXT IMOVE NEXT SHIP
JR MOVE iFOREVER AND SO ON
END

Hexadecimal Listing

ODOO [I3 5D OE 16 FF' OF‘ @F'


éD68 16 FF 16 C5 [ID ISD C1
1-) 1-)
ODYO [I9 DD 21 63 ISD IAA 4'... 4‘.-

ADFB 5F' 16 O8 A7 253 143 ID


ODBB 7E1 OE BE BO IIB CE! I19
ODBB 1O FA AE 77 I23 AEI 77'
6D9O 2E5 DD 23 CD IA8 15 I28
6D9B EEi C9 42 DD 7EI AEY 77'
138 Screen and attribute handling

ODAO CD A8 OD DD 23 1O F4 C9
ODA8 24 7C EO B7 CB 7C DO BB
ODBO O7 7D CO EB OF DB ?C CO
ODB8 OB O7 EE 58 CB BO 4B C9
ODCO O8 B8 BB BB DB BB B8 BB
ODC8 BB OB BB BB B1 B1 B1 B1
ODDO B1 O1 B1 B1 B1 B1 B1 O1
ODD8 G4 B4 O4 B4 B4 O4 B4 O4
ODEB B4 B4 B4 G4 B2 O2 B2 B2
ODEB B2 O2 B2 B2 O2 B2 BE B2
ODFE FF 21 CB OD FD SE B2 1O
ODFB BB 19 7E FE FF QB B5 AF
OEOB FD 77 B2 C9 FD 34 H2 FE
OEBB OB CA 34 OE FE B4 CA SB
OEIB OE FE O1 CA ED OE FE B2
OEIB CA 2O OE C9 CD OB OD FD
OEQB 71 BO FD 7O B1 C9 CD OB
OEBB OD OD C3 1C OE CD OB OD
OESB BC C3 1C OE CD OB OD O5
OE3B C3 1C OE CD OB OD B4 C3
OE4O 1C OE O4 O4 BB 7B EB B7
OE4B 3? 2D BE 1E 1E 14 EB 1E
OESB B1 82 B2 1B BC BC 14 BC
OEEB 7O B2 BC 9O B2 F3 BO O9

OEOB FD 21 42 OE C5 FD 4O O1
OEOB FD 4E BB CD OB OD 11 B3
OE7@ OB FD 19 C1 1E EE FD 21
OE7B 42 OE BO O9 C5 FD 4O O1
OEBO FD 4E OB CD F1 OD 11 B3
OEB8 E8 FD 19 C1 18 EE 1B EO
OEPB OE FE B1 CA ED OE FE O2
OEPB CA 2O OE C9 CD OB OD FD

OEAO 71 BO FD 76 B1 C9 CD OB
OEAB OD ED C3 1C OE CD OH OD
OEBB BC C3 1C OE CD OB OD O5
OEBB C3 1C OE CD OB OD E4 C3
OECG 1C OE O4 O4 BB 78 SO B7
OECB 37 ED BE 1E 1E 14 28 1E
OEDB H1 B2 B2 1B BC BC 14 BC
OEDB 7O B2 BC 9O B2 F3 O6 B9
Screen and attribute handling 139

OEEB FD 21 42 C5 4O O1
OEEB FD 4E B OB 11 B3
OEF OB FD 19 1O FD 1-'31
OEFB 42 OE BO C5 4O 1

There are many improvements that could be made to this routine.


You could easily add other directions, other direction tables and
other characters. In fact if you want to be more ambitious you could
make the objects of variable width and height. In addition improve
the method of placing data on the screen by DRAwing from the
bottom upwards instead of from the top downwards. This method
of DRAwing objects will reduce flicker from the raster by catching the
object as it is being DRAwn. All you have to work out is a routine
similar to INCY but find the next pixel line above for a given screen
address. I do know of a couple of ways to achieve this but l am not
going to spoil your fun by explaining it to you!
2

11 Interrupts on the
Spectrum
Have you ever wished that your computer could execute more than
one program at once? Well, this chapter will explain how, in effect,
you can double the power of your Spectrum by seemingly RI.INning
two programs at once!
Interrupts on the ZBO chip serve similar purposes to those on
other processors. They tell the computer that an external device,
such as a disk drive, printer, keyboard or modem requires some
attention. Take, as an example, the case where we have linked up a
printer printing out data to our computer.
There are two ways of checking whether the printer is ready to get
a character from the microprocessor. The inefficient way is to use a
loop which has a description like this:

WAIT:
IS PRINTER READY?
ANSWER=NO THEN CO TO WAIT

ANSWER=YES THEN GET NEXT CHARACTER: SEND IT


TO THE PRINTER: GO TO WAIT

As you can see the above method ‘polls’ the printer continually to
see if it is ready for the next character. Most of its time is spent in
this loop waiting for the printer, so a lot of CPU time is wasted!
Wouldn’t it be fine if we could continue with other parts of the
program and only send characters when the printer is ready? Well
we can by using interrupts! Your Spectrum uses interrupts to get
characters from the keyboard and update the frames system
variable.
What is happening on a Spectrum is that your computer is run-
ning Spectrum BASIC. Frequently, (1/50 of a second to be precise or
1/68 of a second in N. America) it remembers where it is and what
line it is running. It also recalls what address it is executing in the
ROM or RAM and executes a routine in ROM which scans the keyboard.
After it has done this it will go back to the address it was executing
prior to interruption.

W-i_
Interrupts on the Spectrum 141

On the Z8O processor there are four kinds of interrupts. These


interrupts are split into two categories called non-maskable and
maskable interrupts. We shall be looking at just two of the maskable
interrupts called mode1 and mode 2 interrupts. (maskable means
we can switch the interrupts off Ifwe wish.)
mode 1 interrupts
Every time an interrupt occurs the processor pushes the current
program counter onto the stack and jumps to location 0038 hex.
To exit out of this interrupt we must use a ‘RET’ (return) or ‘RETI’
(return from interrupt) instruction.
This mode of interrupt is actually the one used by the Spectrum
during the scan for a key routine as described above.
mode 2 interrupts
This is the most powerful of the interrupts on the Z80 processor and
is sometimes known as vectored processing.
. In a mode 2 interrupt the programmer can specify up to 128
interrupts for other external devices.
This mode of interrupt revolves round a table which can contain
up to 128 addresses. We can also have more than one table to deal
with other external devices.
The start of a table is always on a page boundary of a 256 byte
section of memory, i.e. OOOH, TOOH, ZOOH, CZOOH, etc. To tell the
processor where the vector table is we LOAD the I (Interrupt) register
with the high byte of the page number. For example if our vector
table was at location COOO hex then we would tell the processor by
executing:

DI ;DISABLE INTERRUPTS
IM 2 ;SET UP INTERRUPT MODE2
LD l,COH ;LOAD l REGISTER WITH CO HEX
El ;ENABLE INTERRUPTS

Note that we only need to specify the high byte as we are dealing
with page boundaries. The second line of code tells the processor
that we want to use mode 2 interrupts. The last instruction turns on
the scanning of interrupts. If we wished to ignore any maskable
interrupts at any time we would use the instruction:

DI ;DISABLE INTERRUPTS

But wait! There is no instruction which allows us to IOAD the I


register directly with a number. We can only LOAD the I register with
the A register. We overcome this problem by using:
142 Interrupts on the Spectrum

LD A,COH ;LOAD THE A REGISTER WITH COH


LD I,A ;AND PUT IT INTO THE I REGISTER.

In interrupt mode 2, when a device causes an interrupt, it provides


an offset data number which is the low byte of the table. The offset
points to a two byte address within the table to which the processor
jumps (after first, stacking its current Program Counter).

TABLE EQU CIIIDDH

IM 2
LD A,CDH
LD I,A ;I REGISTER IS LOADED WITH HIGH
BYTE OF TABLE
El

TABLE: DEFW KEYBROU ;ADDRESS OF KEYBOARD ROUTINE


DEFW ;ADDRESS OF PRINTER ROUTINE
PRINROU

PUT ANY OTHER VECTORS HERE FOR OTHER DEVICES

KEYBROU:

RET
PRINROU:

RET

Now if an interrupt occurs and the data supplied is O then the


processor pushes the current program counter on the stack and
jumps to the address at COIZIDH. If the data supplied was O2 then it
would jump to the address at COD2H which is the printer routine.
What if the data supplied was D1? If that happens a crash is likely
to occur! Do you know why? The programmer has to program the

n-_
Interrupts on the Spectrum 143

device to RETURN a valid data vector with its lowest bit set to zero i.e.
always even!

Now what device can we program to cause an interrupt on a Spec-


trum? How do we program its eight bit vector number? The answer
is we don’t have tool! The Spectrum is not in conventional interrupt
programming. Every 1/5O of a second an interrupt is generated by
the ULA, one of the chips inside the computer. And at the time of the
interrupt the data Off hex is passed to the microprocessor. If in
interrupt mode 2 this will cause a jump to the address of the vector
table Currently pointed at by the I register plus 256 bytes.
Example:

ORG OCOH

INTINT: LD AIBCBH ISET TABLE AT PAGE OCOH


LD I,A ;AND PLACE IN THE I REG
IM 2 ;SET UP FOR INTERRUPT
IMODE 2
EI ;AND ENABLE
RET

ORG OCOFFH ;PLACE VECTOR AT PAGE+OFFH


DEFW INTROU IADDRESS OF
TINTERRUPT ROUTINE

INTROU:
DI TSTOP ANY MORE INTERRUPTS
PUSH HL ESAVE HL
LD HL,5BOflH IPOINT TO THE ATTRIBUTE
TFILE
LD (HL),2S5 ;AND SHOW SOME COLOUR
POP HL IRESTORE HL
JP OOSBH TJUMP BACK TO BASIC.

In our first example we notice that in our interrupt routine we


disable the interrupt. This is only necessary when an interrupt is
longer than 1/5O of a second so that we don’t interrupt an interrupt!
The JP OO38H jump to OO38 hex is the jump to BASIC keyboard scan
routine. This scans the keyboard, updates the frame count and then

‘E
1-1-I-

144 Interrupts on the Spectrum

enables the interrupts. If we didn't wish to RETURN to BASIC then we


would end an interrupt routine with:

El ;ENABLE INTERRUPT
RET ;RETURN FROM INT
OR El
RETI

Due to a hardware quirk in the Spectrum the value of the I register is


limited to certain values O—16 and 32-64. This means that for the 16I<
models we can only have our vector table in the page address O—16
which is ROM!
There is, however, an end of page value which has a two byte
value jumping out to RAM. This is page 28 hex.

LINKING THE INTERRUPT WITH THE RASTER


Re-set your Spectrum and type in the following program:
ORG SOOO

RASTER : HALT
LD A, 1
OUT ( FEH I, A
LD HL, SOOH NIXEXPERIMENTH
IWITH THIS VALUE!

LOOP: DEC HL
LD A, L
OR H
JR NZ, LOOP

LD A, 2
OUT I FEHI, A
JR RASTER

END

Here's a hexadecimal listing of the same program:

ZDBO 76 3E FE 21 BO O5
ZDOB 2B 7D FB 3E O2 D3
7D1O FE 1B |"|'1|IU@C3-_l':|l-1' EIFJQSSE»-I

—;_
Interrupts on the Spectrum 145

When you run the program you should get a BORDER split into two
colours blue and red
The HAIT instruction on the Z80 is used to wait for an interrupt.
The computer will wait at a HALT instruction until some external
device causes an interrupt. In the case of the Spectrum the UIA
causes the interrupt. Therefore, the effect of the HALT instruction is
to wait 1/50th of a second. Of course if we disabled all interrupts by
using the instruction DI then the computer would wait for ever
unless a Non-maskable interrupt (one that can not be disabled) was
activated. In our program we use the HALT instruction to link with the
raster beam to cause a split in the BORDER colour. Objects can be
drawn when the raster is at the top or flying back thus reducing
screen flicker. A lot of game programmers use this technique when
writing fast arcade games.
Try pressing the keys when RUNning this program. Notice how the
BORDERS go up and down. Do you know why? It is due to the
keyboard routine (which is called by the interrupt routine) taking
different lengths of time to execute depending on which keys it
finds pressed.
Every 1/50th of a second the computer reDRAws the screen. The
screen is updated by an election beam which scans across the pixels
turning them on or off if they are set or re-set. The beam starts from
the top left hand side of the screen and scans left to right across
each line. After reaching the bottom the beam (or raster) flys
diagonally back to the top left where it starts to update the screen
again.
Scan lines

/
-——_i-—__
_ _ _—$-
—-

-IiI=__\"I:~ ‘ T

-
in-i"_ ->
'/
__
1'
_'_~\__
V171 T‘

,
—~

_
1-’

‘WP
‘\
\
\ Fly back
TV screen
\
4 fa _ \
II-I-"' i_'— CFC iii;

Interrupts are a powerful feature of the Z80 processor and must be


used with care. It is not always true that the data RETURN for the low
byte of the vector is OFFH if some other device is on the back of the
,-_-i

146 Interrupts on the Spectrum

Spectrum. When an interrupt occurs with a Kempston joystick on


the Spectrum the data on the databus is the actual data returned
from READing the joystick. In order to overcome this problem we
could fill our vector table with an address in which the low and high
bytes are the same: 8080h 7777h 1616h.
Remember that on the interrupt the PC register will jump to the
location in the table. We could put our interrupt routine at that
address or have another jump instruction. Unfortunately, because
of hardware problems limiting the value of the I register, this
method is impossible on the 16K model Spectrums.
We'll now give you listings for two routines that use interrupts.
The first is a TRACE program that can be used to help you debug BASIC
programs. Every 1/50th of a second an interrupt occurs causing the
transfer of the program counter to address 38 hex. This is where the
keyboard is scanned and other ‘housekeeping’ tasks performed. We
can cause the interrupt transfer to point to a routine which looks at
the system variables PPC and SUBPPC. These contain the line number
and statement number which BASIC is currently executing. PRINTing
the values of these variables to the screen tells the BASIC programmer
which statements the program is interpreting and the sequence of
execution. This provides an extremely valuable aid for mapping the
flow of the program, which in turn can greatly assist debugging.
This is not like the true TRACE functions found on some other
computers since we can only see what line we are executing every
1/50th of a second. Some of the faster BASIC statements could be
missed. The trace function is enabled by typing the instruction RAND
USR3233O and disabled by typing RAND USR 32333. When you are running
BASIC and the trace function is enabled then the line you are execu-
ting at the time of the interrupt is displayed on the top left hand side
of the screen. To slow BASIC down as it is executing with the TRACE
function press the ‘Q’ key. This is most useful as it sometimes gets
difficult to see the line numbers being PRINTed.
Assember Listing

ORG 323390

ITRACE ROUTINE
FFOR 16K SPECTRUM

ZEROADD EOU 15368 }ADDRESS FOR NUMERIC DATA


PCC EOU 23621 TLINE NUMBER EXECUTED
Interrupts on the Spectrum 147

SUBPCC EOU 23623 STATEMENT WITHIN LINE

LD ma2: LOAD A WITH 2OH


LD 313* m-rs AND PLACE IN THE
I REGISTER
IM 2 SET UP INTERRUPT MODE 2
EI AND ENABLE
RET

TROFF IM 1 INTERRUPT MODE 1


RET

ORG 7E5CH INTERRUPT ROUTINE


STARTS HERE

TRACE DI
PUSH AF SAVE REGS
PUSH BC
PUSH DE
PUSH HL
PUSH IX

LD HL,(PCC) LOAD PROGRAM POINTER


LD A,H
INC A
JR Z,SKIP

LD DE,163B4
CALL CONV PRINT NUMBER ON SCREEN
INC DE

LD A,(SUBPCC) GET SUB—LINE NUMBER


ONE BYTE NUMBER
LD H,D , AND TRANSFER TO
HL REGISTER PAIR
LD L,A
CALL CONV2
148 Interrupts on the Spectrum

LD A,BFBH

IN A,(OFEH)
RRA
JR C,SKIP

CALL WAIT
CALL WAIT
SKIP:
POP IX
POP HL
POP DE
POP BC
POP AF
JP BO3BH

WAIT: LD HL,BC
LD DE,OO
LD BC,OO
LDIR
RET

PRDIGIT HL POINTS TO SCREEN


ADDRESS
A CONTAINS DIGIT
NUMBER O-9

PUSH DE SAVE REGISTERS


PUSH BC
PUSH IX
PUSH HL

LD PUT CHARACTER OFFSET


LD f'EF m-ca IN HL REGISTER

ADD HL,HL MULTIPLY BY O


ADD HL,HL
ADD HL,HL
-—

Interrupts on the Spectrum 149

EX DE,HL
LD IX,ZEROADD ;POINT TO START OF
NUMERIC DATA
ADD IX,DE ADD OFFSET TO START OF
NUMBER
EX DE,HL
LD B,O SET COUNTER

NXDAT LD A,IIX) GET NUMERICAL DATA


LD (DELA PLACE ON SCREEN
INC D ADJUST SCREEN ADDRESS
INC IX ADJUST DATA POINTER.
DJNZ NXDAT DO NEXT DATA

POP HL
POP IX
POP BC RESTORE REGISTERS
POP DE
RET

DECT2
DEFW IOBO
DECT3 DEFW IOO
DEFW 1O
DEFW 1
CONV2
LD IX,DECT3
JR NDIG2
CONV: LD 1x.nEcr2
NDIG2 LD B,<1x+1>
LD c.r1x+rI
LD A,‘G’—1
AND A
CAR: INC A
SBC HL,BC
JR NC,CAR
ADD HL,BC
CALL PRDIGIT
INC DE
INC Ix
150 Interrupts on the Spectrum

INC IX
DEC C
JR NZ, NDIG2
RET

END

Hexadecimal Listing

7E4A 3E 28 ED 47 ED EIE FE! C9


7E52 ED SO C9 OB B BB BB BIZ!
7EEA BE! OB F3 F5 C5 D5 E5 DD
7EO2 E5 2A 45 SC 7C 3C 2B 1D
7EOA 11 OB 41-El CD CE 7E 13 3A
7E72 47 SC 2O BB OF CD CB 7E
7E7A 3E FE: DB FE 1F 3B BO CD
?EB2 9B 7E CD 9B 7E DD E1 E1

7EBA D1 C1 F1 C3 38 BB 21 BB
7E92 BB 11 BB B1 BO BB ED
7E9A BB C9 D5 C5 DD E5 E5 2O
7EA2 BO OF 29 29 29 E Ei DD 21
7EAA BB 3C DD 19 EB O B DD
7EB2 7E BB 12 14 DD 23 1O F7
7EBA E1 DD E1 C1 D1 C9 EB 3
7EC2 O4 BB BA B B1 BO DD 21

7ECA C2 7E 18 B4 DD 21 CO YE
7ED2 DD 4O 1 DD 4E BO 3E 2F
7EDA A7 3C ED 42 3 FB O9 CD
7EE2 9C 7E 13 DD 23 DD 23 BO
7EEA 2O EO C9 CD CE 7E 13 3A
7EF2 47 SC 2O BB OF CD C8 7E
7EFA 3E FB DB FE 1F 38

The second of our two interrupt driven routines allows us to have an


on-screen clock constantly telling us the time, even when we are
RUNning a BASIC program. After placing the machine code routine in
memory key in the BASIC listing below. This sen/es to set the time on
the clock. After RUNning, the BASIC program clock should be con-
stantly updated on the top right hand side of the screen. You can
stop the clock at any time by entering NEW. This disables the clock by
re-setting the interrupt mode to 1, thereby causing the Z8O to
Interrupts on the Spectrum

branch off to 38 hex on every Interrupt To start the clock off again
simply type RANDOMIZE USR 32330
BASIC Listing
12! CLEAR 32325 LET T=Z243B
IMO INPUT HDURS";H LET H=INT(H
I :IF7 H{B DR H 12 THEN ED TD LB
EH3 INPUT HINS ";H LET H=INT(M
I: IF' Hifl DR H 59 THEN BO TD 3B
14B IF H29 THEN LET H=H+O
E53 IF Hf? THEN LET M=H+O*IMT(M
K13}
OE! PDKE T,H PDVE T+1,H'PDKE T+
2,B:HANDDMIZE USR 3233B

Assembler Listing

ORG 323380

ICLOCK ROUNTINE
IFOR 16K SPECTRUM

TRON:
LD A,2BH SET UP I REGISTER
LD TO PAGE 28 HEX
IM SET INTERRUPT MODE 2
EI AND ENABLE
RET

FRAMES:
DB

ORG 7E5CH START OF INTERRUPT ROUTINE


CLOCK:
DI DISABLE INTERRUPTS
PUSH SAVE REGISTERS ON
PUSH THE STACK
PUSH
PUSH
PUSH

LD A,(FRAMES) UPDATE 1/SO SECOND


UNTER
-q--— _

152 Interrupts on the Spectrum

A
(FRAMES),A
SO IHAVE WE COUNTED THROUGH
:1 SEC?
NZ,PRCLOCK iNO,SO PRINT TIME ANYWAY

A ;GET FRAMES
(FRAMES),A ;TO ZERO.

DE,TIMLIM ;GET BCD TIME LIMITS


HL,SECS IPOINT TO TIMER COUNTERS
B,3 ;NUMBER OF COUNTERS TO
IUPDATE.

NXBCD: I I"' '1-I ;GET TIME COUNTER


3:3“ |,_‘-I5 TINCREASE BY ONE
;BCD
(HLLA
A,(DE) ;GET LIMIT
(HL) FHAVE WE REACHED LIMIT FOR
ITHAT TIMER?
NZ,PRCLOCK
INO SO GO AND PRINT TIME.
(HLLO RESET TIME COUNTER
INC DE POINT TO NEXT TIME LIMIT
DEC HL POINT TO NEXT TIME COUNTER
DJNZ NXBCD ;DO NEXT DIGIT

IAT THIS POINT THE HOURS ARE RESET TO ZERO.

INC HL I POINT TO HOURS DIGIT


(HL) TSET TO 1 O’CLOCK

PRCLOCK
IROUTINE TO PRINT THE CLOCK ON THE SCREEN

HL,10384+31-O ITOP RIGHT HAND CORNER


LD DE,HRS IDE POINTS TO BCD DIGITS
LD B,3 ; COUNTER
—-I-

Interrupts on the Spectrum 153

NXT: LO A,(DE) GET DIGIT


LD C,A SAVE IN C REG
AND OFBH GET FIRST DIGIT
RRCA MOVE DOWN TO BITS O-3
RRCA
RRCA
RRCA
CALL PRDIGIT PRINT DIGIT.
INC HL IPOINT TO NEXT PART
SOF SCREEN
LD A,C ;GET DIGIT
AND OFH IMASK OFF BOTTOM 4 BITS.
CALL PRDIGIT PRINT DIGIT
INC DE POINT TO NEXT
TWO BCD DIGITS.
INC HL TONE SPACE BETWEEN DIGITS.
INC HL
DJNZ NXT TDO NEXT DIGITS

POP IX ;RESTORE REGISTERS


POP HL
POP DE
POP BC
POP AF
JP BO3OH

TIMLIM: DB OflH,OOH,13H
HRS: DB I
J

MINE: DB
SECS: DB i
.II

ZEROADD EOU 15744 IADDRESS OF START OF


INUMERIC DATA
PRDIGIT:
HL POINTS TO SCREEN
ADDRESS
A CONTAINS DIGIT
NUMBER O-9

PUSH HL TSAVE REGISTERS


PUSH BC
154 Interrupts on the Spectrum

SLA FMULIPLY DIGIT BY B


SLA Db
SLA A
LD B,O ;GET OFFSET
LD B,A ,‘IN BC REGISTER
LD IX,ZEROADD FPOINT TO START OF
ENUMERIC DATA
ADD IX,BC IADD OFFSET TO START OF
INUMBER

LD B,8 TSET COUNTER

NXDAT LD A.(IX) ;GET NUMERICAL DATA


LD (HL),A IPLACE ON SCREEN
INC H TADJUST SCREEN ADDRESS
INC IX IADJUST DATA POINTER.
DJNZ NXDAT TDO NEXT DATA

POP BC IRESTORE REGISTERS


POP HL
RET

END

Hexadecimal Listing

7E4A 13E J28 IED 47' IED 5Ef FE! C9


7E52 GET OE! OEI OE! ISO OO IBO OE!
7E5A ISO ISO IE3 IE5 I35 IDS EEI IDD
7EO2 Efii ISA E52 7EI 3E1 I32 52! 7E:
7EOA FEI I32 221 1D AF' I32 52! 7E
7E72 11 I33 17E 21 I38 7E BO I33
7E7A .7E IIO O1 27 77' 1A BEI ZEO
7EB2 OE? I3O IBO 13 2E! IO F1 I23
7EBA 34 21 17 '4O 11 BO 7E1 OO
7E92 I33 1A ~4F IEO ISO OF' OF OF'
7E9A OF' IID I39 7Ef .23 79 EO OF'
7EA2 IID E19 7E 13 I23 23 1O ES’
7EAA IDD E1 E1 D1 C1 F1 I33 3B
7EB2 OEI ISO IOO 13 ISO ISO ISO E5
7EBA [I5 CE: 2?’ CB 27 CE? 27' OO
7EC2 SE1 4F‘ IJD 21 BO 3D IJD O9
-Iqu

Interrupts on the Spectrum 155

7ECA B6 BB DD 7E 9G 77 24 DD
7ED2 23 18 F7 C1 E1 C9 BB 68
7EDA EB BB F3 F5 C5 D5 E5 DD
7EE2 E5 3A 52 7E 3C 32 52 7E
7EEA FE 32 2G 1D AF 32 52 7E
7EF2 11 B3 7E 21 B8 7E Q6 B3
7EFA 7E C6 B1 27 77 lfi
12 Machine code
miscellany
ln this final chapter, l present a complete machine code game and a
variety of routines. You can use these to enhance your BASIC programs
or incorporate into your own machine code programs. The tech-
niques we've seen in the course of the book are all represented here.
Study of the programs should help you in writing your own and will
increase your repertoire of routines and your program library.

BRICKOUT

This version of a venerable arcade game is one of my favourite


programs. There is no better way to become proficient in machine
code than by writing games. The object of this game is to knock three
layers of 32 bricks away from the top part of the screen. The player
controls a bat and directs a ball moving along the screen to knock
down the coloured bricks. If the ball passes the bat then the player
loses a life. The game ends when the player loses all his lives. The
game listing has been broken into sections and heavily annotated to
help you see the structure of the program.
The bat is controlled by the <z> and <x> keys which make it move
left or right respectively. The <CAPS s|—||Fr> key can be used to make
the bat go twice as fast, (a ‘Cheat Key’ if you likel). The game program
comes in two parts. One is in BASIC and the other in machine code. To
start the game after entering the code you RUN the BASIC program
which calls the machine code routine. When the player has lost the
score is printed on the RETURN to BASIC as the variable sc and the user is
asked if he wants another game. Here's the BASIC program:
16 PRINT #B;"pres5 a key when
ready"
2B IF INKEY$="" THEN BU TD EB
32 CLS
49 RHNDDHIZE USR SBBBB
45 PLOT 3,175: DRAW 255,3: FLU
T @,B: DRAM 9,175
SE GD TD 13

ii
Machine code miscellany 157

The machine code routine comes in three main sections. The first
initializes the score, the number of bricks left, the number of balls
left and draws the screen. The second routine, MO\/BAT, moves the
user’s bat, controlled by the <z>, <><> and <CAPS sHiFr> keys. The
last routine, MUBALL, deals with moving the ball around the screen,
knocking out bricks, rebounding off the bat and walls, and updating
the score. We’ll break down the assembler listing, and give the
whole hexadecimal listing at the end.
To start off the game we jump into the portion of code labelled
START. This follows the initialisation:

ORG 32636
JP START
BATYX: DEFH 16BFH ;EfiTS POSITION
BHLLX: DB IOH ;BALLS X POSITION
BALLY: DB OIH ;BALLS Y POSITION
TPBLYX:
DEFN ;TEHP AREA
XIHC: DB ;X MOVEMENT
YIHO: DB ;Y MOVEMENT
LEVEL: DB . |:;i- I-1-G ;LEVEL
;NUHBER OF HALTS FOR DELAY
SCORE: DEFH B ;SCORE
BALLS: DB O ;NUHBER OF BALLS
HITS: DB B ;NUHBER OF BRICKS HIT

PATTBL:

SPACE: DB O, B, O, O, O, ,B, B

FDATA FOF.‘ BQLL

EIALLCH: DB 3CH, 7EH, OFFH, BFFH, FFH, BFFH, 7EH, 3CH


I ,,-__.-l.

158 Machine code miscellany

FDATA FOR BAT

BATCHS: DB 3FH,7FH,BFFH,OFFH,BFFH,OFFH,7FH,3FH
DB BFFH,OFFH,BFFH,BFFH,BFFH,5FFH,OFFH,OFFH
DB BFCH,OFEH,BFFH,OFFH,@FFH,BFFH,@FEH,GFCH

IDATA FOR BRICK

BRICK1: DB OFFH,B1H,31H,B1H.B1H,B1H,B1H,OFFH

START:
LD A,2
CALL 16fl1H :OPEN CHANNEL THO
XOR A :SET A REGISTER TO ZERO
OUT (BFEH),A :SET BORDER TO BLACK

LD HL,O :RE-SET SCORE TO B


LD (SCORE),HL
LD A,5
LD (BALLS),A :SET NUMBER OF BALLS TO 5
LD A,4
LD (LEVEL),A
LD A,96 ;NUNBER OF BRICKS
LD (HITS),A ;PLACE IN HITS
CALL SETUP ISET UP BRICKS ON SCREEN
CALL RNOBAL IPLACE THE BALL ON THE
JSOHEHHERE ON THE SCREEN
LD HL:161OH FINTIALIZE BATS X,Y CO—ORDS
LD (BATYX),HL
CALL PRTBAT ;AND PRINT THE BAT

BATAON:
LD A,(BALLS) ;LOOK AT THE NUMBER
IOF BALLS LEFT
AND A ;IS IT ZERO?
JR Z,GNOVER :IF IT IS BO TO
IDEAL NITH END OF SAME
TUE ARE STILL PLAYING
CALL NOVBAT ;NOVE BAT
CALL NUBALL FNOVE BALL

¥
--

Machine code miscellany 159

EI
HALT IHAIT FOR 1/5O OF A SECOND
DI
JR BATAGN FKEEP PLAYING

GMOVER:
LD BC,(SCORE) :PASS SCORE TO
;BC REGISTER PAIR
EI ;ENABLE INTERRUPTS
RET :AND RETURN TO BASIC

The games ends when there are no balls left, which causes the
routine to jump to the label GMOVER. This gets the current score and
places it into the BC register pair to be passed back to BASIC.
MOVBAT is used to control the movement of the bat according to
the keys <Z> or <x> being pressed. lf the user presses the key
<CAPS si-||Fr> then the routine goes back to the label F|VE,9lD to move
the bat again.
A call is made to either RIGHTTB or LEI-TTB to move the bat right or
left. After this the routine RETURNS to move the ball.
MOVBAT:
:MOVE PLAYERS BAT

CALL PRTBAT IPRINT BAT

LD A, BFEH :SET UP TO SCAN BOTTOM


IN A,(BFEH) :LEFT HAND SIDE OF KEYBOARD
AND 1FH :MASl'( OFF LONER FOUR BITS
CP 1FH ;SEE IF ALL BITS ARE SET
RET Z :NO KEY PRESSED SO RETURN

CALL CLRBAT ICLEAR BAT OFF SCREEN


FIVE9B:
BIT IIF PRESSED ‘Z’
CALL FTB :THEN MOVE LEFT
BIT IIF PRESSED ’X’
CALL rnI-I GHTB ;THEN MOVE RIGHT
BIT .F‘I" ‘4'I":>.1rJ":‘>r-:|> IHAVE HE PRESSED SHIFT
JR NZ,BATPRT :NEY?IF NOT JUST PRINT BAT
SET B,A
JR FIVE9@ ;TURN OFF SHIFT KEY
THAVE ONE MORE GO
160 Machine code miscellany

BATPRT:
CALL PRTBAT iPRINT BAT ON SCREEN
RET ;AND RETURN

When moving the ball left or right a check must be made to make
sure that the bat does not go off the screen. The variable BATXY holds
the X,Y co-ordinate of the left hand side of the bat. The bat is made
up of three characters.

RIGHTB:
PUSH AF iGOING RIGHT, SAVE AF PAIR
LD HL, ( BATYX ) ;GET X,Y CO-ORD OF BAT
:IN HL PAIR
LD A,1DH ;LOAD A REGISTER NITH 29
CP L ;TEST TO SEE IF NE HAVE
THIT THE RIGHT SIDE
JR Z,REDGE :HIT,SO DON'T UPDATE
INC L :INCREASE X CO-ORD
LD (BATYX),HL ;AND SAVE
REDGE:
POP AF IRESTORE KEY STATUS
RET ;AND RETURN

LEFTB:
PUSH AF TGOING LEFT, SAVE KEY STATUS
LD HL,(BATYX) ;GET X, Y CO-ORDS
LD A,L :TEST IF HIT LEFT HAND SIDE
AND A :IE IF EQUAL TO B
JR Z,LEDGE ;HIT SO DON'T UPDATE
DEC L iOECREASE ONE OFF X CO~ORD
LD (BATYX),HL ;AND SAVE
LEDGE:
POP AF IRESTORE KEY STATUS
RET ;AND RETURN

The routine CLRBAT is used to remove the bat from the screen. To do
this we PRINT the character SPACE which consists of zeros. While the
routine PRTBAT is used to PRINT the bat to the screen. Both these
routines call the routine PRTCH which PRINTS the character held in the
A register. In this routine a can is made to two ROM routines. The
routine at 0E9E hex calculates the screen address for a given Y co-
ordinate. The routine at the address GE88 hex calculates the attribute
in the DE register pair for a given screen address.

l__
Machine code miscellany 161

CLRBAT:
PUSH AF , SAVE AF REGISTER
LD HL,(BATYX) GET X Y CO-ORD
LD BC,33BH SET INK AND PAPER
HHITE PAPER BLACK INK
CLRIT B REGISTER IS
LOADED NITH 3
PUSH BC SAVE CHAR CODE
PUSH HL SAVE X Y CO-ORD AND
COUNTER
XOR A SET A TO ZERO
CALL PRTCH PRINT SPACE
POP HL RESTORE X Y
INC L POINT TO NEXT CHAR OF
POP BC RESTORE X Y CO-ORD
AND COUNTER
DJNZ CLRIT RUB OFF 3 CHARACTERS
POP AF RESTORE AF REGISTER
RET

PRTBAT:
LD HL,(BATYX) GET X Y CO-ORD
LD BC,339H SET B=3 AND COLOUR TO
HHITE PAPER AND RED INK
LD A,2 . INTIALIZE A REG TO FIRST
CHARACTER OF BAT

NEXBAT:
PUSH BC , SAVE COLOUR AND COUNTER
PUSH HL , SAVE X Y CO-ORD
CALL PRTCH PRINT PART OF BAT
INC A 1 NEXT PART OF BAT
POP HL , RESTORE X Y
INC L I NEXT X POSTION OF BAT
POP BC J RESTORE COUNTER AND COLOUR
DJNZ NEXBAT DO 3 TIMES
RET AND RETURN

PRINTCHAR:
:H=Y L=X A=CHAR NUMBER C=COLOUR
wP"**

162 Machine code miscellany

PRTCH:
PUSH AF
PUSH BC SAVE CHARACTER
PUSH HL SAVE COLOUR
SAVE X,Y CO*ORDS
PUSH BC
PUSH AF SAVE COLOUR
PUSH HL SAVE CHARACTER
SAVE X,Y CO~ORDS
LD A,H
CALL BEPEH LOAD A NITH Y CO-ORD
POP DE CALCULATE SCREEN ADDRESS
LD D,H PLACE X CO-ORD IN E REG
ADD HL,DE PLACE O IN D
EX DE: FIND SCREEN ADDRESS
AND PLACE IN DE
POP AF GET CHARACTER CODE
LD BC,PATTBL ;BC POINTS TO CHARACTER SET
LD H,D LOAD H NITH A
LD L,A LOAD A NITH CHARACTER
NUMBER
ADD HL,HL TIMES BY 2
ADD HL,HL TIMES BY 4
ADD HL,HL TIMES BY B
ADD HL,BC ADD CHARACTER
TABLE ADDRESS
HL NON POINTS
TO CHARACTER DATA
LD B,S LOAD B HITH DATA COUNT

NXTROH:LD A,(HL) GET CHARACTER DATA


LD (DELA AND PLACE ON SCREEN
INC HL POINT TO NEXT CHARACTER
DATA
INC D POINT TO NEXT PIXEL
LINE ON THE SCREEN
DJNZ NXTROU DO THIS UNTILL
NE HAVE FINISHED
PRINTING THE CHARACTER
EX DE,HL LET HL NON BE
THE SCREEN ADDRESS
CALL BEBBH CALCULATE THE
ATTRIBUTE ADDRESS
POP BC RESTORE COLOUR CODE

#1
-i

Machine code miscellany 163

LD A,C :PLACE IN A REGISTER


LD (DE),A :SET ATTRIBUTE
POP HL :RESTORE X,Y CO-ORD
POP BC :RESTORE COLOUR CODE
POP AF :RESTORE CHARACTER
RET IRETURN FROM PRINTING

The routine SETUP is called only once: at the start of each new game.
It is used to draw the bricks on the screen.

ISET START SCREEN

SETUP:
CALL BD6BH ICLEAR SCREEN
LD BCIZBZBH :32 GREEN BRICKS
LD A,5 IPLACE BRICK CHAR IN A REG
LD HL,3BflH ;START X,Y CO-ORD OF BRICKS
CALL NXCOL ;DRAH BRICKS

LD BCIZQIBH FCOLOUR =1BH MAGENTA


LD HL.4OOH =4 4 X=
CALL NXCOL :DRAU BRICKS

LD BC,2@3BH :COLOUR =3@H YELLON


LO HL,5BBH =5,X=O

NXCOL:
CALL PRTCH TPRINT BRICK
INC L IPOINT TO NEXT X CO-ORD
DJNZ NXCOL iREPEAT 32 TIMES

RET FRETURN

PEEK is the routine which is used to detect any collision between the
ball and any bricks or the bat. The x and Y co-ordinates are placed in
the HL pair and after cALLing this routine the attribute or colour code
is RETURN€d in the A register.

— W . -II
164 Machine code miscellany

PEEK:
;RETURNS ATTRIBUTE
:OF GIVEN X,Y (IN HL PAIR)
:IN A REGISTER
LD A, L :PLACE X CD~ORD
:IN A REGISTER
LD L, H :PLACE Y CG—GRD
;IN L REGISTER
LD H, G :32 BIT NUMBER SD
:PLACE G IN H
ADD HL,HL ;TIMES BY 2
ADD HL,HL :TIMES BY 4
ADD HL,HL ;TIMES BY 8
ADD HL,HL :TIMES BY 16
ADD HL,HL :TIMES BY 32
LD B.G ;LOAD B REG HITH G
LD C,A IPLACE X CO-ORD IN C REGISTER
ADD HL,BC IFIND OFFSET
LD BC,5BOOH
ADD HL,BC TCALCULATE ATTRIBUTE
FADDRESS
LD A,(HL) ;GET CONTENTS OF
FTHAT ADDRESS AND PLACE
;IN A REGISTER
RET TRETURN

BRKOUT deals with the ball colliding with an object. It determines


which coloured brick (if any) it has hit and gives an appropriate
score. When the ball hits a brick the variable HITS is deducted by one
to keep a count of the number of bricks still left standing. It
branches off to NOEND if any are still left.
If all the bricks are knocked down then the routine will reset the
number of bricks by LOADing the variable HITS with 96 (i.e. three rows
of 32 bricks). The player is rewarded by a bonus of two balls and the
variable LEVEL is decreased. This controls the delay when moving the
ball, thus increasing its speed for the next game.
BRKOUT:
FBRICK HAS HIT SOMETHING DO A TEST

LD BC. O
CP 39H ;HAVE HE HIT A YELLOH BRICK
JR NZ, NTYLN :NOT YELLOH
Machine code miscellany 165

LD A,—1 SEND BALL IN OTHER DIRECTION


LD (YINC),A
LD BC,2 ADD TO SCORE
JR BEEP AND MAKE A NOISE ABOUT IT!

NTYLH:
CP IBH HAVE NE HIT A
MAGENTA BRICK?
JR NZ.NTMAGN NOT MAGENTA
LD A,-1 SEND BALL IN
OTHER DIRECTION
LD (YINC),A
LD BC,5 SCORE
JR BEEP AND MAKE A SOUND

NTMAGN:
CP ZOH :HAVE NE HIT A GREEN BRICK?
JR NZ.ERROR JGOD KNOHS NHAT HE HIT!
LD BC:1B GIVE HIM A BIG SCORE
JR BEEP AND MAKE A NOISE!

ERROR:
LD DE,4OH
LD HL,66bH
CALL 3B5H MAKE A LONGER BEEP!

BEEP:
LD HL,(SCORE) ;GET SCORE
ADD HL,BC ;AND ADD 9,5 OR 16
LD (SCORE),HL TSAVE UPDATED SCORE
LD HLJHIT5 :POINT TO NUMBER OF HITS
DEC (HL) TSUBTRACT ONE
JR NZ,NOEND ALL BRICKS HIT?

LD (HL),96 RESET NUMBER OF BRICKS


LD A,(LEVEL) GET LEVEL
AND A TEST FOR ZERO LEVEL
JR Z,MAXLEV DO NOT BOTHER MAKING
IANY MORE DIFFICULT
DEC A iONE OFF THE LEVEL
LD (LEVEL),A ;AND SAVE
LD A,fBALLS) ;GET NUMBER OF BALLS
ADD A,2 ;AND GIVE HIM THO MORE
LD (BALLS),A ;AND SAVE
166 Machine code miscellany

MAXLEV:
CALL RNDBAL ;GET A RANDOM BALL POSTION
CALL SETUP ;SET UP THE HALL
NOEND:
LD DE,B
LD HL,666H
CALL 3B5H IBEEP
LD A,B :MAKE SURE
OUT (GFEH),A :UE HAVE A BLACK BORDER
RET
The routine MUBALL is one of the main routines which deals with the
movement of the ball. The ball has a Y direction (YINC) and x direction
(xmc). These two variables are offsets which are added to the ball’s x
and Y co-ordinates. These are either 1 or -1. If the ball passes the
DOHOHTOTUHEHIBEH,Ofl€lSdBdUCHKIOfithEtHNflbEfOfHHfiBRHHg
balls. If there is still any left then a branch is made to RNDBALL which
sets up another ball at a random x position. If the ball collides with
an object than its x direction and/or Y direction is reversed.

MUBALL:
LD HL,(BALLX) ;GET BALLS X, Y CO-ORD
IBALL DOESNT GO THROUGH
3 THE BAT. . .

LD INC) ;GET Y DIRECTION


D @G TADD TO Y
LD ;AND SAVE NEH Y CO-ORD
LD INC)
>11-< ;GET X DIRECTION
ADD :ADD TO CURRENT X CO-ORD
LD Il>I'“" 'DI" ' ;AND SAVE NEH X CO-ORD
PUSH areseee :SAVE THIS
CALL PEEK TLOOK AT THE COLOUR
:OF NEH X,Y
POP HL :RESTORE SCREEN ADDRESS
CP 39H :IS IT THE BAT
;HIT?
JR NZ,NTBAT :NO ITS NOT!

LD A,(YINC) ;REVERSE Y DIRECTION


NEG
LD (YINC), A ;AND SAVE
BSEMI REBOUND DIRN.
'-II

Machine code miscellany 167

A:(XINC) TREVERSE X DIRECTION

ADD A,L 3 ADD X CO-ORD


LD L,A : AND SAVE IN L
CALL PEEK ILOOK AT COLOURS HERE
CP SSH i IS IT NORMAL BACKGROUND
NZ.MUBALL :NO.THEN MOVE BALL

TSEND BALL BACK THE HAY IT CAME ...

A:(BALLX) GET X CO-ORD


A TEST FOR LEFT HAND SIDE
Z:MUBALL NO THEN MOVE BALL
A:(XINC)
REVERSE X DIRECTION
(XINC),A AND SAVE
MUBALL MOVE THE BALL

NTBAT:
HLi(BALLX) GET X,Y CO*ORD
A.(XINC) GET X DIRECTION
A,L GET NEH X CO~ORD
L,A AND SAVE IN L REG
(TPBLYX),A PLACE NEH X CO-ORD IN TEMP
A IS IT AT THE
LEFT HAND SIDE?
Z,NGXINC YES THEN GO TO
CHANGE X DIRECTION
1FH IS IT ON THE
RIGHT HAND SIDE?
C,YCHECK NO SO CHECK Y MOVEMENT
NGXINC
A,(XINC) GET X DIRECTION
REVERSE X DIRECTION
(XINC),A AND SAVE

YCHECK
A,(YINC) GET Y DIRECTION
A,H GET NEH Y CO-ORD
H,A AND SAVE IN H REG
(TPBLYX+1):A ;AS HELL AS TEMP+1
A F HAVE HE HIT THE TOP?
Z,NGYINC ;YES THEN CHANGE
Y DIRECTION

_ .-tfll
II’

168 Machine code miscellany

CP 23 HAVE HE HIT THE BOTTOM?


JR NC,BALOUT iOUT OF BOUNDS
CALL PEEK NUILODK AT HHERE
THE ARE GOING TO.
CP 38H JIS IT BLANK?
JR Z,GOED ;YES.CARRY ON
CALL BRKOUT THIT SOMETHING SO CHECK!
NGYINC:
LD A,(YINC) ;GET Y DIRECTION
NEG FCHANGE DIRETCION
LD (YINC),A ;AND SAVE
GOED:
LD A,D ISET UP CHARACTER AS SPACE
IERASE OLD
LD C,3BH ;SET UP BACKGROUND COLOUR
LD HL,(BALLX) ;GET BALLS X,Y CO-ORDS
CALL PRTCH ;AND BLANK OUT
LD A,1 ;GET BALL CHARACTER
LD HL,(TPBLYX) ;GET TEMP X,Y
LD (BALLX),HL ;AND SAVE IN BALLS
;X.Y CO-ORDS
CALL PRTCH TPRINT THE BALL!
LD A,(LEVEL) ;GET LEVEL
LEVLP:
EI
HALT £1/55 OF A SECOND DELAY
DI
DEC A
JR NZ,LEVLP IDELAY DEPENDENT ON LEVEL
RET
BALOUT:
LD A,D ; scr UP cunancrcn as srncc
IERASE BALL IBACKGROUND COLOUR
LD C,3BH
LD HL,(BALLX) GET X,Y CO-ORDS
CALL PRTCH AND PRINT
CALL RNDBAL GET RANDOM X,Y CO-ORD
LD HL,BALLS ONE OFF NUMBER OF BALLS
DEC (HL)
RET

IRANDOM X—POSN FOR BALL


Machine code miscellany 169

RNDBAL: I GET FRAMES


LD A, (23672 )
FLSB OF FRAMES
SRL A
AND BFH :O—1S
ADD A, 5 :5-28
LD (BALLX ), A :SAVE RANDOM X CO-ORD
FFOR BALL
LD A,6 :INTIALIZE Y CO-ORD
;SET Y —POS
K LD (BALLX+1),A ;AND SAVE
LD HL,(BALLX) ;GET X, Y CO-ORD
LD (TPBLYX),HL ;AND SAVE IN TEMP X,Y
LD B, 56
DLOOP:
EI
HALT
DI
DJNZ DLOOP THAIT FOR A HHILE
RET

END

MAZE GENERATOR

This program generates random mazes consisting of a 32 by 22 grid


of cells. It can, however, be easily adapted to produce mazes of any
desired width and height. The algorithm used generates mazes
where there is only one route from one cell to another. This routine
could be used in games to produce a maze for an adventure game
program such as the famous ‘Hall of the Things’ by Crystal Software.
A maze is constructed of cells and each of these cells are sur-
rounded by up to four walls. They can be regarded as having just
two walls as the other surrounding cells provide the other two.
Diagram 1 shows how the wall would be made up on a 3 by 3 maze.
Notice that there are no walls on the top and left sides of the maze.
These we can draw later, after we have constructed the rest of the
maze.
u-4

170 Machine code miscellany

Top and left maze walls drawn later

JJJ
1
—mJ
i

_J_J_l
Lower wall of cell

Hexadecimal Listing
7DOB C3 49 7D OF 16 16 81 GB
7D@8 BB B1 B1 Q4 GB BO Q9 BB
7D1O OB QB DO BE GIG DE BO DB
7D18 3C 7E FF FF FF FF 7E 3C
7D2@ 3F 7F FF FF FF FF 7F 3F
7D28 FF FF FF FF FF FF FF FF
7D3@ FC FE FF FF FF FF FE FC
7D38 FF 81 81 81 81 81 81 FF

7D4B 3E Q2 CD D1 16 AF D3 FE
7D48 21 BO GB ‘I7’?
lulu BC 7D 3E B5
7D5@ 32 DE 7D 3E G4 32 BB 7D
7D58 3E 68 32 BF 7D CD IA 7E
7D6@ CD 5F 7F 21 ID 16 22 D3
7D68 7D CD D9 7D 3A DE 7D A7
7D7B 28 BB CD 83 7D CD B7 7E
7D78 FB 76 F3 18 EF ED 4B BC

1__
Machine code miscellany 171

7D8@ 7D FB C9 CD D9 7D 3E FE
7D88 DB FE E6 1F FE 1F C8 CD
7D98 C5 7D CB 4F CC B7 7D CB
7D98 57 CC A8 7D CB 47 28 84
7DA8 CB C7 18 EE CD D9 7D C9
7DAB F5 2A 83 7D 3E 1D BD 28
7DB@ 84 2C '3'?
I-In G3 7D F1 C9 F5
7DB8 2A 83 7D 7D A7 28 84 2D

7DCfl 22 G3 7D F1 C9 F5 2A B3
7DC8 7D E1 38 D3 C5 E5 AF CD
7DD@ ED 7D E1 2C C1 15 F5 F1
7DD8 C9 2A 83 7D 81 39 83 3E
7DE8 G2 C5 E5 CD ED 7D 3C E1
7DE8 2C C1 18 F5 C9 F5 C5 E5
7DF8 C5 F5 E5 7C CD 9E BE D1
7DF8 16 88 19 EB F1 81 18 7D

7E88 26 G8 6F 29 29 29 89 86
7Efl8 88 7E 12 23 14 1D FA EB
7E18 CD 88 GE C1 79 12 E1 C1
7E18 F1 C9 CD 68 DD 81 2B 28
7E2D 3E 85 21 98 83 CD 37 7E
7E28 81 18 28 21 88 84 CD 37
7E38 7E 81 38 28 21 DO 85 CD
7E38 ED 7D 2C 18 FA C9 7D 6C

7E4fl 26 88 29 29 29 29 29 86
7E48 88 4F 89 81 D8 58 89 7E
7E58 C9 B1 DD 88 FE 38 28 DA
7E58 3E FF 32 8A 7D 81 82 83
7E68 18 28 FE 18 28 DA 3E FF
7E68 32 GA 7D 81 D5 88 18 12
7E78 FE 2D 25 85 81 DA 88 18
7E78 89 11 48 88 21 66 86 CD

7E88 85 83 2A 8C 7D G9 22 8C
7E88 7D 21 BF 7D 35 28 1A 36
7E98 68 3A 88 7D A7 28 DC 3D
7E98 32 88 7D 3A 8E 7D C6 52
7EA@ 32 8E 7D CD 5F 7F CD 1A
7EA8 7E 11 88 88 21 66 86 CD
7EB8 B5 83 3E 85 D3 FE C9 2A
7EB8 85 7D 3A DA 7D 84 67 3A
lIll!Hl"'

172 Machine code miscellany

7EC@ 9 7D 85 6F E5 CD 3E 7E
7EC8 E1 FE 39 28 26 3A 8A 7D
7ED8 ED 44 32 8A 7D 3A 89 7D
7ED8 ED 44 85 6F CD 3E 7E FE
7EE8 38 28 D4 3A 85 7D A7 28
7EE8 CE 3A 89 7D ED 44 32 89
7EF@ 7D 18 C4 2A 85 7D 3A 89
7EF8 7D 85 6F 32 87 7D A7 28

7FEfl 84 FE 1F 38 88 3A 89 7D
7F88 ED 44 32 89 7D 3A 8A 7D
7F1O 84 67 32 88 7D A7 28 8E
7F18 FE 17 38 31 CD 3E 7E FE
7F28 38 28 88 CD 51 7E 3A 8A
7F28 7D ED 44 32 8A 7D 3E 88
7F38 E 38 2A 85 7D CD ED 7D
7F38 3E 81 2A 87 7D '17’?
J.-flu-u 5 7D

7F48 CD ED 7D 3A El 7D F8 76
7F48 F3 3D 28 FA C9 3E 88 8E
7F5fl 38 2A 85 7D CD ED 7D CD
7F58 5F 7F 21 8E 7D 35 C9 3A
7F68 78 5C CE? 3F E6 F C6 85
7F68 32 5 7D 3E 86 32 6 7D
7F7fl 2A 85 7D 22 87 7D 86 32
7F78 F8 76 F3 1 FE: C9 A7 28

The theory behind the maze generator is to walk randomly round


the maze knocking down walls as we proceed. To begin we walk a
set number of steps around the maze knocking down the walls if we
meet any obstructions. On our second walk we start off in a cell that
we have not previously entered. We again walk randomly around
the maze knocking walls down. We keep on walking till we arrive at
a cell which we had visited before on ‘other walks’. When we arrive
at such a cell we have then completed a path from one random walk
to another on a different random walk. This process is repeated on
all the untouched cells until we have proceeded through all the
maze.
To implement this algorithm in machine code we represent our
maze by having two arrays, the size of which are the size of the
number of cells in the maze. One is called BUILD, the other MAZE. The
array BUILD holds the path numbers and route which we ‘walk’ along
while the array MAZE holds the ‘wall’ patterns. A wall pattern shows
the structure of the two walls in a cell. The array MAZE is initialized

i—__
Machine code miscellany 173

with the two walls intact. This is represented by the two first bits of
its number being set high (i.e. the number three). Knocking down
the walls is represented by re-setting a particular bit. lf bit O of the
number represents the bottom wall and bit 1 represents the right
hand side wall then we can see the process if we knock down a wall.
Going downwards we reset bit O of the cell we are in. If we knock
down a wall going up we reset bit O of the cell above,the cell we are
entering. Going right we re-set bit 1 of the cell we are in, going left
we re-set bit 1 of the adjacent cell.
One point we have to look out for is that we do not ‘back track‘ on
a particular walk we are doing. We do this by giving each walk a path
number and if we do happen to back track on our original path then
we do not bother to knock down any walls. Using this method we
guarantee our maze does not have any gaping holes and that it is
singular in nature.
The program comes in two parts, one BASIC and one machine
code. The machine code routine generates a random maze. The
BASIC program draws the top and left hand side of the wall to
complete the maze. When you use the generator in a game the
unused bits in the array MAZE can be used to represent up to 63
objects such as axes, torches, wands or nasties! The second array is
unused once the maze is generated so it could be used to store
other variables or data in the game. The maze takes about two
seconds to generate, very slow by machine code standards. perhaps
you could set yourself the task to make it faster. One way of
improving the speed for 48K Spectrum owners would be to place the
routine higher up in the memory map above the address 32768.
Moving the code here would stop the Z80 CPU ‘waiting’ for the
Spectrum's ULA to update the screen.
BASIC Listing

1 CLEAR 29888
18 CLS:LET SC=U5R 32888
28 CLS:PHINT QT 18,18;"SCURE =
|t;SC

38 FDR X=1 TD 288:NEXT X


48 PRINT #8;"PHE5S A KEY TU ST
ART"
58 PQUSE 8
68 EU TD 18
W

174 Machine code miscellany

Assembler Listing

ORG 38668
JP START
XPOS: DB 3
YPOS: DB O
PATH: DB B

OPENCH EOU 16B1H


UDG EQU 23675 UDG ADDRESS

INTHAZE:
LD A,2 OPEN SCREEN CHANNEL
CALL DPENCH
LD HL,NOUGHT SET USER DEF GRAPHICS
TO OURS
LD (UDG),HL
CALL RANDI INTIALIZE RANDOM
NUMBER GENERATOR
LD HLIHAZE RE-BUILD THE HAZE
LD DE,HAZE+1
LD BC,22#32 OF 22 BY 32
LD (HLL3 HITH HALLS
LDIR
I HL POINTS BUILD
3 DE POINTS BUILD+1

LD BC,22¥32 CLEAR THE ARRAY


LD (HLLB BUILD NITH I
LDIR
XOR A SET THE START X CO-ORD
LD (XPOS),A
LD (YPOS),A SET THE START Y CO-ORD
INC A
LD (PATH),A SET THE STARTING
PATH NUMBER
RET
FINISH INTIALIZING

RANDB DB RANDOM UAR B


RAND1 DB RANDOM VAR 1
Machine code miscellany 175

RAND2 DB ; RANDOM UAR 2


RAND3 DB G : RANDOM UAR 3
GENERATE RANDOM NUMBER
BETHEEN
O AND 25¢

LD A,(RAND1) ;GET RANDOM SEED


RRCA A MOD 8 1 32
RRCA
RRCA
PUSH BC ; SAVE BC PAIR
PUSH AF :SAUE AF PAIR
LD A,(RAND2) ;GET SECOND RANDOM VARIABLE
LD B,A ;AND PLACE IN B REGISTER
LD A,(RAND3) ;GET THIRD RANDOM VARIABLE
LD C,A ;AND PLACE IN C REGISTER
POP AF TRESTORE AF
ADD (RAND1)MOD B #32 + (RANDRJ
ADD ?’§* CI@ +(RAND3)
RLCA JALIGN BITS
RLCA ;AND SAUE NEH RANDOM
VARIABLES
LD (RANDD),A
LD A,B
LD (RAND1),A
LD A,C
LD (RAND2),A
LD A,(RANDB)
LD (RAND3),A
POP BC IRESTORE BC PAIR
RET

RANDI
LD A,B SET UP RANDOM UARIABLES
LD (RANDG),A
LD A,173
LD (RAND1 ), A
LD A,2B6
LD (RAND2),A
LD A,R ENSURE SOME RANDOMNESS
LD (RAND3),A
RET
176 Machine code miscellany

LENU EOU 255D LARGEST NALK

UALK:
LD B,LENH
KEN: KEEP WALKING

CALL RANDU
LD &(HL) GET CONTENTS OF
NEH POSTION
AND A TEST FOR NED LOCATION
JR Z,PUTIN ZERO SO MARK PATH!
CP C GOING BACK ON PATH?
JR Z,PUTIN YES MARK IT!
RET HAVE REACHED A VALUE LOWER

PUTIN:
LD A,(PATH) GET PATH NUMBER
LD (HL),A AND PLACE IN BUILD
DJNZ NEH DO THIS FOR LENH MAXIMUM
LD A,(PATH) ONLY DO LENH FOR PATH 1
CP 1
JR NZIHALK

RET

RANDH:
CALL RAND GET RANDOM NUMBER
AND 3 MASK OFF FOR
NUMBERS O TO 3
AND A

JR Z,NORTH IF ZERO GO NORTH


CP 1
JR Z,SOUTH IF 1 GO SOUTH
CP 2
JR Z,HEST IF 2 GO NEST

TGO EAST

L
Machine code miscellany 177

LD A,(XPOS) GET X CO-ORD


CP 31 TEST TO SEE IF HE ARE ON
JR Z,RANDU THE RIGHT HAND SIDE
IF SO GO AGAIN
INC A ELSE INCREASE
X CO-ORD BY 1
LD (XPOS),A
LO C»(HL) VALUE IN C REGISTER
INC HL POSTION
LD A,(HL) VALUE
CP C THEY EOUAL7
RET Z DON T BACKTRACK'

DEC HL GET OLD POSTION


CALL RES1 RESET BIT 1 OF OLD CELL
INC HL POINT TO NEH CELL
RET

LD A,(XPOS) GET X CO-ORD


AND A TEST FOR LEFT HAND SIDE
JR ZiRANDU PICK ANOTHER DIRECTION

DEC A GO LEFT
LD (XPOS),A SAVE X CO-ORD
LD C,(HL) OLD VALUE

DEC HL GO LEFT
LD MIHL) GET NEH VALUE
CP C COMPARE HITH OLD VALUE
RET Z NO BACKTRACKING
178 Machine code miscellany

RES1: PUSH HL TSAVE NEH POSTION


LD DEiMAZE—BUILD :POINT TO CORRESPONDING
TMAZE ADDR
ADD HL,DE
RES 1,(HL) ;KNOCK DOHN HALL
POP HL ;GET NEH POSTION
RET

NORTH
LD A,(YPOS) ;GET Y CO-ORD
AND A IARE HE AT THE TOP?
JR Z,RANDH ;YES,THEN PICK ANOTHER
;DIRECTION

DEC A :GOING UP
LD (YPOS),A iSAVE NEH Y CO-ORD
LD C.(HL) ;GET OLD VALUE
LD DE,-32 FOFFSET FOR GOING UP
ADD HL,DE TPOINT TO NEH PART OF
IBUILD ARRAY
LD %(HL) ;GET PATH NUMBER
CP C J‘COMPARE HITH OLD VALUE
RET Z ;DON’T BACKTRACK!

RESG: PUSH HL TSAVE NEH POSTION


LD DEIMAZE-BUILD FPOINT TO CORRESPONDING
IMAZE
ADO HL,DE
RES O,(HL) ;KNOHN DOHN HALL
POP HL IRESTORE POSTION
RET

SOUTH
LD A,(YPOS) ;GET Y CO-ORD
CP 21 IHAVE HE HIT THE BOTTOM?
JR Z,RANDH IYES THEN PICK
EANOTHER DIRECTION
Machine code miscellany

A GOING DOHN
(YPOS),A SAVE Y CO-ORD
Q(HL) OLD VALUE

DEl32 OFFSET FOR GOING DOHN


HL,DE
A,(HL) GET NEH PATH NUMBER
C COMPARE HITH OLD PATH
Z DON T BACKTRACK
A CLEAR CARRY
HL,DE NORMAL SUBTRACTION
RESO KNOCK DOHN BOTTOM HALL
DE,32 GET HL BACK
HL,DE

PRINTC
HL SAVE REGISTERS
BC

OIOH PRINT A REGISTER


TO CURRENT CHANNAL
RESTORE REGISTERS
BC
HL

DISPLAY DISPLAY MAZE TO


HL,MAZE SCREEN LOAD A HITH
A,22
NUMBER OF LINES DOHN
LINE PUSH AF SAVE LINE COUNT

B,32 GET CHARACTER COUNT


DRAHS GET MAZE VALUE
A,(HL)
A,144 ADD BASE OF UDG
PRINTC PRINT CHARACTER
HL NEXT MAZE CELL
DRAHS REPEAT 3" TIMES
180 Machine code miscellany

AF , RESTORE LINE NUMBER


A 3 ONE OFF LINE NUMBER
NZ,LINE REPEAT 22 TIME

BUILDM
HLIBUILD POINT TO ARRAY BUILD
A INTIALIZE THE X CO-ORD
(XPOS),A AND Y CO-ORD
(YPOS),A

A,(HL) GET PATH NUMBER


A TEST FOR ZERO
Z,SKIP START HALKING ON ZERO
HL NEXT ONE ACROSS
A,(XPOS) UPDATE X CO"ORD
A
(XPOS),A
32 HAVE HE GONE RIGHT ACROSS?
NZIFIND NO SO CARRY ON LOOKING
A YES RESET X CO-ORD
(XPOS),A
A,(YPOS) GO ONE DOHN
A
(YPOS),A
22 HAVE HE GONE ALL
NZ,FIND THE HAY DOHN? NO THEN KEEP
LOOKING ELSE RETURN

A,(PATH) GET PATH NUMBER


(HLLA PLACE AT NEH CELL
HALK DO A RANDOM HALK
A,(PATH) UPDATE
A
(PATH),A NEH PATH NUMBER
BUILDM CARRY ON BUILDING
Machine code miscellany 181

START:
CALL INTMAZE ICLEAR MAZE
CALL BUILDM ;BUILD MAZE
CALL DISPLAY TDISPLAY MAZE
RET

IUSER DEFINE CHARACTER SET FOR MAZE

NOUGHT:
DB OJBJLOJ%OJB
DB 0,0,0,0,0,0,0,255
OB 1, 1, 1, 1, 1, 1, 1, 1
DB 1,1,1,1,1,1,1, 255

MAZE: OS 32122
BUILD: OS 32322

END

Hexadecimal Listing

753$ C3 BO 76 OB OB BB 3E B2
7538 CD G1 16 21 97 76 22 7B
7545 5C CD 98 75 21 B7 76 11
7548 BB 76 O1 CB E2 36 Q3 ED
7556 BB B1 C8 G2 36 BB ED BO
7558 AF 32 33 75 32 34 75 3C
7566 32 35 75 C9 BO OE BO SO
7568 3A 65 75 OF BF OF C5 F5

7579 3A 66 75 47 3A 67 75 4F
7578 F1 BB 81 O7 B7 32 64 75
7588 78 32 65 75 79 32 66 75
7588 3A 64 75 32 67 75 C1 C9
759E 3E BO 32 64 75 3E AD 32
7598 65 75 3E CE 32 66 75 ED
75AB 5F 32 67 75 C9 O6 FF CD
75A8 CB 75 7E A7 28 O4 B9 28
182 Machine code miscellany

7588 81 C9 3A 35 75 77 18 EF
7588 3A 35 75 FE 81 28 E6 C9
7588 CD 68 75 E6 83 A7 28 36
75C8 FE 81 28 4D FE 82 28 16
75D8 3A 33 75 FE 1F 28 E9 38
75D8 32 33 75 4E 23 7E 89 C8
75E8 28 CD F5 75 23 C9 3A 33
75E8 75 A7 28 D4 3D 32 33 75
75F8 4E 28 7E 89 C8 E5 11 48
75F8 FD 19 C8 8E E1 89 3A 34
7688 75 A7 28 8C 38 32 34 75
7688 4E 11 E8 FF 19 7E 89 C8
7618 E5 11 48 FD 19 C8 86 E1
7618 C9 3A 34 75 FE 15 28 A8
7628 3C 32 34 75 4E 11 28 88
7628 19 7E 8? C8 A7 ED 52 CD
7638 18 76 11 28 88 19 C9 E5
7638 C5 D7 C1 E1 C9 21 87 76
7648 3E 16 F5 86 28 7E C6 88
7648 CD 37 76 23 18 F7 F1 3D
7658 28 F8 C9 21 77 79 AF 32
7658 33 75 32 34 75 7E A7 28
7668 1C 23 3A 33 75 3C 32 33
7668 75 FE 28 28 F8 AF 32 33
7678 75 3A 34 75 3C 32 34 75
7678 FE 16 28 E1 C9 3A 35 75
7688 77 CD A5 75 3A 35 75 3C
7688 32 35 75 18 C6 CD 36 75
7698 CD 53 76 CD 3D 76 C9 88
7698 88 88 88 88 88 88 88 88
76A8 88 88 88 88 88 88 FF 81
76A8 81 81 81 81 81 81 81 81
7688 81 81 81 81 81 81 FF 88
7688 88 88 88 88 88 88 88 88
76C8 88 88 88 88 88 88 88 88
7688 88 88 88 88 88 88 88 88
76D8 88 88 88 88 88 88 88 88
76D8 88 88 88 88 88 88 88 88
76E8 88 88 88 88 88 88 88 88
76E8 88 88 88 88 88 88 88 88
Machine code miscellany 183

76Ffl flfi BB BE B9 BB BB BB B5
?éF8 BE B9 E3 BE QB B5 BB QB
7796 flfl EB BB BB B6 EQ QB BB
7798 BB B5 BE GE 65 QB B5 B9
7715 BB BB G8 EB BB BB G9 BB
7?18 BB E6 E5 QB GE QB GB B9
?72B GB B9 BB BB 86 BB GB BB
7728 B6 BE BB EB QB B6 @@ QQ
LARGE PRINT
I wrote this routine to enhance my own BASIC programs. The routine
PRINTS characters on the screen twice the width of normal characters.
l have ‘patched’ part of the BASIC operating system so that the large
characters can be PR|NTed from BASIC and will accept all the control
characters, such as INK, PAPER, AT, TAB, etc. To enable the large PRINT
facility we first call the routine at address 30000. This gives the
Spectrum an additional channel, channel number 5. Then, to PRINT
large characters to the screen we simply us the BASIC syntax:

PRll\lT#5 ; “STRING”

Here's a sample BASIC program which demonstrates how the routine


can be used:

13 CLS : RHNDUHIZE USR EBBBB


EB PRINT "This program demenst
rates"
SB PRINT "Hew tn get "5: PRINT
#5;"Lerge";: PRINT " letters"
4B PRINT #5;" on the screen

58 PRINT
63 PRINT "It can cope with can
trel codes"
TB PRINT #5;fiT 5,5;"such as AT

75 PRINT
BB PRINT #5; INK 5; PAPER 2;"a
nd colours“
PB PRINT #5; INVERSE 1;TAE 7;"
inverse"
163 PRINT #5; FLASH 1;" as well
as flashing“
184 Machine code miscellany

Assembler Listing

ORG 33380

CURCHL EQU 23633


REPDRTJ EQU 15C4H INVALID I/O DEVICE
STRHS EQU 23568D STREAMS
STREAH5 EOU STRMS+6+5¥2 OPEN CHANNEL 5

CHARS EQU 236060 CHARS CHARACTER ADDRESS


UDG EOU 236750 UDG ADDRESS
CHANS EOU 236310 CHANNEL ADDRESS
CHANINF EQU STREAH5+2 CHANNEL 5

POCHANGE EOU BABBH


TVDATA EIU 23566
TVDATL EOU TVDATA
TVDATH EOU TVDATA+1
PDCDNT EBU BA87H

INITP: SET UP PRINT#4 COMMAND


LD HL,CHANIND MOVE CHANNEL INFORMATION
LD DE.CHANINF
LD BC,5
LDIR
LD HL,CHANINF FIND DISTANCE BETWEEN CHAN
LD DE,(CHANS)
AND A
SBC HL,DE
INC HL
LD (STREAN5),HL SET UP STREAMS
RET

CHANIND:
DEFU PRINTD PRINT OUT ROUTINE
DEFH REPORTJ INPUT ROUTINE
DEFB ID!
Machine code miscellany 185

PRINTD
NHEN BASIC CALLS THIS ROUTINE THE
A REG CONTAINS CHAR NUMBER

25H TEST TO SEE IF PRINTABLE


NCICAR PRINT THE CHARACTER
BBB3H GET CURRENT PRINT POSTION
B6 PRINT 'P'
FUR cones aa- as HEX
C,SA69H
18H AND 18H TO 1FH
NC,OA69H
16
C,O9F4H+16D GO TO ROMS TABLE

HLIATTAB ASSUME CONTROL CHAR


IS AT OR TAB
22
NCIRIGHT YOU HHERE RIGHTl
HL,INKOVER
RIGHT
HL RETURN ADDRESS IS PUSHED
BBB3H FETCH CURRENT CHARACTER

POTVZD
DE,POCONTD SAVE FIRST OPERAND
IN TVDATH
(TVDATH),A
POCHANGE CHANGE ADDRESS OF
CURRENT CHANNEL

ATTAB
DE.POTV2D NEXT TIHE ROUND SOTO POTVD
POTVID SAVE CHARACTER CODE
IN TVDATAL

INKOVER
DEIPDCUNTD NEXT TIME POCONTD
PGTVID (TVDATL),A SAVE CONTROL CODE
POCHANGE CHANGE OUTPUT ADDRESS
i —_

186 Machine code miscellany

POCONTD BOTH OPERANDS ARE


COLLECTED
LD DEIPRINTD INEXT TINE PRINTD
JP POCONT+3 :DEAL HITH OP AND CONT CODE

CAR: LD DE,(CHARS) ;GET CHARACTER ADDRESS

LD H,D GET CHARACTER CODE IN HL


LD L,A
ADD HL,HL :12
ADD HL,HL ;¥4
ADD HI-1 :18
ADD HL,DE HL POINTS TO START OF
CHAR DATA
EX DE,HL NON DE DOES!

LD HLIDUGD
PUSH HL
POP IX : EX HL NITH IX REG
LD B,B ; DATA COUNT

GETD: LD A,(DE) ;GET DATA

FECTHD GET DOUBLE HORD IN HL

PUSH BC SAVE DATA COUNT


CALL FETD
POP BC RESTORE DATA COUNT

LD (IX+O),L PLACE IN UDG AREA


LD (IX+B),H
INC IX NEXT BYTE IN UDG
INC DE NEXT CHAR DATA
DJNZ GETD DO THIS EIGHT TIMES
LD HL,(UDG) SAVE REAL UDG ADDRESS
PUSH HL
LD HL,DUGD GET DUMMY UDG ADDRESS
LD (UDG),HL AND CHANGE UDG
LD A,145 NOH PRINT USER DEFINED
GRAPHICS
Machine code miscellany 187

CALL B9F4H
LD A,144 FNOU PRINT USER DEFINED
FGRAPHICS
CALL G9F4H
POP HL iRESTORE UDG
LD (UDG),HL
RET

FETD:
CALL NYBBLE FDO ONE NYBBLE
LD L,H
INOH GET NEXT NYBBLE
NYBBLE:
LD B,4 ,‘NUMBER OF BITS
NBIT: RRCA

ITRY CHANGING ABOVE OPCODE TO RLCA!!! FOR A BIT OF FUN

RR C THAKE THICE AS FAT


SRA C
DJNZ NBIT ;DO B TIHES
LD H,C
RET

DUGD: DS B82

END

Hexadecimal Listing

753$ 21. 14A 755 11 22! 5[I B1


7538 GET IED I30 21 I22 5E1 IED
7543 4F' 250 A7’ EE) 52! I23 22!
7548 fifil (39 4F’ I75 [I4 15 '44
7558 223 DE! 91. §?5 [ID T33 @E=
7558 l36 l)A 65' IDA IPE 18 l)2
756G IBA FEi 1Ei IDA @4l l3A 21
7568 I75 FEI 16 38 T33 21 T32
188 Machine code miscellany

757B E5 C3 3 BB 11 BE! 75 32
7578 BF 5C C3 BB BA 11 74 75
758B 18 B3 11 BE? 75 3? B11: 5l.'I
7588 C3 BB BA 11 4F 75 C3 BA
759B BA ED 5E1 36 5C as BB 6F
7598 29 2"? 29 19 EB 21 DE 75
75AB E5 DD E1 B6 B8 1A C5 CD
75A8 CF 75 C1 DD 75 ea DD 74
7588 B8 DD Z333 1.3 1B HP EA 7E!
75B8 5C E5 21 DE 75 ‘I7’?
iii.-a.. 7E1 {fill
75CB 3E 91 CD F4 B‘? I51.-‘I ‘?B CD
75C8 F4 B‘? E1 7E1 5C [I19 Ill’)
75DB D3 75 6C B6 B4 BF CEI 1‘?
75DB CE? 2‘? 1B F‘? 61 C9‘ BB B
75EB BB BB BB BB B BB BB B
75E8 BB B BB B BB 82 75

75FB E5 C3 B3 BEI 11 BB 75 3113


75F8 BF 5C C3 8 BA 11 74 75

PIXEL SCROLL
This routine allows the user to scroll any portion of the screen to
either left or right. lt has a ’wrap-around’ effect, and so could be
most useful when writing arcade games with scrolling background
scenery of mountains, high rise flats or the like. When calling the
routine the HL register pair must point to the screen address of the
position from which you wish to scroll. The program below is a
demonstration program showing how the routine can be used from
BASIC!

5 FDR x=1 To 32*22:PRINT CHR$


143;:NEXT x
1B PRINT AT o,e;"THIs scRoLL w
ILL eo LEFT"
an PRINT "HITH THIS LINEE!"
so PRINT AT B,B;"THIS scRoLL w
ILL so RIGHT"
4e PRINT "ALONG NITH THIS LINE
SB RANDDHIZE USR EIEBBB
{QB GD TU 5B
Machine code miscellany 189

Here are the listings for the scroll routine:


Assembler Listing

ORG 320000

NLINES EOU 16 ;NUHBER OF LINES TO SCROLL


NBYTES EOU 32 INUNBER OF BYTES TO SCROLL
EOU 16384 ISCREEN ADDRESS
EOU 16384+256¥8 ISCREEN ADDRESS2

JP TEST ITEST THE SCROLL

I1181311331888!!!Ilfllkllikfltlkililiiiillltlkt
iThese two routines SLEFT SCROLL LEFT
; and SRIGHT SCROLL RIGHT scroll the screen
ileft and right respectiv1g.Theg use the rout-
;—ine INCY which finds address of corresponding
ipixel line addresses.
i0n entrg to the routine HL points to the top
ileft hand side of the portion of the screen
ito he scrolled.
;The other values which the program will give are
;NBYTES nunber of bytes to scroll ie width
;NLINES number of lines to scroll
iBoth rountines have a urap—around effect.

SLEFT
L0 HL,A00+NBYTES-1
IPOINT TO RIGHT HAND SIDE
LD CJNLINES INUHBER OF LINES TO SCROLL

PUSH HL ;SAVE SCREEN ADDRESS


L0 BJNBYTES :NUNBER OF BYTES TO SCROLL
IACROSS

CHARX
RL (HL) ISCROLL LEFT THROUGH
DEC HL ICARRY
DJNZ CHARX IREPEAT NBYTES TIMES
POP HL ;RESTORE RIGHT HAND
ISIDE ADDRESS
L0 A,B ;SET A TO ZERO
r____i -
190 Machine code miscellany

ADC A,A PLACE CARRY IN BIT I OF


OR (HL) RIGHT HAND SIDE
L0 (HLLA
CALL INCY GET ADDRESS OF NEXT PIXEL
LINE
DEC C 0OHN,ONE LESS LINE
JR NZILINE REPEAT UNTIL DONE ALL LINES
RET

SRIGHT
LD HLiADD2 POINT TO LEFT HAND
OF SCREEN
L0 C,NLINES NUMBER OF LINES TO SCROLL
LINER: PUSH HL SAVE LEFT HAND
SIDE ADDRESS
LD BINBYTES INUNBER OF BYTES TO SCROLL

CHARR:
RR (HL) SCROLL RIGHT THROUGH CARRY
INC HL TO THE RIGHT
DJNZ CHARR REPEAT UNTIL DONE
INBYTES TIMES
POP HL FRESTORE LEFT HAND SIDE
LD A,B ROTATE CARRY INTO LEFT
HAND SIDE
RRA
OR (HL)
LD (HLLA
CALL INCY NEXT PIXEL LINE DOHN
DEC C ONE LESS PIXEL LINE
JR NZILINER REPEAT UNTIL NO MORE LINES
RET

INCY: NEXT PIXEL LINE DOHN


HL POINTS TO SCREEN
ADDRESS
INC H NEXT LINE DOHN
L0 A,H TEST IF HITHIN CHARACTER
AND 7
RET NZ UITHIN CHAR SO RETURN

LD A,L NEXT CHARACTER DOHN

L I
Machine code miscellany 191

ADD ¢h2GH
L0 L,A
RET C :00 NOT ADJUST SECTOR SINCE
IUE HAVE GONE OVER

L0 Adi FHITHIN SECTOR SO


SUB 3 TRE-ADJUST
L0 H,A
RET

TEST:
CALL SLEFT JSCROLL LEFT
CALL SRIGHT ISCROLL RIGHT
RET

END

Hexadecimal Listing
7DB@ C3 46 7D 21 1F 4B GE 1B
7Dfl8 E5 B6 2B CB 16 2B 11 FB
7D1H E1 3E BB BF B6 77 CD 37
7D18 7D BD ER EC C9 21 BB 48
702B BE 1B E5 B6 EB CB 1E 23
7D2B 1B FB E1 3E BB 1F B6 77
7D3B CD 37 7D BD 25 EC C9 24
7D3B 7C E6 B7 CE 7D C6 BB 6F

7D4B D8 7C D6 E8 67 C9 CD H3
7D48 7D CD 1D 70 C9 BB GE BB
705B BB G8 BB BB BB SB BB BB
7D58 BB EB BB BB BB BB BB BB
706$ GB BB BB BE BB BB BB GE
7D68 BB BB BB BB BB BB BB BB
7D7fl BB BE EB GB BB BB BB BB
7D7B BB B9 BB B5 BB GB EH BB

AUTO LINE NUMBER


This routine produces line numbers automatically when the user is
typing in a BASIC program. Like the Clock and Trace programs given
192 Machine code miscellany

in Chapter 11, this uses interrupts. The routine LOADS the ASCII line
number into the system variable LAST-K every 1/50th of a second. This
causes the line number to be placed in the edit area and lower
screen of the Spectrum. To enable the auto line facility, key in the
instruction RAND USR 32333. To turn off the auto line first otters the line
number currently being edited and then enter RAND USR 32330:.
Don’t forget to CLEAR memory to keep the machine code safe.
CLEAR 32329 is suitable for this.
Assembler Listing

ORG 323300

ECHOE EOU 23682 ;COL NUMBER AND RON NUMBER


LASTR EOU 23560 ;LAST REY TO BE PRESSED
FLAGS EOU 23611 IKEYBOARD FLAGS
EPCC EOU 23625 ICURRENT LINE NUMBER
PPC EOU 23621 ICURRENT LINE EXECUTING

DISINT
IM 1 _: ENABLE DEFAULT INTERRUPTS
RET

ENABLE
XOR A ;SET A TO ZERO
L0 (STATE LA :NOT OUTPUTTING ASCII CHARS
LD A128“ ISET I REG TO PAGE 2BH
L0 I,A
IM 2 ;AND ENABLE INTERRUPT MODE 2
EI
RET

ORG 7E5CH ISTART OF INTERRUPT ROUTINE

CALL 38H ISCAN KEYBOARD FIRST


DI IDISABLE INTERRUPTS FIRST
PUSH AF ISAVE REGISTERS
PUSH BC
PUSH DE
PUSH HL
PUSH IX
Machine code miscellany 193

L0 A,(STATE) GET STATE


AND A TEST FO ZERO
JR NZ,DML ALL READY DOING A LINE

L0 A,(PPC+1) ARE HE EXECUTING A LINE?


CP 255
JR NZ,BYE YES SO EXIT FROM ROUTINE

LD AITECHOE)
CP 20H
JR NZ,BYE

L0 A,(EDHOE+1)
CP 17H
JR NZ.BYE IARE HE AT BOTTOM OF SCREEN
IARRIVE HERE IF HE ARE AT THE BOTTOM OF THE SCREEN

L0 Ai(LASTK) GET LASTK


CP OOH IF NOT RETURN
JR NZJBYE THEN EXIT FROM ROUTINE

FIRST LD A,4 SET UP NO OF CHARS


TO PRINT
L0 ISTATEJIA
L0 HLIDECTL START OF TABLE
L0 (CDATA L HL

L0 HL,(EPCC) ;GET CURRENT LINE NO


L0 0EiGOBAH ;GET STEP NUMBER
ADD HL,DE ;GET NEXT LINE NUMBER
L0 (LINE)iHL AND SAVE

DML: L0 A,(STATE) ;GET STATE


DEC A ONE LESS CHAR
L0 (STATE),A TO PRINT
L0 HLl(LINE) GET LINE NUMBER
CALL CONV OUTPUT ASCII TO LASTK
194 Machine code miscellany

BYE: RESTORE REGS


POP IX
POP HL
POP DE
POP BC
POP AF
EI
RET

DECTL: DEFN 10000 START OF TABLE


DECTX: DEFN 1000
DEFH 100
DEFN 10

CONV: LD IXi(CDATA) GET CURRENT TABLE POINTER


NDIGIT L0 C,(IX+0l GET LOU BYTE OF MULTIPLES
OF TENS
LD B,(IX+1l GET HIGH BYTE OF MULTIPLE
L0 n,'a'-1 SET UP A REG NITH 30 HEX
AND A RESET CARRY
FIDIG: INC A A00 1 TO A REGISTER
SBC HL,BC UNTIL HE GET A CARRY
JR NCIFIDIG
ADD HL,BC CORRECT NUMBER IN HL
L0 (LINE).HL AND SAVE IT‘
CALL OUTP2 OUTPUT ASCII CHAR IN A
REGISTER
INC IX POINT TO NEXT MULTIPLE
INC IX
PUSH IX TRANSFER IX TO HL
REGISTER PAIR
POP HL
LD (CDATA),HL AND SAVE
RET

OUTP2:
L0 (LASTK),A PLACE CHAR IN LASTK
LD HL,FLAGS SIGNIFY HE
SET i(HL) PRESSED A KEY
RET
Machine code miscellany 195

CDATA: DEFN 0 I CURRENT LI NE DATA


STATE: DB 0 FNO OF CHARS TO PRINT
LINE: DEFU 0 3 LINE NUMBER

END
Hexadecimal Listing

7E4A ED 56 C9 AF 32 E9 7E 3E
7E52 28 ED 47 ED 5E FB C9 B
7E5A BB B CD 38 BB F3 F5 C5
7E62 D5 E5 DD E5 3A E9 7E A7
7E6A 2B 31 3A 46 5C FE FF 2B
7E72 37 3A 82 5C FE 2B 2B 3B
7E7A 3A 83 5C FE 17 2B 29 3A
7EB2 8 5C FE BD 2B 22 3E B4

7EBA 32 E9 7E 21 B2 7E 22 E7
7E92 7E 2A 49 5C 11 BA BB 19
7E9A 22 EA 7E 3A E9 7E 3D 32
7EA2 E9 7E 2A EA 7E CD ETA 7E
7EAA DD E1 E1 D1 C1 F1 FB C9
7EB2 EB 3 64 BB A BB B1 BB
7EEA DD 2A E7 7E DD 4E BB DD
7EC2 46 B1 3E 2F A7 3C ED 42

7ECA 3B F-"E1 B9 22 EA 7E CD DE
7ED2 7E DD 23 DD 23 DD E5 E1
7EDA 22 E7 7E C9 32 B8 5C 21
7EE2 3E! 5C CE! EE C9 B BB B
7EEA BB BB ISA 46 5C FE FF 2B
7EF2 37 3A B2 5C FE 2B 2B 3B
7EFA 3A B3 5C FE 17 2B

SORT

Another program which can be used with BASIC, this sort routine
which allows you to sort strings into alphabetical order. The routine,
when called in BASIC searches for the dimensional array AS. It should
be first set up with the number of objects to sort and the length of
each string. lfthe string is not found or the length is too large then it
will exit from the sort routine with an appropriate error message.
When you wish to sort the string you simply call the machine code
from BASIC by using the instruction RAND USR 32000. This will then sort
l

196 Machine code miscellany

out the string in ascending order. The method used to sort out the
strings is known as a ‘Bubble Sort’. This method of sorting is not the
most efficient. However, under one second to sort out 100 strings of
25 characters in length is not slow!
The BASIC listing below demonstrates how the machine code pro-
gram is used:

5 LET sert=32BBB
1B DIN a$(1BB,25)
2B FDR p=1 to IBB
3B FDR c=1 to 25
4B LET a$(p,c)=CHR$ ((RND*26i+
65)
5B NEXT c
6B NEXT p
7B PRINT #B;"Pre5s L to 1i5t,5
to eert"
BB LET k$=INKEY$: IF k$="" THE
N GD TD BB
9B IF k$=“L“ DR k$="l" THEN GD
SUB 12B: BB TU 7B
IBB IF k${§"s“ AND k${}"S“ THEN
BU TD BB
11B CLS: PRINT "serting":RANDDH
IZE USR sort: BEEP 1,1: GD SUB 1
2B: STOP
12B FDR p=1 TD IBB
13G PRINT a$(pi
14B NEXT p
15B RETURN

Here are the listings for the sort routine:


Assembler Listing

ORG 320000
VARS EOU 236270

START:
LD HL,(VARS) ;SET HL TO POINT TO
IVARIABLE AREA
TEST: LD A,(HL) ;GET 1ST BYTE OF VARIABLE
CP 128 IEND OF VARS MARKER?
JR Z,NOTFOUND IFINISHED LOOKING AT VARS
Machine code miscellany 197

CP 193 IIS IT A5?


JP Z,FOUND IYES FOUND IT!

AND 111000000 ;MASK OFF TOP THREE BITS


CP 011000000 TSINGLE DATA
JR ZJADISIX JYES ADD 6
CP 111000000 ;’FOR NEXT’ VARIABLE?
JR Z.ADI19 FYES ADD 19
CP 101000000 ;VARIABLE NAME LARGER
FTHEN ONE LETTER?
JR Z,SKIPC ,‘YES THEN SKIP PASS
IVARIABLE NAME

I010 OR 110
INC HL
LD E.(HL) ;GET LENGTH LOU
INC HL
LD ETHL) ;GET LENGTH HIGH
INC HL
ADD HL,DE ISKIP PASS VARIABLE
JP TEST ITEST FOR NEXT VARIABLE

NOTFOUND:
RST 00
DB 01 IVARIABLE NOT FOUND ERROR!
ERROR:
RST 0B ;SUBSCRIPT NRONG ERROR!
DB 02
ADI19:
L0 DE,19 ;GO PASS VARIABLE
ADD HL,DE
JP TEST TTEST NEXT VARIABLE

SKIPC:
INC HL ISKIP PASS VARIABLE.
BIT 7,(HL) ;NAME
JR Z,SKIPC TTILL BIT 7 IS SET

ADISIX:
LD DE.6 JGO PASS VARIABLE
198 Machine code miscellany

HL,DE
TEST TEST NEXT VARIABLE

FOUND
HL
HL
HL POINT TO NUMBER OF DIMS
MUST BE THO OR LESS

&(HL)
2
NZIERRDR SHOULD BE TNO DIMENSIONS

HL POINT TO NUMBER OF
ELEMENTS
Bl(HL) NUMBER OF ELEMENTS
HL GET HIGH BYTE‘
m(HL)
A
NZJERRDR LARGER THEN 255 ELEMENTS
HL
Q(HL) LENGTH OF STRINGS
HL
A,(HL)
A
NZ.ERROR :LARGER THEN 255 CHARACTERS
HL
ON POINTS TO START OF STRING

A.C i SAVE SIZE


(SIZE).A

SORT:

IHL POINTS TO START OF STRING


:0 CONTAINS NUMBER OF STRINGS
TC CONTAINS LENGTH OF STRING
Machine code miscellany 199

NEXTS: PUSH BC iSAVE NUMBER AND LENGTH


XOR A iRESET SNAP FLAG
L0 tFLAG).A
PUSH HL ISAUE ADDRESS DF FIRST
ISTRING
NEXTEL:
PUSH HL ISAVE ADDRESS OF STRING
LD E,C ;GET LENGTH OF STRING
LD 0,0 ;AND PLACE IN DE REGISTER
ADD HL,DE IPOINT TO SECOND STRING
EX DEIHL ;AND PLACE IN
;THE DE REGISTER
POP HL IRESTORE ADDRESS OF STRING
CALL COMPARE ICOMPARE THE THO STRINGS
CALL C.SUAP IIN ASCENDING ORDER

EX DEIHL :HL NON POINTS TO


INEXT STRING

DJNZ NEXTEL IREPEAT COMPARISION UNTIL


FDONE UP TO CURRENT NUMBER
TOF STRINGS
POP HL ;GET ADDRESS OF
TFIRST STRING
POP BC IRESTORE COUNTERS
LO A.(FLAG) ;GET SNAP FLAG
AND A ITEST FOR ZERO
RET Z IND SNAPS MADE SO SORTED
DEC B TONE LESS TO SORT
JR NZJNEXTS
RT

COMPARE
PUSH HL TSAVE REGISTERS
PUSH DE
PUSH BC
COMPARS : :COMPARE STRINGS
TONE POINTED BY THE HL PAIR
;AND ONE POINTED BY
;THE DE PAIR
200 Machine code miscellany

L0 A (DE) GET CHARACTER


SUB (HL) COMPARE AGAINST THE
SAME ONE IN
THE SECOND STRING
JR NZ BYEFC NOT EOUAL EXIT FROM
COMPARISON
INC POINT TO NEXT CHARACTER
INC POINT TO NEXT CHARACTER
DEC REPEAT UNTIL COMPARED
ALL CHARACTERS
JR NZ COMPARS

BYEFC POP RESTORE REGISTERS


POP
POP
RET

FSHAP THE THO STRINGS POINTED


IBY THE HL PAIR AND THE DE PAIR

PUSH SAVE REGISTERS


PUSH
PUSH

LD A (SIZE) GET SIZE


LD PLACE IN THE LOH BYTE
OF THE COUNTER
LD NOT LARGER THEN 255

LD DE BUFF DE POINTS TO THE BUFFER


LDIR MOVE THE STRING FROM HL
TO THE BUFFER

POP PUT ORIGINAL HL IN DE


PUSH

LD GET COUNTER
LDIR MOVE TO SECOND STRING

L0 HL BUFF POINT TO BUFFER


LD GET COUNT
LDIR AND SNAP
Machine code miscellany 201

LD (FLAG).A ISIGNIFY A SNAP HAS MADE

POP HL FRESTORE REGISTERS


Pm’ DE
POP BC
RET

BUFF: DS 255 ,"BUFFER


FLAG: DB 0 ; SNAP FLAG
SIZE: DB B i SIZE OF STRING
END

Hexadecimal Listing

700B 2A 48 5C 7E FE BB 28 1C
7DB8 FE C1 CA 3B 7D E6 EB FE
701B 60 28 21 FE EB 28 11 FE
7D18 A0 28 14 23 5E 23 56 23
7D2B 19 C3 B3 7D CF B1 CF B2
7D28 11 13 BB 19 C3 B3 7D 23
7D30 CB 7E 28 FB 11 B6 BB 19
7D38 C3 B3 7D 23 23 23 7E FE

7D4B B2 2B E3 23 46 23 7E A7
7D48 2B DC 23 4E 23 7E A7 2B
7058 D5 23 79 32 A7 7E C5 AF
7D58 32 A6 7E E5 E5 59 16 BB
7D6B 19 EB E1 CD 77 7D DC 87
7D68 7D EB 10 FB E1 C1 3A A6
7D7B 7E A7 C8 B5 2B EB C9 E5
7D78 D5 C5 1A 96 2B B5 23 13

7D8B 0D 2B F7 C1 D1 E1 C9
7D88 D5 E5 3A A7 7E 4F B6 §i'.'3 EL!’
7D90 11 A7 7D ED BB D1 D5 4F
7D98 ED BB 21 A7 7D 4F ED BB
7DAB 32 A6 7E E1 D1 C1 C9 BB
7DA8 0B BB 0B B0 B0 BB BB BB
7DBB BB BB BB BB BB BB BB BB
7DB8 BB BB BB BB BB BB BB BB
.1 i___I_

202 Machine code miscellany

RECURSION
This program is similar to the music routine given in Chapter 9 but is
slightly more elaborate and complex. The tune l have given is the
one I translated (from the Spectrum manual) from the section on the
BEEP command. You can however write your own music. See the
table given in Chapter nine. The routine is called by setting the ix
register to point to the music data. The data represents the notes to
be played and the duration. Each note and duration is represented
by two bytes making a total of four. The first two bytes make up the
frequency of the note and the second two the duration. The nice
thing about this music routine is that it has the ability to play
substrings of music. The routine scans first of all for the frequency in
the table. lf the low byte of the frequency is a one then this indicates
that the following two bytes are the address of a substring to be
played. The end of a string of music is indicated by having the byte
0. Substrings can be nested to many levels dependent on the RAM
you have left. The whole principle behind this routine is that of
recursion. It's a routine which calls itself, in the same way as BASIC
subroutines can.
Assembler Listing
ORG 320000

BEEPER EOU 03B5H IADDRESS OF BEEPER ROUTINE


L0 IX.FRERE IPOINT TO MUSIC
CALL PLAY ;AND PLAY IT SAM!
RET
PLAY:
PUSH IX ISAVE STRING POSTION
LD L.(IX+0) FLOH PITCH
LD H.(IX+1) IHIGH PITCH
L0 E.(IX+2) ILON DURATION
L0 D,(IX+3) IHIGH DURATION
LD A,L ILOOK AT LON PITCH
CP 01
JR Z.PLS ;PLAY SUBSTRING
JR C.BYE IZERO SO BYE
CALL BEEPER IPLAY NOTE
POP IX ;GET STRING POSTION
LD DE.4 INEXT NOTE AND DURATION
ADD IX.DE
JR PLAY IKEEP PLAYING SAM!
Machine code miscellany 203

PLS:
INC IX i POINT
INC IX I TO RETURN POSTION
INC IX
to L.H i
ADJUST SUBSTRING ADDRESS
LD H,E l
POP AF ;GET RID or nto STRING
IADDRESS
PUSH IX IPUT IN NEH STRING ADDRESS

PUSH HL ITRANFER SUBSTRING


POP IX FADDRESS TO IX REGISTER
CALL PLAY IPLAY SUBSTRING
POP IX IRETURNED FROM PLAYING
ISUBSTRING
JR PLAY IKEEP PLAYING
BYE:
POP IX
RET

FRERE
DB 01
DEFN FRERE1
DB 01
DEFN FRERE1

FRERE1: DB 01
DEFN TUNE1
DB 01
DEFN TUNE1

DB 01
DEFH TUNE2
DB 01
DEFN TUNE2
_ 204 Machine code miscellany

DB 01
DEFN TUNE3
DB 01
DEFN TUNE3

DB 01
DEFN TUNE4
DB 01
DEFN TUNE4

TUNE1:
DEFH 66AH
DEFN 105H
DEFN 5B3H
DEFN 125H
DEFN 560H
DEFN 9BH
DEFH 5B3H
DEFN 92H
DEFN 66AH
DEFN 105H
DEFN 00

TUNE2:
DEFN 560H
DEFN 137H
DEFN 4C6H
DEFN 15DH
DEFN 43DH
DEFN IBBH
DEFN 00

L
T

it
Machine code miscellany 205

TUNE3:
DEFN 43DH
DEFN 126H
DEFN 3FFH
DEFN 67H
DEFN 43DH
DEFN 0C4H
DEFN 4C6H
DEFH BAEH
DEFN 560H
DEFN PBH
DEFN 5B3H
DEFN 92H
DEFN 66AH
DEFN 105H
DEFN 00

TUNE4:
DEFN 66AH
DEFN 105H
DEFN BPAH
DEFN 0C4H
DEFN 66AH
DEFN 20AH
DEFN 00
END
Hexadecimal Listing

7DBB l)D 21 41 .70 (DD BE? J70 [39


7DB8 I30 Efii IDD 6E1 001 IJD 66- 01
7D1B DD 5Ef BI! IDD 561 l33 JTD ITE
7018 B1 263 BE I38 21 (ID Bfii 032
7D2B IDD E1 11 Bil 001 DD 19 18
7D28 DF' l)D I23 l)D I23 IJD I23 T60
7D30 =63 F1 l)D IE5 IE5 IDD E1 [ID
7D38 BE! 7D IJD E1 18 [IA IJD E1
206 Machine code miscellany

7D4B C9 B1 47 7D B1 47 7D
7D48 5F 7D B1 5F 7D at 75
7D5B 01 75 7D 01 83 70 B1
7D58 7D 01 A1 7D B1 A1 7D
7D60 06 B5 B1 E3 B5 I."£"i B1
7068 B5 98 BB 83 B5 92 BB
7D7B B6 B5 B1 B0 B0 6B 05
7078 B1 C6 B4 5D B1 3D B4
7D80 B1 BB BB 3D B4 26 B1
7D88 B3 arr BB 3D B4 C4 BB
7D9B 04 AE BB 6B 05 98 BB
7D98 B5 P:-2 BB 6A B6 B5 B1
7DAB BB an B6 05 01 9A B8
7DA8 BB 6A B6 BA B2 BB BB
7D8B 63 F1 DD E5 E5 DD E1
7088 B8 70 DD E1 18 CA DD

7DCB C9 B1 47 7D B1 47 7D
7DC8 5F 7D B1 5F 70 B1 75
7DDB 01 75 7D B1 83 7D B1
7DD8 7D B1 A1 70 B1 A1 7D
7DEB B6 B5 B1 83 B5 25 B1
7DE8 05 98 0B 83 B5 92 BB
7DFB 06 B5 01 BB BB 6B B5
7DF8 B1 C6 B4 5D B1 3D B4
Appendix 1
Z80 instructions listed
by mnemonic
8E 142 ADC A,(HL)
DD 8E dd 221 142 dd ADC A,(IX'd)
FD 8E dd 253 142 dd ADC A,(IY'
8F '43 ADC A,A
88 '36 ADC A,B
89 '37 ADC A,
8A ‘$8 ADC A,
8B '39 ADC A,
8C '40 ADC A,
39 141 ADC A,
CE XX 206 XX ADC A, Zl_JIl" I@(")
ED AA 23? 74 ADC HL,BC
ED SA 23? 90 ADC HL,DE
ED 6A 237 106 ADC HL,HL
ED 7A 237 122 ADC HL,SP
86 134 ADD A,(HL
DD 86 dd 221 134 dd ADD A,(IX'd)
FD 86 dd 253 134 dd ADD A,(IY'd)
8? 135 ADD A,A
30 128 ADD A,B
81 '29 ADD A,
82 130 ADD A,
33 '31 ADD A, l"l"l@f"}
84 '32 ADD A,H
85 133 ADD A,L
C6 XX '98 XX ADD A,N
09 9 ADD HL,BC
19 25 ADD HL,DE
29 41 ADD HL,HL
39 57 ADD HL,SP
DD 09 221 9 ADD IX,BC
DD 19 221 25 ADD IX,DE
DD 29 221 41 ADD Ix,Ix
DD 39 221 57 ADD IX,SP
FD 09 253 9 ADD IY,BC
Append|x1- Z80 IHSUUCUOHS listed by mnemonic

253 25 ADD IY,DE


253 41 ADD IY,IY
253 57 ADD IY,SP
166 AND (HL)
221 166 dd AND (IX'd)
253 166 dd AND (IY'd)
16? AND A
<60 AND B
261 AND c
*e2 AND
'63 AND
'64 AND
'35 AND
230 XX AND
203 7U BI“ (HL)
dd 46 221 203 dd 70 BIT (IX'd)
dd 46 253 203 dd 7U BI’ (IY'd)
203 71 BI-
203 64 BI“
203 65 BIT
203 66 BI7
203 67 BIT CJ CJ 7|CI lC| lZ|-:Im<:I \w.\‘sWua-5.
|' |\: Ir*:tI J=-
203 68 BIT D,H
203 69 BI” U,L
203 78 BI“ ,(HL)
dd 4E 221 203 dd 78 BI“ (IX'd)
dd 4E 253 203 dd 78 BIT ‘\\ (IY‘d)
203 79 B17 '\-\-A-A ,A
203 72 BI“ ,,B
203 73 BIT
203 74 BIT
203 75 BIT
203 76 BI“
554\

203 77 BI“ I

\
"In\ II‘l'lU
"\‘Q 1"‘l_')
203 86 BI" ,(HL)
dd 56 221 203 dd 86 BIT (IX'd)
dd 56 253 203 dd 86 BIT (IY‘d)
203 87 BI“
203 80 BI"
203 81 BI“
203 82 BI’
203 83 BI‘
203 84 BIT
203 85 BI- |'\J l'\J|.Il'\JI)l"\J l'\J \‘\
"\ |"_':l I"l'Uf"')UJI=I
‘In‘U\\"\*\
Appendix 1 -Z80 instructions listed by mnemonic 209

203 96 BI ,(HL)
dd 5E 221 203 66 94 BI (IX'd)
dd 5E 253 203 66 94 BI (IY'd)
293 95 BI A
203 as BI B
33 s9 BI
33 90 BI D
33 91 BI E
l'\JI\JI'\Ji\J 33 92 BI
up-

H
2D3 93 BI
II-

L
203 102 BI
In

(HL)
dd 66 221 203 dd 102 BI
-F-

(IX'd)
dd 66 253 203 dd 102 BI
1

(IY'd)
203 103 BI
—n

203 96 BI
Z

203 97 BI
Q

2E3 9s BI
I

2C3 99 BI
-0:

2C3 100 BI
203 101 BI L
203 110 BI
*-

(HL)
dd 6E 221 203 dd 11D BI (IX'd)
dd 6E 253 203 dd 110 BI‘F
,(IY'd)
203 '11 BI
-‘—

,A
203 104 BI
-pp

B
203 '05 BI
203 106 BI
203 10? BI
203 108 BI
q-

2C3 '09 BI
y
L
203 116 BI
qua

(HL)
dd 76 221 203 dd 118 BI (IX'd)
dd 76 253 203 dd 118 BI (IY'd)
233 '19 BI
i

233 "2 BI

D3 13 BI
-F

up-

D3 BI
D3 BI
D3 _\ \1
J1\ sJ
O\
U1-I‘-‘~ BI T
I\Jl'\)l\J|'\JI\J D3 "7 BI T In
r-:n| munIUntI JI>'l Ut'1ED>
233 '26 BI ,(HL)
dd 7E 221 203 dd 126 BI
-—

(IX'd)
dd 7E 253 203 dd 126 BI
To

\\\\ \ '\ '\.- \ -.\ \-(IY'd)


203 12? BI
Z

\|1-~o0 -~ou1.n-| u1 ;~4=>\+ -;wu4m ,A


Appendix1 -Z80 instructions listed by mnemonic

78 203 120 BIT


79 203 121 BIT
7A 203 122 BIT
7B 203 123 BI“
7C 203 124 BIT
7D 203 125 BIT -\.l"-l'\ l'-| ~.l |"'I|'l10r':tD
XXXX 220 XXXX CA__ fixx w*6,NN
s
XXXX 252 XXXX CA;L M,NN
XXXX 212 XXXX CA__ NC,NN
XXXX 205 XXXX CA__ NN
XXXX 196 XXXX CA__ NZ,NN
XXXX 244 XXXX CA_L P,NN
XXXX 236 XXXX CA_L PE,NN
XXXX 228 XXXX CALL P0,NN
XXXX 204 XXXX CALL Z,NN
63 CCF
190 CP (HL)
BE dd 221 190 dd CP (IX'd)
BE dd 253 190 dd CP (IY'd)
191 CP A
184 CP B
185 CP C
186 CP D
187 CP E
188 CP H
189 CP L
XX 254 XX CP N
A9 237 169 CPD
B9 237 185 CPDR
A1 237 161 CPI
B1 237 177 CPIR
47 CPL
39 DAA
53 DEC (HL)
35 dd 221 53 dd DEC (IX'd)
35 dd 253 53 dd DEC (IY'd)
61 DEC A
5 DEC B
11 DEC BC
13 DEC C
21 DEC D
27 DEC DE
29 DEC E
37 DEC H
Appendix 1 —Z80 instructions listed by mnemonic

43 DEC
221 43 DEC
253 43 DEC
45 DEC
59 DEC
243 DI
16 XX DJNZ N
251 EI
227 EX (SP),HL
221 227 EX (SP),IX
253 227 EX (SP),IY
8 EX A ,AF'
235 EX DE,HL
217 EXX
118 HALT
237 70 IM 0
237 86 IM 1
237 94 IM 2
237 120 IN A
219 XX IN A,(N)
237 64 IN B, C
237 72 IN C,
237 80 IN
237 88 IN
237 96 IN
237 104 IN I" :C|'TI'C7
52 INC
221 52 dd INC (IX'd)
253 52 dd INC (IY'd)
60 INC
4 INC
3 INC
12 INC
20 INC
19 INC
28 INC
36 INC
35 INC
221 35 INC
253 35 INC
44 INC
51 INC
237 170 IND
237 186 INDR
___—_ _L l __ i. I

Appendix 1 —Z8lii instructions listed by mnemonic

A2 237 162 INI


B2 237 178 INIR
233 JP (HL)
E9 221 233 6P (IX)
E9 253 233 CP (IY)
XXXX 218 XXXX 6P C,NN
XXXX 250 XXXX CP M,NN
XXXX 210 .P NC,NN
XXXX 195 XXXX JP NN
XXXX 194 XXXX JP NZ,NN
XXXX 242 XXXX LP P,NN
XXXX 234 XXXX LP PE,NN
XXXX 226 XXXX LP P0,NN
XXXX 202 XXXX JP Z,NN
XX 56 XX QR C,N
XX 24 XX 0R N
XX 48 XX QR NC,N
XX 32 XX NZ,N
XX 40 XX z,u
XX 14 XX c,u
2 _ (BC),A
18 L (DE),A
; (HL),A
L (HL),B
U U OUZJSU (HL),C
(HL),D
(HL),E
\I\A
\1
\~\
u—
4tr
(HL),H
-_\_.\-31_a-1
-1._.\ ON U1
Usl
PU
"0
"~-1'-\ 1 (HL),L
XX 54 xx (HL),N
77 dd 221 "9 -— (1x'6>,
70 dd 22' '12 (IX'd),
71 dd 22' "3 1 (IX'd),
72 dd 22' '14 -I- (IX'd),
73 dd 22' 115 i <1x'6>,
74 dd 221 1'6 1 <1x'6>,
75 dd 22' '17 can (IX'd),
36 dd 221 54 dd XX @- <1x'6)
77 dd 253 1'9 F‘
F4[T@U UC7¢QU@‘U' U @ (IY'd),
70 dd 253 112 _D (IY‘d)
71 dd 253 1'3 LD (IY'd),
72 dd 253 114 LD (IY'd),
73 dd 253 115 LD (IY'd),
74 dd 253 '16 LD (IY'd) "-4\5Zl'"lU'J3="Zl':E"lUI"JCDJ*
Appendix 1 —Z80 instructions listed by mnemonic

75 dd 253 117 dd ;D (IY'd),L


36 dd XX 253 54 dd XX _D (IY'd),N
XXXX 50 XXXX LD (NN),A
43 XXXX 237 67 XXXX LD (NN),BC
53 XXXX 237 83 XXXX LD (NN),DE
XXXX 34 XXXX (NN),HL
63 XXXX 237 99 XXXX (NN),HL
22 XXXX 221 34 XXXX (NN),IX
22 XXXX 253 34 XXXX (NN),IY
73 XXXX 237 115 XXXX (NN),SP
10 ,<sc>
26 ,(DE)
126 1 ,(HL)
7E dd 221 126 dd 1 ,(IX'd)
7E dd 253 126 dd 1 ,(IY'd)
XXXX 58 XXXX I- (NN)
'27 1

'20 1

'21 2
'22 1

'23
'24
57 237 87
125
XX 62 XX q-

5F 237 95 1

70 -1 (HL)
A

46 dd 221 70 dd -- (IX'd)
46 dd 253 70 dd (IY'd)
71 l'_|_
F“F‘
4‘

64
65
66
67
68
69
XX 6 XX UQWU @U' CUG U U U UJClt1UJIEDUJI>Z1 J3> J=-> J=-> \ s~4\- s\' \ ZIUr—ZI-:Hlrn:Ur‘1fiEC1U'J>
4B XXXX 237 75 XXXX LD BC,(NN)
XXXX 1 XXXX LD BC,NN
78 LD C,(HL)
4E dd 221 78 dd LD c,<1x'6)
4E dd 253 78 dd LD ,(IY'd)
79 LD
72 LD ('>¢'>(") ‘\\WED
Appendix 1 - Z80 instructions listed by mnemonic

73
74 l_

75 _

76 -|—

77
86 -— (HL)
56 dd 221 86 dd 1 (IX'd)
56 dd 253 86 dd (IY'd)
87
80 rs
81
82
83
84
85 ¢_

XX 22 XX F4
5B XXXX 237 91 XXXX ,(NN)
17 XXXX ,NN
94 ,(HL)
5E dd 221 94 dd FA
c
i ,(IX'd)
5E dd 253 94 dd ,(IY'd)
95 @-

88
89
90
91
92
93
XX 30 XX
102 F (HL)
66 dd 221 102 dd in (IX'd)
66 dd 253 102 dd L (IY'd)
103 -_

96 L
97
98
99 to

100 F

F
101 to
XX 38 XX Zr"I|2'r1“ICl'r:‘I<flZt.|I7-J¢r"l>=|U:-lJP_‘fiZ=IJl- '2l1=U-i"‘:
XXXX 42 XXXX ,(NN)
6B XXXX 237 107 XXXX _ JZI IMFH MFHI1F rfl FHU' 27I;U' C7|-Ur'€\7t>F'Js¢>-t"b<x' msrx1 's~x4-a\n.~4,(NN)
\'\ \
XXXX 33 XXXX _ HL,NN
47 237 71 U QU CFU UQC7IU U WU QIJ5'U@ "-Z7'U '@C7¢@ U 'W@U I,A

iii‘
Appendix 1 -Z80 instructions listed by mnemonic

2A XXXX 221 42 _ IX,(NN)


21 XXXX 221 33 XXXX IX,NN
2A XXXX 253 42 IY,(NN)
21 XXXX 253 33 XXXX to IY,NN
110 _,(HL)
6E dd 221 110 dd L,(IX'd)
6E dd 253 110 dd _,(IY‘d)
;'A
'11
'04 _,B
'05
'06 1

107 1
u_

'08 0-»

'09
XX 46 ts: \\\
4F 237 79 1
R, 3:-Zr-:lrn<:vr>
7B XXXX 237 123 XXXX —-n SP,(NN)
U@U QU CU @U'CU U

249 D SP,HL
-l_

F9 221 249 1D SP,IX


F9 253 249 D SP,IY
'-—

XXXX 49 XXXX D SP,NN


A8 237 168 LDD
B8 237 184 LDDR
AO 237 160 _DI
BO 237 176 _DIR
44 237 68 NEG
0 NOP
132 OR (HL)
B6 dd 221 182 dd OR (IX'd )
B6 dd 253 182 dd OR (IY'd )
'63 OR A
'76 OR B
'77 OR C
'78 OR D
179 OR E
'80 OR H
'31 OR L
XX 246 XX OR N
BB 237 187 OTDR
B3 237 179 OTIR
79 237 121 OUT (C),
41 237 65 OUT (C),
49 237 73 OUT (C),
51 237 81 OUT (C), UCWUJP
Appendix 1 — Z80 instructions listed by mnemonic

59 237 89 (C),E
61 237 97 3
I

1 (C),H
69 237 105
ann-

(C),L
XX 211 XX 10-

(N),A
AB 237 171 1

CDQQOO tit,
L
—II

A3 237 163 0'-


241 POP AF
193 POP ac
209 POP DE
225 POP HL
E1 221 225 POP 1x
E1 253 225 POP 1v
245 PLSH AF
197 PLSH ac
213 PLSH DE
229 PLSH HL
E5 221 229 PLSH 1x
E5 253 229 PUSH IY
86 203 134 RES O,(HL)
CB dd 86 221 203 dd 134 RES E,(IX'd)
CB dd 86 253 203 dd 134 RES U,(IY'd)
87 203 135 RES 3,4
80 203 128 RES 0,5
81 2E3 '29 RES c,c
82 2C3 130 RES 2,0
83 203 131 RES 3,2
84 203 132 RES D,H
85 2C3 +33 RES o,L
8E 2C3 '42 RES ’,(HL)
CB dd 8E 221 203 dd 142 RES ’,(IX'd)
CB dd 8E 253 203 dd 142 RES ’,(IY'd)
8F 233 "43 RES '1!A
88 203 <36 RES 1,5
89 203 *3? RES ,c
8A 263 138 RES ,0
8B 2C3 139 RES 3__\—\ ,5
8C 233 '40 RES
,,H
8D 203 <41 RES ?,L
96 2&3 '50 RES 2,(HL)
CB dd 96 221 203 dd 150 RES 2,(IX'd)
CB dd 96 253 203 dd 150 RES IY'd)
97 203 151 RES
90 203 144 RES
91 203 145 RES l'\J|"\J|'\J'l\.J N"i
‘in‘\i'>UJI =-rx

_-L-_
Appendix 1 - Z80 instructions listed by mnemonic 217

203 146 RES


203 147 RES
203 148 RES .'I I'T'|U

203 149 RES L


203 158 RES <51.)
U~l|'\JPUl'\Jl\J \*5\
"'5‘Q

dd 9E 221 203 dd 158 RES 3,(IX'd)


dd 9E 253 203 dd 158 RES 3,(IY'd)
203 '59 RES 3,4
233 152 RES 3,5
ZD3 '53 RES 3,
203 '54 RES 3,
203 '55 RES 3,
203 '56 RES 3, IFHUCW
233 '57 RES 3,L
203 '66 RES A,(HL)
dd A6 221 ZO3 dd 166 RES 4,(IX'd)
dd A6 253 203 dd 166 RES 4,(IY'd)
203 '67 RES 4,4
203 160 RES 4,5
203 '61 RES 4,
203 162 RES 4,
203 '63 RES
203 '64 RES
203 '65 RES
203 174 RES (HL)
dd AE 221 203 dd 174 RES (IX'd)
dd AE 253 203 dd 174 RES (IY'd)
2C3 '75 RES
253 '68 RES
253 169 RES
233 '70 RES
203 171 RES
2C3 '72 RES
2G3 '73 RES u1r u1' on\.Lnu1 -I> \-t \ \~.- ~\s\ |-1Im-|"rc'~r:?-r">:lIJ >
233 '82 RES 6,(HL)
dd B6 221 203 dd 182 RES 6,(IX‘d)
dd B6 253 203 dd 182 RES 6,(IY'd)
2E3 183 RES 6,A
2C3 176 RES 6,B
2C3 '77 RES 6,
2C3 '78 RES 6,
253 '79 RES 6,
53 180 RES 6,
I\lI\) 33 181 RES 6, |_'J'Il' lU(")
Appendix 1 - Z80 instructions listed by mnemonic

BE 203 190 Res 7,(HL)


CB dd BE 221 203 dd 190 RES 7,(1x'
CB dd BE 253 203 dd 190 Res 7,(IY'
BF 203 191 Res 7,A
B8 203 184 Res
B9 203 185 RES
BA 203 186 RES 'xl'-l"-l xxx Ohm
BB 203 187 RES ?,e
BC 203 188 Res 7,H
BD 203 189 Res 7,L
201 RET
216 RET c
248 Re" M
208 Re" NC
192 Re" NZ
240 RE‘ P
232 Re" PE
224 RET P0
200 RET 2
4D 237 77 RETI
45 237 69 RETN
16 203 22 R_ (HL)
CB dd 16 221 203 dd 2O Re (IX'd)
CB dd 16 253 203 dd 20 _ (IY'd)
17 203 23 2 A
1D 203 16
11 203 17 1

12 203 18 1

13 203 19 1

14 203 20 u_

15 203 21 nu.

23
O6 203 6 _ (HL)
CB dd O6 221 203 dd 6 _ (IX'd)
CB dd O6 253 203 dd 6 _ (IY'd)
O7 203 7
OO
O1
O2
O3 ‘1F‘Iii
O4 l\I|'\JI'\JI"xJI'\J F1f“lC)CJC3
O5 20 U-lL.I~|LN\.NLAlL!~l U‘!-F*U~l'\J—\@ r-:1rnw¢->lIJ=-
7 J=-I-mwnnl
6F 237 111 Fflinu mizumzuim ui zum Un n n n n nr

-1-|fl._
Appendix 1 — Z80 instructions listed by mnemonic 219

1E 203 3O RR (HL)
CB dd 1E 221 203 dd 30 RR (IX'd)
CB dd 1E 253 203 dd 3D RR (IY‘d)
'F 253 31 RR A
'8 253 24 RR B
203 25 RR C
203 26 RR D
203 27 RR E
2:13 28 RR H
_.\ -x a Ul"JCD3='\O 253 29 RR L
31 RRA
DE 203 14 RRC (HL)
CB dd OE 221 203 dd 14 RRC (IX'd)
CB dd DE 253 203 dd 14 RRC (IY'd)
CF 203 15 RRC A
13 8 203 8 RRC B
D9 203 9 RRC C
GA 203 10 RRC D
DB 203 11 RRC E
C1 C 21:3 12 RRC H
OD 253 13 RRC L
15 RRC A
67 23? 103 RRD
199 RS- 0
215 RS7 1O
223 RS7 18
231 RS“ 20
239 RS7 28
24? RST 30
255 RS7 38
20? RS7 8
155 SBC A,(HL)
9E dd 221 158 dd SBC A,(IX'd)
9E dd 253 158 dd SBC A,(IY'd)
'59 SBC A,A
'52 SBC A,B
153 SBC A,
154 SBC A,
'55 SBC A,
'53 SBC A,
'5? SBC A, |_ICFl'lU("‘)
XX 222 XX SBC A,N
42 237 66 SBC HL,BC
52 23? 82 SBC HL,DE
Appendix 1 - Z80 instructions listed by mnemonic

62 237 98 SBC HL,HL


72 237 114 SBC HL,SP
55 SCF
C6 203 198 SE‘ U,(HL)
CB dd C6 221 203 dd 198 SET ,(IX'd)
CB dd C6 253 203 dd 198 SE" 1L:J
J,(IY'd)
C7 233 '99 SE” I,A
CD 2G3 '92 SE’ L,B
C1 2G3 '93 SE7
‘FT
1“,
C2 2C3 '94 SET
C3 283 '95 SE” CJ
_il
it

C4 233 '96 SE7


1|‘!

1-I,
\xI
‘x FT‘!QI5

C5 2G3 '97 SE“ E,L


CE 203 2C6 SE“ ',(HL)
CB dd CE 221 203 dd 206 SET T,(IX'd)
CB dd CE 253 203 dd 206 SE“ ',(IY'd)
CF 203 2C7 SE7
,!A
C8 203 260 SET A,B

C9 203 211 SE" 1,¢


CA 203 232 SET ,,D
CB 203 203 SE* ,,E
CC 203 204 SE7 ,'H
CD 203 205 SE-
,,L
D6 203 2'4 SE“ ,(HL)
CB dd D6 221 203 dd 214 SET (IX'd)
CB dd D6 253 203 dd 214 SE“ ,(IY'd)
D7 203 2'5 SE“
DD 203 268 SET
D1 203 SE“
D2 2C3 SE“
D3 2C3 SET
x1
xifi
D4 203 l'\Jl\Jl'\JI'\J l\J-\@'~O SE“ H
D5 203 2'3 SE’ L
DE 2D3 222 SE- (HL)
CB dd DE 221 203 dd 222 SE“ (IX'd)
CB dd DE 253 203 dd 222 SE” (IY'd)
DF 203 223 SE7
D8 203 216 SE“
D9 203 217 SE“
DA 2G3 218 SE-
DB 2C3 219 SE“
DC 2G3 220 SET
DD 2C3 221 SE“
E6 203 230 SET P~WiflLN U4lWML HhJR)NIUFHJR NIU '\"\' "'\|‘\ "\‘ \"\‘ \ m:ownmt#n~urs'>I-:»mn HL)

_‘
Appendix'l -Z80 instructions listed by mnemonic 221

DD CB dd E6 221 203 dd 230 SE’


FD CB dd E6 253 203 dd 230 SET ,(IY'd)
CB E7 203 231 SE"
CB ED 203 224 SET
CB E1 203 225 SE“
CB E2 203 226 SET
CB E3 203 227 SE”
CB E4 203 228 SE“
CB E5 203 229 SE“
CB EE 203 238 SE’ (HL)
DD CB dd EE 221 203 dd 238 SE” (IX'd)
FD CB dd EE 253 203 dd 238 SE’ (IY'd)
CB EF 203 239 SET A
CB E8 203 232 SE" B
CB E9 203 233 SET
CB EA 203 234 SE"
CB EB 203 235 SE’
CB EC 203 236 SE-
CB ED 203 237 SE’ L
CB F6 203 246 SE“ (HL)
DD CB dd F6 221 203 dd 246 SE’ (IX'd)
FD CB dd F6 253 203 dd 246 SE” (IY'd)
CB F7 203 247 SE“
CB FD 203 240 SE‘
CB F1 203 241 SE7
CB F2 203 242 SE7
CB F3 203 243 SE-
CB F4 203 244 SE'
CB F5 203 245 SET L
CB FE 203 254 SE7 (HL)
DD CB dd FE 221 203 dd 254 SET (IX'd)
FD CB dd FE 253 203 dd 254 SE' (IY'd)
CB FF 203 255 SE7
CB F8 203 248 SE7
CB F9 233 249 SE”
CB FA 233 250 SET
CB FB 203 251 SE“
CB FC 203 252 SE“ WP
m°’“
"'IwP
IWm:zzmio-n1mIUO>vtfi
CB FD 203 253 SE“ fl'“J\|Nfl"dO\~0@i>EChO\~&mnL\flAhU1w"\\mnC\'5‘\
U\"\"\'\
1P"\'\
-‘\"'11\\
b4\*5"\
'\>‘\‘hi
"'\$*¥\~#-P "0\
\\'\ L
CB 26 203 38 SLA (HL)
DD CB dd 26 221 203 dd 38 SLA (IX'd)
FD CB dd 26 253 203 dd 38 SLA (IY'd)
CB 27 203 39 SLA A
CB 2O 203 32 SLA B
222 Appendix1 -Z80 instructions listed by mnemonic

CB 21 203 33 SLA C
CB 22 203 34 SLA D
CB 23 203 35 SLA E
CB 24 203 36 SLA H
CB 25 203 37 SLA L
CB 2E 203 46 SRA (HL)
DD CB dd 2E 221 203 dd 46 SRA (IX'd)
FD CB dd 2E 253 203 dd 46 SRA (IY'd)
CB 2F 203 47 SRA A
CB 28 203 40 SRA B
CB 29 203 41 SRA C
CB 2A 203 42 SRA D
CB 2B 203 43 SRA E
CB 2C 203 44 SRA H
CB 2D 203 45 SRA L
CB 3E 203 62 SRL (HL)
DD CB dd 3E 221 203 dd 62 SR_ (IX'd)
FD CB dd 3E 253 203 dd SR_ (IY'd)
CB 3F 203 63 SR_ A
CB 38 203 56 SR;
CB 39 203 57 SR F
CB 3A 203 58 SR_
CB 3B 203 59 SR_ l"T'lU<""5T

CB 3C 203 60 SR_ H
CB 3D 203 61 SRL L
96 150 SUB (HL)
DD 96 dd 221 150 dd SUB (IX'd)
FD 96 dd 253 150 dd SUB (IY'd)
97 '51 SUB A
90 '44 SLB B
91 145
92 A
t46
93 '47
94 148 O0U)U’)U5
95 '49 SL1'“6'-I
Ff
15-_

D6 XX 214 XX SL CUTCDWUJ
CD ZI_:l "|'lQ¢'5
EE XX 238 XX XOR N
AE 174 XOR (HL)
DD AE dd 221 174 dd XOR (IX'd)
FD AE dd 253 174 dd XOR (IY'd)
AF 175 XOR A
A8 168 XOR B
A9 169 XOR C
Appendix1 —Z8lil instructions listed by mnemonic 223

17O XOR
171 XOR
172 XOR
173 XOR |"'Il'l'l@
l
l Appendix 2
Z80 instructions
listed by opcode
O0 NOP
O1 XXXX XXXX LD BC,NN
O2 LD (BC),A
O3 INC 5c
O4 INC 5
O5 oec 5
O6 XX ‘.>< >< LD 5,R
O7 RLCA
O8 ex AF,AF'
O9 ADD HL,BC
OA
\OC \.lO'-U1I’-‘~U l"\J-—\lD
LD A,(BC)
OB 44x oec 5c
OC
\
INC c
OD
\
oec c
1
OE XX >< >< l_ ‘T ('1 ‘in Z

OF A RRCA
F
O ex
DJNZ N
\
1 ex
><>< ><>< >< >< LD DE,NN
\ ‘\-
O '\lOU'l-I3‘U~l‘\J—=~@ LD (DE),A
\
9 INC oe
\
2O INC 0
\
21 oec 5
\
XX 22 XX LD D,N
\
23 RLA
\
>< >< 24 XX JR N
\
25 ADD HL,DE
\
26 LD A,(DE)
_\
27 nec oe
3
28 INC e
\
29 oec e
N
XXI1 U .":m>\OCXI\lO .J'l-?~LNl\J 3O XX LD E,N
I‘
F 31 RRA
2 O XX 32 XX JR NZ,N
21 XXXX 33 XXXX LD HL,NN
22 XXXX 34 XXXX LD (NN),HL

b.
Appendix 2 - Z80 instructions listed by opcode 225

INC HL
Inc H
oec H
XX XX LD H,N
DAA
XX XX JR z,n
ADD HL ,HL
XXXX XXXX LD HL, (NN
DEC HL
INC L
oec L
XX LD L,N
CPL
XX XX JR nc, N
XXXX XXXX LD SP, NN
XXXX XXXX LD (nn ),A
INC SP
INC (H L)
DEC (H L)
XX XX LD (HL ),N
scr
XX XX JR c,n
ADD HL ,SP
XXXX XXXX LD A,( NN)
oec SP
INC A
oec A
XX XX LD A,N
CCF
_
;
_
_
i

i—n I I'- xx

—-

—-

-Q

UUUUU O O EU J CDUJEDC IU x x x x x r-xlIZl"I1Uf“!w>/"\|'_ZIl‘'1Ql'1w HL)


Appendix 2 - Z80 instructions listed by opcode

79 r_

80
81
82 1

83
2

—p

84
85 I-
86 i

87 1

88 -1

89 it

9O I-4.

91
92
93
94
95 I-
96
97
98
99 ‘-

1OO u—

101
102 ‘I-I IIII“FI-‘ *x.x.»,-Ix-I
103 Qu- I:l :lCE:l1nr nm mOwU<:Iws7 \:'r1
104 It
x x x x x x x Wx'J>"\lx_I‘1U¢">lIJ -"‘\I_Z l"1U'(JlI 1'=Iv"\l‘“JZ"'lUt“‘.1mI
105 _,C
106 ‘_ ;,D
'07 l_ _,E
'08 L,H
'09 _,L
'1O ;,(HL)
111 _,A
'12 (H;),B
'13 (HL),C
'14 (HL),D
'15 UQ W@U C7W@'U@ QCI 7QU U@ 'QU¢@C7@U C7U €7 (H_),E

116 D (H_),H
117 D (H;),L
118 H A LT
119 LD (HL),A
120 LD A,B
121 LD A,C
122 LD A,D

,|,-2:“-1"‘ -
Appendix 2 — Z80 instructions listed by opcode

23 LD A,E
24 LD A,H
25 LD A,L
26 LD A,(HL)
27 LD A,A
28 ADD A,B
29 ADD A,C
3O ADD A,D
31 ADD A,E
32 ADD A,H
33 ADD A,L
34 ADD A,(HL)
35 ADD A,A
36 ADC A,B
37 ADC A,c
38 ADC A,D
39 ADC A,E
4O ADC A,H
41 ADC A,L
42 ADC A,(HL)
43 ADC A,A
44 SLB
45 Sc
46
47 I

48
49
5O III
1
Ml

51 U)U’!LOU‘)U‘)U)
{F
I
If‘
'1 WwCU
TTU3W

52 SBC J5-2 >»-x|—Il'1: r'1ED


53 SBC A Ixx
54 SBC A,
55 SBC A, FTII-GFIW
56 SBC A,H
57 SBC A,
58 SBC A, ~1- I F ‘H-I

59 SBC A,A
6O AND 5
61 AND c
62 AND 5
63 AND e
64 AND H
65 AND L
66 AND (HL)
Appendix 2 - Z80 instructions listed by opcode

'37 AND A
'35 XOR B
'39 XOR
'70 XOR
'71 XOR
'72 XOR
'73 XOR |_:l'I!T'lUt">
'74 XOR (HL)
175 XOR A
'73 OR B
'77 OR C
'75 OR
'79 OR
150 OR
151 OR
152 OR /'x|_:Il'T'lU II: I-' at
153 OR A
'54 CP B
'55 CP C
153 CP
157 CP
155 CP
159 CP l_:lIlTlU
'90 CP ( HL)
191 CP A
'92 RET NZ
'93 POP BC
XXXX '94 XXXX JP NZ,NN
XXXX '95 XXXX JP NN
XXXX '93 XXXX CALL nz,nn
'97 PUSH BC
XX '98 XX ADD A,N
'99 RST U
200 RET Z
201 RET
XXXX 202 XXXX JP z,nn
XXXX 204 XXXX CALL Z,NN
XXXX 205 XXXX CALL NN
XX 206 XX ADC A,N
207 RST 8
208 RET NC
209 POP DE
XXXX 210 JP NC,NN
XX 211 XX our (N),A

.1-_
Appendix 2 - Z80 instructions listed by opcode 229

2,
XXXX XXXX CALL NC,NN
21 PUSH DE
XX 21 '.>< >< SUB N
2?
RST 10
2, RET C
O'\U‘l-I *-U~lI\J
2'7 EXX
XXXX 2'8 XXXX JP c,nn
XX 219 XX IN A,(N)
XXXX 220 XXXX CALL c,nn
XX 222 XX s5c A,N
223 RST 18
224 RET P0
225 POP HL
XXXX 226 XXXX JP P0,NN
227 ex (SP),HL
XXXX 228 XXXX CALL P0,NN
229 PUSH HL
XX 230 XX AND N
231 RST 20
232 RET PE
233 JP (HL)
XXXX 234 XXXX JP PE,NN
235 EX DE,HL
XXXX 236 XXXX CALL PE,NN
XX 238 XX XOR N
239 RST 28
240 RET P
241 POP AF
XXXX 242 XXXX JP P,NN
243 DI
XXXX 244 XXXX CALL P,NN
245 PUSH AF
XX 246 XX OR N
247 RST 30
248 RET M
249 LD SP,HL
XXXX 25D XXXX JP M,NN
251 EI
XXXX 252 XXXX CALL M,NN
XX 254 XX CP N
255 RST 38
O0 203 O RLC B
O1 203 1 RLC C
O2 203 2 RLC D
P, I Ii

230 Appendix 2 - Z80 instructions listed by opcode

CB 03 203 3 RLC
CB 04 203 4 RLC
CB D5 203 5 RLC
CB 06 203 6 RLC r"\|".'I|Tl I I- x./
CB 07 203 7 RLC A
CB 08 203 8 RRC B
CB 09 203 9 RRC C
CB OA 203 RRC D
CB OB 203 \
RRC E
CB DC 2C3 \
RRC H
CB OD RRC L
CB OE AAx
RRC (HL)
CB OF 1;‘ 1. 1-P'~LJ~l'\J—-15$ RRC A
CB 10 \
6 RL
CB '1 2C 1 7 R;
CB 2 18 RL
CB 19 R-
CB l"\J|\l|"'xJTUHJPJDJ LH LH UJLN HL 20
CB 2C3 21
CB 203 22 I l_' \_:

CB 2C3 23
CB - 2C3 24 I-U5U,T-U17:-D I-U

CB 2C3 25 RR f"iTI='/\|_:I f'IlU{".|m

CB 2C3 26 RR D
CB 203 27 RR E
CB 1 203 28 RR H
CB l 2C3 29 RR L
13;‘-x x x
CB 1 l'T1U(">mJ>\OD‘\JO-LflI'~LIl 2C3 3O RR (HL)
CB 1F 203 31 RR A
CB 20 203 32 S_
CB 21 203 33 S-
CB 22 203 34
CB 23 203 35
CB 24 203 36 F,
CB 25 233 37
CB 26 2C3 38 I l"' xx

CB 27 203 39 (/,‘IUJO"JU)O')U’J ID-3='J>Il J>I.'PI>J='


CB 28 203 40 SRA
CB 29 203 41 SRA
CB 2A 203 42 SRA U('7UJ3>¢"\l_Il'|U("Jm
CB 2B 203 43 SRA E
CB 2C 203 44 SRA H
CB 2D 203 45 SRA L
CB 2E 203 46 SRA (HL)
Appendix 2 - Z80 instructions listed by opcode 3

203 SRA A
203 SRL B
203 SRL C
203 SRL D
203 SRL E
203 SRL H
203 SRL L
203 SR_ (HL)
203 SRL A
203 BI-
233 BIT
233 BIT
233 BI‘
203 BI-
203 BIT
203 BIT I I- \_l

203 BIT
\CJCJO Q©C|D
203 BIT
I
2C3 BIT
BI- '1‘
203
203 BIT '5

203 BIT 1 x x x x x :|n1'-:7<'1l7J>/-rIF'W<'>UJ


all-_
203 BIT
203 BIT 1,<RL>
233 BIT 1,A
203 BIT 2,5
203 BI“ 2,c
203 BI- ,5
203 BIT ,e
203 BI“ ,5
2C3 BIT L
2C3 BIT HL)
203 BIT
203 BIT
203 BIT
203 BIT
233 BIT
203 BIT
203 BIT
203 BIT I P \l
203 BIT
203 BIT
203 BIT
2C3 BIT #~b-PLHUJWIALNUJMLHJNIUPRJN \\\\\‘'\\‘ Uf5m>f\|-IF|1Uf"lm>*‘\
P
Appendix 2 - Z80 instructions listed by opcode

63 2O 99 BIT
I‘
64 2C ITO BIT
F
65 2C 01 BIT -F"-l “-Ii“
1'
66 20 :1 2 BIT
F
67 20 03 BIT
68 2C 54 I
BIT
69 2C '1 :1 5 BIT
6A 2C :1 3 BIT
6B 2C '1 1:17 BIT
6C 2C I1
05 BIT
6D 2C J1
1:19 BIT U'lU'lU'lLflU'lLfl-P"'

6E 2C LH LNMLNHLN LN LN J ' 0 BIT L)


6F 2 C3 J- 1 BIT U1

70 2 D3 )- BIT 6
71 2 D3 )- BIT 6
72 D3 J1
BIT 6
73 03 Ii
BIT 6
74 03 J1
BIT
75 03 J1
BIT 0*-D"~
1 1 31 13 1 31
76 03 @'\IO\Ll'1-F"~'Lh|l"x.'l BIT L)
77 l\J|"'xlPU|"Jl'\.Jl"U 03 '9
F
BIT
78 2 D3 H
2O BIT
79 2 O3 F
21 BIT
2 33
F
7A 22 BIT
7B 2 03 I.
23 BIT
7C 2 33 I
24 BIT
7D 2 :13 I
25 BIT “xl “xl"\ xl“ O"~
7E 21 :13 F
26 BIT Ch
u'|
nxl-l=*- IIII
l_
I_' \-I‘x-I
7F 2133 I
27 BIT "'xl
2 :13
I 11

8O 28 RES
81 2 1 :13 *1‘
1 29 RES Ll)
L

2 1:13
,-
82 l 3O RES
F r
83 2 I 31 RES (J
L‘J
I‘
84 2 ‘id- 32 RES
85 2 1 33 RES
F ,-
86 2 1-L 34 RES L11
L11L—J I I- x.-I
4!‘ I
87 21 -cl» 35 RES
88 2 '1 36 RES
r Q)
x—x
89 2 CTJCT1Lil) LNU\lLNU~lU~lLNLN 37 RES
8A 2 [I1 3 ' 38 RES
F

8B 2 C3 '1 39 RES 1
8C 2 03 '1
4O RES
0'

/1
8D 03 41 RES
0'

I1 I
8E l'\Jl\l D3 42 RES ‘\' \' x\"'“‘u"\'| "\‘ "'\ x'\‘ /‘\l_IE'1Uf">mJ='\f-:Il1Qt"'JT:|7-l\_CfT1Wt->CU3='f‘\I_J:FflC7{'|]J:P"\I_FHU'¢Tim3>f\I_:|FH HL)

I-._
Appendix 2 - Z80 instructions listed by opcode 3

2 :13 RES
2 :13 RES
2 :13 RES
2 :13 RES
2 :13 RES
2 :13 RES
2 :13 RES
2 :13 RES
:13 RES
:13 RES
:13 RES
:13 RES
:13 RES 3
C) LN RES
:13 RES 3
:13 RES 3
:13 RES
:13
l'\J" l'\.} Jl"\ 'Jl\ 'Jl\ 'J RES
2 03 RES
2 :13 RES
2 :13 RES
:13 RES
RES
LDC) LMLN RES
:13 RES
33 RES
:13 RES
33 RES
:13 RES
:13 RES
D3 RES
:13 RES
D3 RES
33 RES
:13 RES
-D3 RES
1:13 RES
»:»3 RES 6
:13 RES
I\JPQl \JPfI\J P JF\lT‘Ui\JPd I\J FU til U1-I RES IIIII
I“
I“|-I“
I" \-I\-J5-I\-J‘\-I

2 :1 3 RES
2 :1 3 RES 7
2 :1 3 RES
2 :1 3 RES O-O~ 0-u10~*u1.n1~1-|=O\I>-lr4\=|~u4LNU-x\ xs\a-.~\lUL:~ls'\JI ‘~l\J'| I\Jfl—=~ UC'>OJ/\I"C.‘l'UFJIP/"\1l'UfiDJ>"\I_ZFflUf‘JCD>'\I_FT1Qt">UJPr‘\|“'IFlOED
Appendix 2 - Z80 instructions listed by opcode

BB 203 '87 RES 7


BC 203 188 RES
BD 203 139 RES
BE 203 '90 RES III FT" \. -I
BF 203 '91 RES
CD 233 :92 SET
C1 233 #93 SET
C2 D3 194 SET
C3 D3 '95 SET
C4 U3 :96 SET C
C5 D3 <9? SET (1
C6 l\Jl\Jl\J|\Jl'\J U3 "~98 SET Ci III I" \-I
C7 203 :99 SET
CB 200 SET
C9 D3 201 SET
CA U3 202 SET
CB 203 SET
CC 33 204 SET
CD 33 205 SET
CE L14L11L1421:6 SET III IT" u.»
CF 33 2:: SET
DO l'U‘~Jl'\ IJF' l\J' l\J 'T(tKI3
L1
.JLJ SET
D1 203 SET
D2 2G3 SET
D3 ZD3 SET
D4 2G3 SET
D5 2C3 SET
D6 253 SET III IT" \_z
D7 203 SET
D8 ZQ3 SET
D9 2C3 SET
DA 203 £14
CIr\1
(J\
4>~
CID
C23
KJ1
\£J
'“-D~J1
‘*4 SET
C3C]
\
AIx
~\
Ix4\4\
94\
4x
DB 9
ZO3 I\Jl\Jl\JPUTUI\JI\Jl"\JPUPUI'\JPU SET
DC 2G3 220 SET
DD 2C3
L 221 SET
DE 2D 222 SET II: FT" s.¢
DF 27 223 SET
ED 2 224 SET
E1 2L 225 SET
E2 2G 226 SET
E3 29 227 SET
E4 20 228 SET
E5 2C 229 SET
E6 2CL_Jt___L14LJJL14LJJL14
1
Lad
L11L14 230 SET (I1
4>~
II)(I3331. wsx sx sn\-xw \ - \~ fir—IlU<‘1m=-\rI'tU‘13=-rIFUOWZ1=~v'\|-IrU‘1EDl=-»~|Irnt:'*>EJZ=-r|In HL)
£41LadL14£14L14L14L14L24
III_
CI)
4>~4=~
r\J
r\JF\JF\Jr\JF\Jr\J
F\J
1-1
141
1~191
-J1--t-
"~J -F~
£>-
Appendix 2 - Z80 instructions listed by opcode 35

203 231 SE"


203 232 ss"
203 233 SE“
2C3 234 SE‘
2C3 235 set
263 236 SE"
203 237 SET
203 238 ss"
233 239 SE“
223 240 scf
2E3 241 SET
2C3 242 SE"
203 243 SE“
2&3 244 set
203 245 SET
233 246 ss"
203 247 sec
203 248 ss"
203 249 SE"
203 250 SE‘
203 251 set
203 252 ss"
203 253 ss"
233 254 SE“ \-I
\-I
\-I’ II I-1-|-
203 255 sst \I|J'l~ \'lO~ O~\ Ou1U \n.r|U1u -b\'-as\ \ \-xs s >,-|—Ir1<:'-CIJ:r=-».;—Ir1'|0n:lJ>"-rImonwib
227 9 ADD IX,BC
22? 25 ADD IX,DE
XXXX 22‘ 33 XXXX LD IX,NN
XXXX 22¢ 34 XXXX LD (NN),IX
22’ 35 INC IX
22’ 41 ADD 1x,1x
XXXX 22’ 42 LD IX,(NN)
22? 43 DEC IX
dd 22’ 52 dd INC (IX'd)
dd 22¢ 53 dd osc <1x'd1
dd XX 22‘ 54 dd LD (IX'd),N
221 57 ADD IX,SP
dd 22' 70 dd -0 B,(IX'd)
dd 22' 78 dd _o (IX'd)
“‘\

dd 22’ 86 dd 2 ,(IX'd)
dd 22¢ 94 dd _ ,(IX'd)
dd 22' 102 dd _ ,(IX'd)
dd 224 110 dd _ |“"Il'1"lU(") ,(IX'd)
dd 221 112 dd _ QUUUC7 (IX'd),B

I I I I I
v_ __ __ 7 7 7 7 _7

236 Appendix 2 - Z80 instructions listed by opcode

DD 71 dd 221 "'3 ul- (IX'd),


DD 72 dd 221 <<4 1 (IX'd) ‘I

DD 73 dd 221 1:5 (IX'd), ITIUFI


22' ..6
i

DD 74 dd (IX‘d),H
DD 75 dd 22' "? (IX‘d),L
DD 77 dd 22' *:9 @UUQUU (IX‘d),A
DD 7E dd 22' '26 _D A,(IX'd)
DD 86 dd 221 '34 ADD A,(IX'd)
DD 8E dd 22” :42 ADC A,(IX'd)
DD 96 dd 22' '50 SUB (IX'd)
DD 9E dd 22’ '58 SBC A,(IX'd)
DD A6 dd 221 '33 AND (IX'd)
DD AE dd 22* '74 XOR (IX'd)
DD B6 dd 221 '82 OR (IX'd)
DD BE dd 221 190 CP (IX'd)
DD E1 22' 225 POP IX
DD E3 22' 227 EX (SP),IX
DD E5 22' 229 PUSH IX
DD E9 22’ 233 JP IX)
DD F9 22' 249 LD sP,1x
DD CB dd 06 22’ 203 6 RLC (IX'd)
DD CB dd OE 22’ 2:3 14 RRC (IX'd)
DD CB dd 16 221 2:3 20 RL (IX'd)
DD CB dd 1E 22” 203 30 RR (IX'd)
DD CB dd 26 22' 2:3 38 SLA (IX'd)
DD CB dd 2E 22' 2:3 46 SRA (IX'd)
DD CB dd 3E 22” 2c3 62 SR_ (IX'd)
DD CB dd 46 22' 203 70 BIT O,(IX‘d)
DD CB dd 4E 22' 203 78 BIT 1,(IX‘d)
DD CB dd 56 22' 203 86 BIT 2,(IX‘d)
DD CB dd 5E 221 233 1
H 94 BIT 3,(IX'd)
DD CB dd 66 221 2G3 1 BIT 4,(IX'd)
DD CB dd 6E 22’ 293 BIT 5,(IX'd)
DD CB dd 76 221 203 BIT 6,(IX'd)
DD CB dd 7E 22' 203 BIT 7,(IX'd)
DD CB dd 86 22' 203 '34 RES O,(IX'd)
DD CB dd 8E 221 203 RES 1,(IX'd)
DD CB dd 96 22’ 203 RES 2,(IX'd)
DD CB dd 9E 22’ 203 RES 3,(IX'd)
DD CB dd A6 221 203 '66 RES 4,(IX'd)
DD CB dd AE 221 203 '74 RES 5,(IX'd)
DD CB dd B6 221 203 '82 RES 6,(IX'd)
DD CB dd BE 221 203 ’9O RES 7,(IX'd)
DD CB dd C6 221 203 '98 SET D,(IX'd)

-1-._
Appendix 2 — Z80 instructions listed by opcode 237

dd CE 221 2G3 dd 206 SET (IX'


dd D6 221 2G3 dd 214 SET ,(IX'd)
dd DE 221 2C dd 222 SE (IX'
dd E6 221 2C dd 230 SET ,(IX'd)
dd EE 221 2C dd 238 SET vi-ru~|r\.1-\ \-.
\- (IX'
dd F6 221 2C dd 246 sst 6,(IX'
dd FE 221 213 dd 254 SET 7,(IX'd)
237 64 IN B,(C)
237 65 out (C),B
237 66 sac HL,BC
XXXX 237 67 XXXX LD (NN),BC
237 68 use
237 69 RETN
237 7D IM 0
237 71 LD I,A
237 72 IN c,<c1
237 73 out <c1,c
237 74 ADC HL,BC
XXXX 237 75 XXXX LD BC,(NN)
237 77 RETI
237 79 LD R,A
237 80 IN o,(c1
237 81 out <c1,o
237 82 sac HL,DE
XXXX 237 83 XXXX LD (NN),DE
237 86 IM 1
237 87 LD A,1
237 88 IN E,(C)
237 89 out <c1,E
237 9D ADC HL,DE
XXXX 237 91 XXXX LD DE,(NN)
237 94 IM 2
237 95 LD A,R
237 96 IN H,(C)
237 97 out (C),H
237 98 sac HL,HL
XXXX 237 99 XXXX LD (NN),HL
237 103 RRD
237 I04 IN L,(C)
237 10 out (C),L
237 '03 ADC HL,HL
XXXX 237 FTC‘
XXXX to HL,(NN)
237
If
RLD
237
\ I‘
sac HL,SP
Appendix 2 - Z80 instructions listed by opcode

XXXX 237 '15 XXXX LD (NN),SP


237 '20 IN A,(C)
237 121 out <c1,A
237 122 ADC HL,SP
XXXX 237 '23 XXXX LD SP,(NN)
237 '30 LDI
237 131 CPI
237 '32 INI
237 '33 out:
237 '33 LDD
237 '39 CPD
237 '70 IND
237 171 outo
237 173 LDIR
237 '77 CPIR
237 '73 INIR
237 '79 OTIR
237 134 LDDR
237 '35 CPDR
237 '33 INDR
237 '87 OTDR
253 9 A00 IY,BC
253 25 A00 IY,DE
XXXX 253 33 XXXX LD IY,NN
XXXX 253 34 XXXX LD (NN),IY
253 35 INC IY
253 41 A00 IY,IY
XXXX 253 42 LD IY,(NN)
253 43 DEC IY
dd 253 52 dd INC (IY‘d)
dd 253 53 dd DEC (IY'd)
dd XX 253 54 dd XX LD (IY‘d),N
253 57 A00 IY,SP
dd 253 70 dd -0 B,(IY'd)
dd 253 78 dd ED (IY'd) ‘M
dd 253 86 dd _ ,(IY'd)
dd 253 94 dd _ ,(IY'd)
dd 253 19 dd _ ,(IY'd) I :I'TIU("J

dd 253 AIH0
dd _ L,(IY'd)
dd 253 dd ; (IY'd),B
dd 253 "3 dd 2 <IY'd1,c
dd 253 dd _ (IY'd),
dd 253
If
dd _ (IY'd),
dd 253 116 dd
l _ (IY'd),
WQU U CSFU I I TIU

lg
Appendix 2 - Z80 instructions listed by opcode 239

I
253 17 LD (IY'd),L
253 119 LD (IY‘d),A
253 '26 LD A,(IY'd)
253 '1'
34 ADD A,(IY'd)
253 '42 ADC A,(IY'd)
253 150 SUB (IY'd)
253
I
58 SBC A,(IY‘d)
253 l
'66 AND (IY'd)
253 '74 XOR (IY'd)
253 '82 OR ( IY‘d)
253 '90 CP (IY'd)
253 2 25 POP IY
253 2 27 EX (SP),IY
253 2 29 PUSH IY
253 2 33 JP IY)
253 2 49 LD SP,IY
253 2 C3 3 RLC (IY'd)
253 2 03 14 RRC (IY'd)
253 2 D3 20 RL (IY'd)
253 2 C3 30 RR (IY'd)
253 2 C3 33 SLA (IY'd)
253 2 l:l 3 43 SRA (IY'd)
253 2 23 32 SRL (IY'd)
253 2 D3 70 BIT O,(IY'd)
253 2 I3 73 BIT 1,(IY'd)
253 2 C3 33 BIT ,(IY'd)
253 2 03 94 BIT "- (IY'd)
253 2 23 '02 BIT ,(IY'd)
253 2 U3 110 BIT ,(IY'd)
253 2 03 '13 BIT O-U‘I-l1-\'L:Jr\J ,(IY'd)
253 2 03 '23 BIT 7,(IY'd)
253 2 D3 '34 RES O,(IY‘d)
253 2 C3 '42 RES 1,(IY'd)
253 2 C3 '50 RES 2,(IY'd)
253 2 I: 3 153 RES 3,(IY'd)
253 2 33 '33 RES 4,(IY'd)
253 2 D3 '74 RES 5,(IY'd)
253 2 1U 3 '32 RES 6,(IY'd)
253 2 C3 '90 RES 7,(IY'd)
253 2 C3 '93 SET O,(IY'd)
253 2D3 203 SET 1,(IY'd)
253 2 I1 3 214 SET 2,(IY'd)
253 2 U3 222 SET 3,(IY'd)
240 Appendix 2 — Z80 instructions listed by opcode

FD CB dd E6 253 203 dd 230 set 4,(IY'd)


FD CB dd EE 253 203 dd 238 set S,(IY'd)
l' FD CB dd F6 253 203 dd 246 set 6,(IY'd)
FD CB dd FE 253 203 dd 254 set ?,(Ir'd1

_-__
Appendix 3
Flag operation table
Flag table notation
Flags
- Flag is unchanged by operation.
Flag is affected according to result of operation.
P/V is set according to parity result.
PN is set according to the overflow result.
Flag is set to zero
Flag is set to one
Result of flag unknown.
1+—h=|t_A$<'U Contents of the interrupt flip flop.
Addressing
S Any 8 bit addressing mode A, B, C, D, E, H, L, (HL), (lX+dd)
UY+dm=
r Any 8 bit register A, C, D, E, H, L
b Bit number 0-7
RR Any16 bit register.
n Any 8 bit number

Flag operation table


Instruction C Z P/V S Instruction C ZP/VS
-1!- #
ADC Hl_,RR -31- il-
‘H: is:
=i=
ADC '3!- -11- -IE -x.

=i=
ADC -11- -Hr -2+ *-
CPDR -if

-X~ -IF \7
ADD 'K' -I6 -H- -K

il-
ADD A,n £- -)9
<<<<< -1+

AD HL,RR FF #- *- *=l = l= =t+E=l = *=| l= l= l= l=°#=l


AD SP,RR =l=
nrw TUTU 31!!
-if -11-
<<* 4(-

=i=
AD
AD '1!- *- il- *
')(-1

AN -7!- -11-
DEC s ~8- ii-

AN UULJUUU SE1?
-1+
IN r,(C) *- -IF

BIT -36-
§1ETUTU =|:|;
+1- Q QS SESES S eees INC s #-
<"o<'o *
S$—\
*$*
Ill‘-

M
_m2 M
p
UACp e D d _m 3
_
F _WO_/_ OPPNHas MN _mHE n t

Q r H C n St T u Cfi O n C Z WS N H
_
NN DI ## ## ## RR RRAC
__ DD OD
H
_‘
I *# 11 *

A
3
iPL
kl__,
__‘ NNDDDDDmm
DID _______
11**### ##f*f* ##
##*
* 119890 # D@@O RRRRRR £RLmR% HH LL J}
(£5555 #** * * PPPPPPP ******* DDDODO DODOOG
__***##
D
AA JR

R 0 #
mN mm _
*
#* OV #*
O

O1
D

0*
S LA
SS Mm
S

S5 ## * _ _ _ _ *_ _ * _VVVV
PPV * *_#_ _ _*#*
G

DO
H

DD

OR 0 * P * D D S BC H _|__ R R * *1 #
OOO RTT H 0____* *11**_ p_## *## @1111 @## SSSSS GBMUU 1 MlE
_fi_| 6*
DRTTDRI CBB AmSn ****
ASH *
3*
OOHUUA ##_ ##_ ## Q
H;___

0 D XO R 5 D P D
R L CA * D O XO R n 6 * P _____ 6 D
Appendix 4
Spectrum monitor-
assembler listing
ASEG
ORG 255660

JP FSTART
ALTER EIU 390
COHHA EHU ’,'

SAUEB: LD A1 GFFH
iIX POINTS TO START OF BLOCK
IDE CONTAINS NUMBER OF BYTES
BALL B4C2H
RET

LDADB: SCF
LD AIBFFH
CALL B556H
RET

HEADIN:
LD DE,17
LD IXIHEADER
XOR A
SCF
CALL B556H
LD A1(HEAOER+11)
LO B,A
LD A,’$’
LO (HEADER+11),A
CALL CRLF

LD DE1HEADER+1
CALL PRTSTR
A‘: 2
LD
CALL PRTCHR
244 Appendix 4 - Spectrum monitor-assembler listing

EX DE,HL
LD (HLLC
INC HL
INC HL
INC HL

LD A,(HL)
CALL HEXO
DEC HL
LD A,(HL)
CALL HEXO
DEC HL
A‘: .r
LD
CALL PRTCHR

LD AJHL)
CALL HEXO
DEC HL
LD A,(HL)
CALL HEXO

CALL CRLF
RET

HEADOUT
LD DE,17
LD IX,HEADER
XOR A
CALL B4C2H
RET

KEY: PUSH HL
PUSH BC
PUSH DE
CALL HAITS PAUSE FOR A HHILE
UAITK: LD A1(23611) LOOK AT FLAGS
BIT 5,A
IR Z1HAITK NO KEY PRESSED
RES 5,A RESET FLAG
LD (23611),A
POP DE

.1__
Appendix 4— Spectrum monitor-assembler listing 245

POP BC
POP HL
RET

GETKEY:
CALL KEY
LD A1(2356B) LOOK AT LAST-K
CALL PRTCHR
RET
OPENCH2:
, 1
LO A,B2 I OPENS CHANNEL S1
FOR PRINTING
CALL 1601H
RET
PRTCHR:
PUSH AF
PUSH AF
XOR A
LD (23692),A
POP AF
RST IBH
POP AF
RET
PRTSTR:
LO A,(DE) GET CHARACTER
CP lg!
IS THIS THE END
OF A STRING?
RET Z YES THEN RETURN
CALL PRTCHR PRINT CHARACTER
INC DE POINT TO NEXT CHARACTER
JR PRTSTR
FSTART:
LO SPJSTACK
CALL OPENCH2
LO DEIHUHE
CALL PRTSTR
LO DEIHELCHESS
CALL PRTSTR
CALL CRLF

UERYSTART:
INITU2: LD SPISTACK
LD A,B
LD (2365B)1A ICAPS ON
246 Appendix 4- Spectrum monitor-assembler listing

LD HLJERRSP
LO (HL),LOH(VERYSTART)
INC HL
LD (HL),HIGH(UERYSTART)
DEC HL
LO (23613).HL

INITU LO HLIINITU
PUSH HL

CALL CRLF
LD A,’ )’
CALL PRTCHR

START CALL GETKEY


IA!
SUB IS IT IN THE ALPHABET?
RET C IND
:S.r_:A:+1
CP
RET NC IND!
ADD A,A £32
LO HLIUECTBL
LO E,A
LO D,H
ADO HL,DE
LD E1(HL)
INC HL
LO D1(HL)
EX DE,HL
JP (HL) JUNP TO CONHAND

VECTBL:
DEFU ERROR
DEFN ERROR
DEFN ERROR
DEFN DUNP DUMP
DEFN MODIFY EDIT NEHORY
OEFU FILL FILL
DEFN GOTO GOTO
DEFN HUNT HUNT
OEFU IDENT IDENTIFY FILENAHE
DEFN ERROR
OEFU ERROR
Appendix 4 - Spectrum monitor-assembler listing 247

DEFN LOADBYTES ;LOAD FRON TAPE


DEFH NOUE NOUE A BLOCK
OEFH ERROR
DEFN ERROR
DEFN PUMP PRINT DUMP
DEFU ERROR
DEFN CHREG MODIFY REGS
OEFH SAUEBYTES }SAVE MEMORY

HAITS:
LO BCJBQBBH
LO DEIABODH
LO HL14OB@H
LDIR
RET

MODIFY
CALL GETEXPR1 GET START ADDRESS
NODIFB CALL HEXOD OUTPUT START ADDRESS
A’: 1
LO
CALL PRTCHR
LO A,(HL)
CALL HEXO
LO A’! I

CALL PRTCHR
PUSH HL
CALL HEXI
POP HL
LO (HL),A
INC HL
CALL CRLF
JR HODIFY LOOP UNTIL FORCED
OUT BY AN ERROR

GETEXPR2: ;GET THO UORD EXPRESSION


CAL L H EXD
PUSH HL ISAUE E1
248 Appendix 4- Spectrum monitor-assembler listing

A‘: I
LO
CALL PRTCHR
CALL HEXD
F PUSH HL
POP DE IE2
POP HL ;GET E1
RET E1=HL E2=OE

GETEXPR3:
CALL GETEXPR2
PUSH HL
PUSH DE
CALL GETEXPR1
POP DE
POP HL
RET

GETEXPR1:

A’! I
LO
CALL PRTCHR
CALL HEXD
PUSH HL
POP BC
CALL CRLF
RET E1=HL E2=DE E3=BC

LOADBYTES:
A’! 1
LO
CALL PRTCHR
CALL GETEXPR2

LO (DESTTIIHL

LO rn
OR
JP =’3’ ERRORS
I“

LO (LENTT),DE

LD DE1LOADNESS
CALL PRTSTR

1-__
Appendix 4 - Spectrum monitor assembler listing 249

LO OE1FILENANE
CALL PRTSTR

GETFILE:
CALL HEADIN

LO OEiHEAOER+1
LO HL.FILENAHE
LO B,1O

CONPF: LO A,(DE)
RES 5,A
LD C,(HL)
RES 5,C
CP C
JR NZ1GETFILE

INC HL
INC DE
DJNZ CONPF

LOAOIF: LO DE1(LENTT)
LO IXi(OESTT)
CALL LOAOB
RET

DESTT: DEFN O
LENTT: DEFN B

CR EDU OOH , RETURN


LF EOU BAH , LINEFEED
HELCHESS: DEFN CR,’#SBUG¥’
DEFN ’ (C) John H11s0n’
DEFN ' 1934.'
DEFN CR, ' 1'
SAUENESS: DEFN CR,'Press ang leg when readg$
250 Appendix4- Spectrum monitor-assembler listing

LOAOHESS: DEFH CR.’Haiting for S’


NOTHESS: DEFH CR,’ROUTINE NOT IHPLEMENTED$’
ERRHESS: DEFN CR,'8#ERROR##’,CR,’$’
NONE: DEFN 22,1,1,CR,’$’

SAUEBYTES:
A’! 1
LO
CALL PRTCHR
CALL GETEXPR2 ;GET 2 VALUES START
;AND NUMBER OF BYTES I
(H AOER 13),HL
ii
JP
A,E
O
ZJERRORS
"
LO (HEAOER+11),OE

LO DEISAUEHESS
CALL PRTSTR

CALL UAITS
CALL HAITS
CALL HAITS
CALL GETKEY

LO A,3
LO DEIHEADER
LO HL,FILENAHE
LO (OELA
INC DE

LO BC,1O
LDIR
CALL HEADOUT
CALL UAITS
CALL HAITS
CALL HAITS
LO IXi(HEAOER+13)
LO OE1(HEAOER+11)
CALL SAUEB
RET

1-__
Appendix 4 - Spectrum monitor assembler listing 251

HEXAS PUSH HL
CALL HEXO
A’: 1
LO
CALL PRTCHR
POP HL
RET

LINE: LO B,B
NBYTE LO %(HL)
CALL HEXAS
INC HL
DJNZ NBYTE
CALL CRLF
RET

DUMP:
A’! r
LO
CALL PRTCHR
CALL GETEXPR1
ALOCK LO C,B
BLOCK CALL HEXOO
A‘: 1
LO
CALL PRTCHR
CALL PRTCHR
CALL LINE
DEC C
JR NZ1BLOCK
CALL CRLF
CALL CRLF
CALL GETKEY
CP CR
JR ZIALDCK
RET

PINE: LO B,2!
PBYTE LO A,(HL)
CP 32
JR CISBOGBY_2
CP 128
JR C1SBOGGY
A‘:':
LO
252 Appendix4- Spectrum monitor-assembler listing

SBOGGY: CALL PRTCHR


INC HL
DJNZ PBYTE
CALL CRLF
RET

PUMP:
A’: I
LO
CALL PRTCHR
CALL GETEXPR1
PALOCK: LO C,B
PLOCK: CALL HEXOO
A‘: 1
LO
CALL PRTCHR
CALL PRTCHR
CALL PINE
DEC C
JR NZJPLOCK
CALL CRLF
CALL CRLF
CALL GETKEY
CP CR
JR Z,PALOCK
RET

ERROR: NOP
NOTIMP: PUSH OE
LO OE:NOTMESS
CALL PRTSTR
POP OE
RET

'ROUNTINES
IHEXO OUTPUT HEX NUMBER IN ACCUMULATOR
IHEXOD OUTPUT HEX UORD IN HL
IHEXI INPUT HEX NUMBER PUT IN ACCUMULATOR
IHEXD INPUT HEX HORD AND PUT INTO HL

1__
Appendix 4- Spectrum monitor-assembler listing 253

HEXOO:
LO A,H
CALL HEXO
LO A,L

HEXD:
LO E,A
SRL A 5 GET TOP FOUR BITS
INTO LOUER NYBBLE
SRL A
SRL A
SRL A
CALL CONV ICONVERT TO ASCII
IRETURNS ASCII VALUE IN A
LO AIE I GET ORIGINAL VALUE
AND OFH 5 MASK OFF LOHER FOUR BITS
ICONVERT LAST HEX DIGIT
CONV:
ADO A:3BH
CP 3AH 5 IS DIGIT IN RANGE B-9?
JP M,OECO :YES THEN PRINT AND RETURN
IIN THE RANGE IO-15 SO CONVERT TO A—F
ADO A,7
DECO: CALL PRTCHR IPRINT A HEX DIGIT
RET

ERRORS: JP VERYSTART

HEXI:
CALL GETKEY
CALL CONV2
LO E,A
CALL GETKEY
CALL CONV2
SLA E MOVE LOUER FOUR BITS UP
SLA E
SLA
SLA
OR l"|'!l"l1I'| l MERGE IN SECOND DIGIT
RET
CONV2: AND A
SBC A:3BH
CP BAH
‘I
Y

254 Appendix 4 - Spectrum monitor-assembler listing

RET C
AND A
SBC A,7
CP IOH
JR NC1ERRORS
RET

HEXD CALL HEXI


PUSH AF
CALL HEXI
LO L,A
POP AF
LO H,A
RET

FILL 'HL POINTS TO START ADDRESS


EOE POINTS END ADDRESS
BBC =NUMBER OF BYTES
A‘: I
LO
CALL PRTCHR
CALL GETEXPR2
A’! I
LO
CALL PRTCHR

PUSH HL
EX DE,HL
AND A CLEAR CARRY
SBC HL,DE
JP C:ERRORS
JP ZIERRORS
PUSH HL
POP BC

POP HL
PUSH HL
POP DE
INC OE

PUSH HL
PUSH OE
CALL HEXI

1—._
Appendix4- Spectrum monitor-assembler listing 255

POP DE
POP HL

LO (HLLA
LDIR
CALL CRLF
RET

RETGET POP OE ISET ORGINAL


LO HL.PUTREG
PUSH HL
PUSH DE
CALL GETREG
RET

GOTO:

All I
LO
CALL PRTCHR
CALL HEXD
PUSH HL IGUTD
AI: I
LO
CALL PRTCHR

FPOP ALL REGS VALUES


CALL GETKEY
CP CR
JR Z,RETGET
CP COMMA
JP NZIERRURS
CALL HEXD
PUSH HL
LO DEIBRKP
LO BC,3
LDIR ISAVE BYTES

POP HL
LO (HLJIDCOH
INC HL
LO (HL),LOH(BRK)
256 Appendix 4- Spectrum monitor-assembler listing

INC HL
LO (HL)1HIGH(BRK)
CALL GETREG
RET

PUTREG LO (SAVESP),SP
LO SP,AHLREG+2
EX AF,AF’
EXX
PUSH HL
PUSH DE
PUSH BC
PUSH AF
EXX
EX AF,AF’
PUSH IX
PUSH HL
PUSH OE
PUSH BC
PUSH AF
LO SP1(SAVESP)
RET

GETREG LO (SAVESP),SP
LO SP1AFREG
POP AF
POP BC
POP OE
POP HL
POP IX
EX AF,AF’
EXX
POP AF
POP BC
POP OE
POP HL
EX AF,AF'
EXX
LO SPITSAVESP)
RET

BRK: IPUSH ALL VALUES ON STACK


CALL PUTREG
Appendix4- Spectrum monitor assembler listing 257

POP HL RET ADDRS


DEC HL
DEC HL
DEC HL
FBACK SPACE 3 INSTR

CALL CRLF
LO A,’8’
CALL PRTCHR
CALL HEXOO
EX DEIHL IDEST
LO HLIBRKP
LO BC,3
LDIR PUT BYTES BACK

;PUT BACK FOUR BYTES


IOISPLAY PC
IOISPR
CALL OISPR
RET

OUTREG LO B,4
NXTREG LO E1(HL)
INC HL
LO Di(HL)
PUSH HL
EX DE,HL
OI1R: CALL HEXOO
Al: I
LO
CALL PRTCHR
CALL PRTCHR
POP HL
INC HL
DJNZ NXTREG
RET

OISPR: CALL CRLF


LO DEIREGMESS
CALL PRTSTR
LO HLIAFREB
CALL OUTREG
CALL IXOUT OO IX REG
CALL CRLF NON ALTERNATE
258 Appendix4- Spectrum monitor-assembler listing

CALL OUTREG
RET

IXOUT
DOING LO A,(HL)
PUSH AF SAVE LON BYTE
INC HL
LO $(HL)
CALL HEXD OUT HIGH
POP AF GET LOU
CALL HEXD AND OUT
INC HL
LO All I

CALL PRTCHR
CALL PRTCHR
RET

CHREG
IGETREG VALUE
A’: 1
LO
CALL PRTCHR
CALL GETKEY
CP ALTER
JR NZ,LOO
CALL GETKEY

ADO A,’I'-

LDD: LO HLILOOKUP
LO BC1LENTAB
CPIR
JP NZ1OISPR
DEC HL
LO OE1LOOKUP
AND A
SBC HLIDE
LO DEIAFREG
SLA L
ADO HL,DE
INC HL
Appendix4- Spectrum monitor assembler listing 259

A’: I
LO
CALL PRTCHR
LO Ai(HL) ;LON
CALL HEXD
DEC HL
LO A,(HL) HIGH
CALL HEXD
INC HL
A’: I
LO
CALL PRTCHR

CALL HEXI
LO IHLLA
DEC HL
CALL HEXI
LD (HL),A
RET
LOOKUP:
OB ‘A IIIBIIIDIIIHIIIXI
DB -fIIllJ'!'!LI‘IP-I

I A! BI DI HI
I

LENTAB EOU 9O

A’: I
MOVE: LO
CALL PRTCHR
CALL GETEXPR3

GETBC: PUSH HL
AND A
SBC HL,DE
JR NCJDSHDP
POP HL
EX OE: HL
JR GETBC
OSHOP:
;HL =NUMBER OF BYTES
IOE =START ADDRESS
IBC =DESTINATION
:(SP)=ENO ADDRESS
EX DE,HL
:OE =NUM HL=START
iBC=OEST
260 Appendix4- Spectrum monitor-assembler listing

PUSH BC SAVE OEST


PUSH OE ’ SAVE COUNT l
POP BC PUT IN OE
POP DE GET OEST

POP AF GET RID OF END


STACK CONTAINS START
PUSH HL GET START
HL CONTAINS START
DE DESTINATION
BC NUMBER OF BYTES
STACK CONTAINS
AND A
SBC HLIDE
POP HL
JR CIBACKU
LDIR
RET

BACKU:
ADO HLIBC
DEC HL
EX DE,HL
ADO HL,BC
DEC HL
EX DE,HL
LDDR
RET

IOENT:
LO A’! I

CALL PRTCHR
CALL GETKEY
CP OD
RET Z
CP 65
JP CIERRORS
LO HLIFILENAME
LO B,1B
LO C,32
CLBUFF LD (HLLC
INC HL
DJNZ CLBUFF

K ‘Q
Appendix4- Spectrum monitor-assembler listing 261

LO HL:FILENAME
LO B,9

PUTBUF LO (HL),A
DEC B
RET Z

INC HL
CALL GETKEY

CP OOH
RET Z

CP 65
JP C,ERRORS
JR PUTBUF

HUNT:
A’: 1
LO
CALL PRTCHR
CALL GETEXPR2
PUSH HL SAVE START
EX DEIHL
AND A
SBC HL,DE
JP CIERRDRS
JP ZIERRDRS
PUSH HL
POP BC
POP HL
A’: 1
LO
CALL PRTCHR

PUSH HL
PUSH OE
CALL HEXI
POP DE
POP HL
262 Appendix 4- Spectrum monitor-assembler listing

COMP: CP (HL)
PUSH AF
JR NZINFDUND '
CALL CRLF
CALL HEXOO
CALL GETKEY
CP OOH
JR NZ1BHUN
NFOUND:
INC HL
DEC BC
LD A,B
OR C
JR ZIBHUN
POP AF
JR COMP
BHUN:
POP AF
RET

CRLF: LO A,CR
CALL PRTCHR
RET
REGMESS:
OEFM ‘AF BC '
OOOO::OBBO::
OEFM ’DE HL ’
OEFM IX
DB CR, S
REGS:
AFREG DEFN OOOOH
BCREG DEFN OOOOH
DEREG DEFN OOOOH
HLREG DEFN OOOOH
IXREG DEFN OOOOH
AAFREG: DEFN OOOOH
ABCREG: DEFN OOOOH
AOEREG: DEFN OOOOH
AHLREG: DEFN OOOOH

BRKP: DB 5 S
SAVESP: DB SQ 5!: BE

__ 4»-_
Appendix 4 - Spectrum monitor-assembler listing 263

HEADER: OS 17
FILENAME
OS 13
DB CR,’$'

OS 75
STACK: DB O
ERRSP: DEFN O

END
_ 2'-rt--~ —"- '

i
\-_ .

I’

- T.-r
Ah-;_. _ _ - ‘=0’?-3.‘:-‘k
-1.
Index

A C
Accumulator '|9,29,31 CALL 21 ,38-39
ADC 32-34 Carry flag 19,32/11,70
addition 29-32,79 cassette recorder 56
addressing 10 loading/saving ‘I03-114
register indirect 27 CCF 70
index 27 channel routines 94-114
indirect 369 Clock program 150-155
ports 54 comments 15
screen 121-139 compare 51-52
relative 37 CPD 66
AND 59 CPDR 65
animation 127-129 CPI 66
A register see Accumulator CPIR 65
arithmetic operations 29-4D CPL 70
assembler 13-17,84—87
attribute file 121-139
D
Auto Line Number program DAA 7O
191-195
DEC 29,32-33
decimal system 9-11
B DEFB 14-‘I5
BASIC loader 78-78 DEFM 65
binary system 8-11 DEFS 15
BIT 53 DEFW 15
block compare 65-66 disassembler 14
block manipulation 64-71 DJNZ 37
block transfer 66-69
Dump (monitor) 73
monitor 75
border
scrolling attribute program E
85-95 Edit (monitor) 73
split colour program 144-‘I45 EQU 15
branching 51-52 error messages 39-4O
Brickout program 156-169
266 Index

F L
Fill memory (monitor) 74 labels 15
flags 19-20 Large Print program 183-188
floating point arithmetic 40 LDDR 67-68
ROM routines 115-120 LDIR 67
F register 19 loader program 77-78
loading operations 22-27
G monitor 75
Goto address (monitor) 74 ROM routines 103-114
logica.‘ operations 34,59-63
H
hexadecimal system 12-13 M
Hex Monitor 77-78 masking 55
H flag 20 Maze Generator program
HL registers 20 169-183
Hunt byte (monitor) 74 memory addressing 1
mnemonics 13,84
l mode1 interrupts 141
Identify filename (monitor) 75 mode 2 interrupts 141-144
IN 55 monitor 14
INC 29,32-33 program 72-84
index addressing mode 27 Move block (monitor) 75
indexing 30 multiplication 33,42,46-48,70
indirect addressing 30 music 99
input/output 53-58
instruction set N
AND 60 NEG 70
OR 62 negative integers 11-12
XOR 63 nesting 39
integers negative 11-12 N flag 19
interfacing 53-58 number systems 8-13
interrupt routines 18,140-155 nybble 13
I register 18
IX registers 18,30 O
IY registers 18,28,30 OR 62
OUT 56
‘.-

J output 56
JP 35
lump P
conditional 35 Parity overflow flag 20
relative 36 PC register 20
pixel
K scroll program 188-191
keyboard 54-55 POP 21
Index 267

port SCF 70
addressing 54 screen
reading 55 addressing 97
print ASCII (monitor) 76 file 121-139
printer 140 scrolling program 85-93
printing pixel scroll 188-191
large print 183-188 SET 52
ROM routines 94-97 shifting operations 44
to screen 127-129 signed integer representation
pseudo operators 14,65 11-12
PUSH 21 Sign flag 20
Sl_A 4-4
R Sort program 195-201
reading sound generation 57-58
keyboard 54-55 SP register 20
port 54 SRA 45
recursion 202-206 SRL 44
register indirect addressing 27 stack 21-22
Register modify (monitor) 76 streams 94
registers 17-28 SUB 31
pairs 17-18,20-24 subtraction 31-35,38
relative addressing 37
remarks 15 T
RES 53 tape loading/saving 103-114
RETURN 39 timing program 150-155
RL 42 toggling 62
RLC 41 Trace program 146-150
RLD 45 truth tables
ROM routines 94-120 AND 60
floating point 115-120 OR 61
printing 94-97 XOR 62
screen addressing 97 two's complement 12,70
tape loading/saving 103-114
rotating operations 41
V
RR 43
vectored processing 143
RRC 43
R register 18
X
S XOR 62
saving operations 27
monitor 77 Z
ROM routines 103-114 Z80 chip 9-14,17,19-21,23,25,27
SBC 32-34 Zero flag 20
—n

A hi.
More Pan/PCN Computer Library titles for the
Sinclair ZX Spectrum
Robert Erskine Er Humphrey Walwyn.
Paul Stanley Er Michael Bevvs
Sixty Programs for the Sinclair ZX
Spectrum £5.95 0 330 28260 3
A massive software library for the price of a single cassette. Explosive games.
dynamic graphics and invaluable utilities. this specially commissioned
collection takes BASIC to the limits and beyond.
Four of the country's best-selling software writers have pooled their talents to
bury programming cliches and exploit your micro's potential t0_the full.
Whether you are a games player or a more serious user. here's the book to
make your micro work for you.
r_ _-'_| l_ |‘I_l|'!‘-lL‘il iII|

You might also like