CrackingCodeZXSpectrum PDF
CrackingCodeZXSpectrum PDF
|
. \.;-'-_.
1 I" L 1
. ,-
|_ '.
Pan -
‘a
1
J-
_ _ 9075'"-|IEll LIBRARY _ *__ 1
__
—II|§L_
JOHN WILSON
I"""
w “
,'f‘
_z1:.,' 3- "-
A hi.
P /Personal Computer New
C mputerLibra1y
lohn Wilson
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
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:
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__
25 decimal
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.
Address... l __ - l 10110101
Add ress+1 10100010
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:
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
DB 02H,04H
DEFS 100
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
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:
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
Now to enter this machine code program the following BASIC pro-
gram Could be used:
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
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
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
POP BC
POP HL
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!
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
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
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
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:
F9 LD SP,HL
DD F9 LD SP,lX
FD F9 LD SP,lY
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)
32 LL HH LD (ADDRESS),A
L —
26 Chips, registers and numbers
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:
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:
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.
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
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
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
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>
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)
LD A,8
LD HL,6000H
ADD A,(HL)
Address Contents
6000H 02
6001 H 03
6002H 06
6003H 07
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
SUB B
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
ADC A,2
SBC A,3
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
LD HL,0432H
LD BC,0536H
ADD HL,BC
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
AND A
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:
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
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:
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:
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
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.
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:
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.
i
40 Number crunching
RST 08H
DB 08
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
.;_.__ m 7
42 Rotating and shifting
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
RLA RL (HL)
RL A RL (lX+d)
RL B RL (lY+d)
RL C
RLD
RLE
RLH
RLL
—-II
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 -- _ . —
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.
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
fiiljlilililsliliri
S SRA (HL)
is
SRA C
03> SRA (lX+d)
SRA (lY+d)
SRAD
SRAE
SRAH
SRAL
--I-7-I"---W-—
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
RLD (HL)
We would find that the contents of location 6888H and the accumu-
lator would be Changed to:
The instruction RRD (HL) has the opposite effect, as shown in the
diagram below:
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
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
MULT18
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
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 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
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.
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
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
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:
CP 128
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 n,r
SET n,(HL)
SET n lX+dd)
SET n lY+dd)
1-.we .- '\./'- t.
SET 4,A
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
BIT 7,A
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.
scans the keys 0 to 6 on the top row of the keyboard. The other
addresses and the keys they scan are given below:
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
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)
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
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:
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
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
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 —
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
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 (HL)
AND (IX+dd)
AND (lY+dd)
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
LD A,18181181B
OR 111888888
The above code would set the top three bits in the Accumulator.
18181181
OR 11188888
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
LD A,1
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:
IR TOG
6 Block manipulation
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
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.
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
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
I
| _._
DE—I-_
68 Block manipulation
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:
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
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
INC A
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:
4+1 =5
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
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
>E C080
C080 FF 3E
C801 00 2A
C002 80 C9
C083 88 <ENTER>
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:
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.
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
‘ .
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.
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:
>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:
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
>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.
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
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
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.
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.
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:
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.
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.
The content of the DE register pair is LOADed into the A register with
_..iI T
88 Program production
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.
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).
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.
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.
ENE)
ORG 30006
LD B,21
Ill llllllllll|"llI|
92 Program production
LD FPLACE DE INTO HL
LD fi1CI
INC IIF'II FIE‘I IHL POINTS ONE TO
FRIGHT OF DE
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
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,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
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
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:
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 "
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
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!
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
ORG 32000
JP START
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
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
HEADER: OS 17
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-__
__.. ,
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
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
NANT:
LD DEISAVEO IPROMPT FOR ANSNER
LD BCISIZO
CALL PRXSTRING
Using the ROM routines 111
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
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
A*B+C*D/2
A B * C D 2/ * +
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
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
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:
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:
The calculator has five constants available in the ROM used for cal-
culating sines and cosines:
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
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
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
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
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-_
__-
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.
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
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
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
n-_
Screen and attribute handling 127
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.
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.
-__
Screen and attribute handling 129
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
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
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
MOVEMENT ROUTINE
‘IIInn
\-
I
I
I
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
PUSH BC
CALL PRTCHR
POP BC
RET
LD IXJSHIP
L__
Screen and attribute handling 133
SCROLL:
SRL A SCROLL DATA DOHN TO BIT
POSTION
RR C
DJNZ SCROLL
LD
ADD ?’3* oar- hJ=2 NEXT CHAR LINE DOWN
(WITHIN SECTION)
LD L,A
RET NC CHAR WITHIN SECTION
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-@
_-__
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
UPD:
CALL PRINOBJ
DEC B
JP UPDAA
DOWND:
CALL PRINOBJ
INC B
JP UPDAA
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;_
-_|
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
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
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
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
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
IM 2
LD A,CDH
LD I,A ;I REGISTER IS LOADED WITH HIGH
BYTE OF TABLE
El
KEYBROU:
RET
PRINROU:
RET
n-_
Interrupts on the Spectrum 143
device to RETURN a valid data vector with its lowest bit set to zero i.e.
always even!
ORG OCOH
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.
‘E
1-1-I-
El ;ENABLE INTERRUPT
RET ;RETURN FROM INT
OR El
RETI
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
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;
ORG 323390
ITRACE ROUTINE
FFOR 16K SPECTRUM
TRACE DI
PUSH AF SAVE REGS
PUSH BC
PUSH DE
PUSH HL
PUSH IX
LD DE,163B4
CALL CONV PRINT NUMBER ON SCREEN
INC DE
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
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
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
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
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
A
(FRAMES),A
SO IHAVE WE COUNTED THROUGH
:1 SEC?
NZ,PRCLOCK iNO,SO PRINT TIME ANYWAY
A ;GET FRAMES
(FRAMES),A ;TO ZERO.
PRCLOCK
IROUTINE TO PRINT THE CLOCK ON THE SCREEN
TIMLIM: DB OflH,OOH,13H
HRS: DB I
J
MINE: DB
SECS: DB i
.II
END
Hexadecimal Listing
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
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
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
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
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
¥
--
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
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"**
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
#1
-i
The routine SETUP is called only once: at the start of each new game.
It is used to draw the bricks on the 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
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
LD BC. O
CP 39H ;HAVE HE HIT A YELLOH BRICK
JR NZ, NTYLN :NOT YELLOH
Machine code miscellany 165
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?
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. . .
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’
END
MAZE GENERATOR
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"'
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
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
Assembler Listing
ORG 38668
JP START
XPOS: DB 3
YPOS: DB O
PATH: DB B
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
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
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
TGO EAST
L
Machine code miscellany 177
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
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!
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
PRINTC
HL SAVE REGISTERS
BC
BUILDM
HLIBUILD POINT TO ARRAY BUILD
A INTIALIZE THE X CO-ORD
(XPOS),A AND Y CO-ORD
(YPOS),A
START:
CALL INTMAZE ICLEAR MAZE
CALL BUILDM ;BUILD MAZE
CALL DISPLAY TDISPLAY MAZE
RET
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”
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
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
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 —_
LD HLIDUGD
PUSH HL
POP IX : EX HL NITH IX REG
LD B,B ; DATA COUNT
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
DUGD: DS B82
END
Hexadecimal Listing
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
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!
ORG 320000
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
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
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
L I
Machine code miscellany 191
ADD ¢h2GH
L0 L,A
RET C :00 NOT ADJUST SECTOR SINCE
IUE HAVE GONE OVER
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
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
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
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
OUTP2:
L0 (LASTK),A PLACE CHAR IN LASTK
LD HL,FLAGS SIGNIFY HE
SET i(HL) PRESSED A KEY
RET
Machine code miscellany 195
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
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
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
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
SORT:
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
LD GET COUNTER
LDIR MOVE TO SECOND STRING
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_
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
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
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
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
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
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
'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
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_
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
_-L-_
Appendix 1 - Z80 instructions listed by mnemonic 217
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
1-I,
\xI
‘x FT‘!QI5
_‘
Appendix'l -Z80 instructions listed by mnemonic 221
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
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
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
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 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
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
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"'
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
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
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 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
_-__
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
=i=
ADC -11- -Hr -2+ *-
CPDR -if
-X~ -IF \7
ADD 'K' -I6 -H- -K
il-
ADD A,n £- -)9
<<<<< -1+
=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
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
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
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
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
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
RET C
AND A
SBC A,7
CP IOH
JR NC1ERRORS
RET
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
GOTO:
All I
LO
CALL PRTCHR
CALL HEXD
PUSH HL IGUTD
AI: I
LO
CALL PRTCHR
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
CALL CRLF
LO A,’8’
CALL PRTCHR
CALL HEXOO
EX DEIHL IDEST
LO HLIBRKP
LO BC,3
LDIR PUT BYTES BACK
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
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
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|