.........1.........2.........3.........4.........5.........6.........7.........8

Mastering Machine Code on Your Spectrum
part 2 of 8 - from ZX Computing Dec'82/Jan'83

In the last issue of ZX Computing, Toni Baker, author of
"Mastering Machine Code on Your ZX81", opened up the topic
of machine code on the Spectrum. Here, she continues the
discussion, concluding her venture into the realms of
registers, addresses and other mysteries.


In this issue, I'll attempt to take your level of machine
code knowledge up to a point where at least you know what it
is and how to make programs out of it. In the next article I
shall leave the mechanics of programming alone, and start to
concentrate on the ideas behind sticking instructions
together in the right order without getting lost.


Machine Code

The brain of the ZX Spectrum is a little black chip called a
Z80A - this is the device which carries out machine code
programs. Contrary to popular belief, NO part of the
Spectrum will carry out BASIC programs. There is a chip
(called the ROM) which effectively "is" Spectrum BASIC, but
the ROM itself is not a brain - the ROM is a very big
machine code program - and no more.

To be a little more precise, the Z80A chip mentioned above
is actually a brain without a memory, and the memory of the
Spectrum has to come on separate chips. Let's take a closer
look at memory, and how it affects machine code.


Using memory

There are many ways to think of memory. Some people relate
it to numbers written on pieces of paper and stored in
matchboxes or jam jars. A more logical approach assumes a
knowledge of programming - at least in BASIC - and so this
is the approach I shall use.

You are familiar, I take it, with the BASIC concept of an
array. Imagine then the effect of the statement DIM M(100).
This then gives you a series of different variables called
M(1), M(2), M(3), and so on up to M(100). Machine code
memory is organised a little like this. A dimension
statement is not needed (and does not exist) because the
memory arrangement is already set up in advance, but the set
up is as follows. Memory is a series of one-byte variables,
(that is to say variables which can each store any number
between 00 and FF) which are called (0000), (0001), (0002),
and so on up to (FFFF(. Notice I've written them in brackets
because they are like elements of an array, but without any
preceding letter - this is because the array has no name -
it doesn't need one because there is only one such array in
existence in machine code.

Because memory is set up in advance, much of it is already
used by the computer. This has absolutely nothing to do with
the Z80A, it is simply a result of the way that the memory
is wired up. (This makes it Sinclair's fault). It is used as
follows.

0000-3FFF are already filled with various numbers, and in
fact form a machine code program. You cannot change any of
these addresses even if you want to - for instance the
machine code instruction LD (02D4),A will simply not be
carried out (although it will take the same amount of time
to execute as LD (42D4),A which would work). These addresses
are called ROM.

4000-5CB6 are addresses which all have a fixed purpose. For
instance, (4000) stores the first eight pixels on the TV
screen, and (5C8D) stores current colours (as used by PRINT
statements in BASIC), and so on.

Depending upon the context, something like (ABCD) can mean
one of two different things. Either:

(i) The contents of address ABCD (exactly as you'd expect).
or
(ii) It can also mean (ABCD) + 100*(ABCE) defined as in (i).

To make this clear, suppose that address ABCD stores the
byte F3 and that address ABCE stores the byte 4A.

Then by writing (ABCD) we could mean either the number F3,
or the number 4AF3. Exactly which of the two forms we mean
can be deduced fairly easily from the context. For instance
'LD A, (ABCD)' must mean 'LD A, F3' since the A register can
only hold one byte, whereas 'LD HL,(ABCD)' must mean 'LD
HL,4AF3' since the HL register pair must hold two bytes.

5CB7 to (5C65)-1 are all addresses which are used by the ROM
for varying purposes. Note here that (5C65)-1 means (5C65) +
100*(5C66) - 1. The absolute value of this address will vary
from time to time.

(5C65) to SP-1 are spare addresses not used by the ROM. You
can use these for any purpose you choose - eg. 'LD (7000),A'
is generally quite sensible. Note though that:

(i) The bytes at the start of this region are likely to be
continually overwritten by the ROM.

(ii) The bytes at the end of this region will definitely be
overwritten by something called an 'interrupt routine' which
I shall talk about in the next article.

SP is a two-byte machine code register which I shall dwell
on a bit more further on.

SP to (5CB2) is something called the MACHINE STACK which I
shall explain in greater detail further on.

(5CB2)+1 to (5C7B)-1 is spare and can be used in machine
code.

(5C7B) to (5CB4)-1 are used by the ROM to store each of the
user defined graphics.

(5CB4) to 7FFF if you have 16K or FFFF if you have 48K are
all spare addresses and can be used by us. If you have only
16K then addresses 8000 to FFFF do not exist.


Storing numbers

Enough of all that boring drivel. Let's turn our attentions
to something constructive. Firstly, here are all the
different ways of storing numbers on the Spectrum.

Instructions like LD C,42 you already know about, so let's
see what else we can do. I'll use some abbreviations here:
the small letters m, n, p, and q to represent single bytes,
and combinations mn and pq to represent byte pairs.

LD A,(pq) Only the A register may be used in this way.

LD (pq),A The reverse operation. Again only the A register
may be used like this.

LD BC,(pq) Only register pairs BC, DE and HL may be used in
this way.

LD (pq),BC Ditto.

The following combinations can NOT be made:

LD (qp),m
LD (pq),mn
LD (pq),(mn)


The stack

The Stack, or "machine stack" as it is sometimes referred
to, is a highly useful piece of memory organisation. It does
not have a BASIC equivalent. Imagine, if you would, a stack
of cardboard boxes. We may only alter this stack in two ways
- we can place more boxes on top, or we can remove boxes
from the top. What we cannot do is to insert boxes into the
middle, or to remove boxes from the middle. The machine
stack is very similar to this idea, except that it uses
numbers instead of cardboard boxes, for although cardboard
boxes would probably be more fun, they wouldn't fit in the
case of the Spectrum. It consists of a sequence of numbers.

You can place new numbers at the end of the list, and you
can remove numbers from the list. Each number in the list is
two bytes long.

To spot the usefulness of the stack it is best to show by
example. This program will exchange the values of register
pairs BC and DE - notice how it works:

PUSH BC Stack the number currently held in BC.

PUSH DE Stack the number currently held in DE.

POP DE Remove the number at the top of the stack and assign
to BC.

POP DE Remove the number at the top of the stack and assign
to DE.

The words "push" and "pop" are a delightful pair of words -
almost as much fun as PEEK and POKE in fact. PUSH means
append a new number to the list, and POP means remove the
most recently PUSHed number from the list.

The actual location of the stack is somewhere very high in
memory. The computer keeps track of things with a machine
code register called SP (Stack Pointer). SP is a two-byte
register, just like BC or HL, however, unlike these two it
cannot be separated into its two constituent bytes.
Unfortunately, for some reason as yet unknown to me, the
instruction LD HL,SP does not exist, so if you ever want to
know the exact value of SP you need two separate
instructions: LD HL,0000 / ADD HL,SP. What does SP do? I
hear you ask! It simply stores the address of the item at
the top of the stack - this register is updated
automatically every time either PUSH or POP is used.


Arithmetic

The simplest arithmetic instructions are INC (increment) and
DEC (decrement). INC D means increase D by one, DEC HL means
decrease HL by one, and so on. You should notice however the
following phenomena: if D contains the byte FF then INC D
will change the value of D not to 100 (for it cannot contain
a value that large) but to 00; similarly, if HL contains
0000 then DEC HL will "decrease" it to FFFF.

What we can't do, although I'm sure we'd all like to, is to
be able to say LD A,B+C or LD BC,3*HL+1, almost as we do in
BASIC. Unfortunately, such luxuries are beyond us, and 'LD'
can only ever transfer the value of a register, a constant,
or the contents of an address. Arithmetic is restricted to a
few basic specialised instructions. In order to understand
arithmetic we first need to introduce a new "register"
called the CARRY FLAG.


The carry flag

A FLAG is very similar to a REGISTER except that where a
register may hold any value between 00 and FF, a flag may
only hold the number zero or the number one. A very, very
important flag - as far as arithmetic is concerned - is the
CARRY FLAG. I shall denote this flag by the letter K to
avoid confusion with the C register. (Please note that this
is not a standard convention, and that to my knowledge
nobody uses this representation except me).

The need for the carry flag is made apparent by additions
like 93 + E8. The correct answer is of course 17B, however,
no single register on its own can store numbers that large.
If A contained the number 93, and B contained the number E8,
then "ADD A,B' (at first sight equivalent to the BASIC
statement LET A = A + B) could never store the correct
answer in the A register alone. The CARRY comes in as
follows. I shall write KA to mean the "register pair" formed
by K (the carry flag) and A (the A register). If the result
of such a subtraction turns out to be negative you should
add 200 to KA, or 20000 to KHL, as the case may be. In other
words, "LET KA = 04 - 07" means "LET KA = 200 + 04 - 07" (or
1FD) rather than simply minus three.

Some other instructions you should know are:

AND A meaning LET K = 0
SCF   meaning LET K = 1
CCF   meaning LET K = 1 - K

Some quite useful things to know are:

SBC A,A   means IF K = 0 THEN LET A = 00
                IF K = 1 THEN LET A = FF
AND A / SBC HL,BC means LET KHL = HL - BC
ADD A,B   means LET KA = A + B
ADC A,B   means LET KA = A + B + K
ADD HL,BC means LET KHL = HL + BC
ADC HL,BC means LET KHL = HL + BC + K
similarly
SUB A,B   means LET KA = A - B
SBC A,B   means LET KA = A - B - K
SUB HL,BC does not exist
SBC HL,BC means LET KHL = HL - BC - K


Machine Code

Multiplication and division instructions do not exist in
machine code, but we shall see how we may get around this in
a later article. In the next part of this series I shall
conclude my explanation of all machine code instructions,
and begin to discuss how they may be usefully put together
into PROGRAMS. In the meantime, here are four tables which
between them tell you the hexadecimal codes for all of the
machine code instructions, even the ones you don't know
about. The tables are reproduced from my book MASTERING
MACHINE CODE ON YOUR ZX81 - please keep them even though you
may not understand them all as yet, for they will not be
repeated.


- Table 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

r           B      C      D      E      H      L      (HL)   A      (IX+d)   (IY+d)   n
----------------------------------------------------------------------------------------------
ADD A,r     80     81     82     83     84     85     86     87     DD86dd   FD86dd   C6nn
ADC A,r     88     89     8A     8B     8C     8D     8E     8F     DD8Edd   FD8Edd   CEnn

AND r       A0     A1     A2     A3     A4     A5     A6     A7     DDA6dd   FDA6dd   E6nn

BIT 0,r     CB40   CB41   CB42   CB43   CB44   CB45   CB46   CB47   DDCBdd46 FDCBdd46 -
BIT 1,r     CB48   CB49   CB4A   CB4B   CB4C   CB4D   CB4E   CB4F   DDCBdd4E FDCBdd4E -
BIT 2,r     CB50   CB51   CB52   CB53   CB54   CB55   CB56   CB57   DDCBdd56 FDCBdd56 -
BIT 3,r     CB58   CB59   CB5A   CB5B   CB5C   CB5D   CB5E   CB5F   DDCBdd5E FDCBdd5E -
BIT 4,r     CB60   CB61   CB62   CB63   CB64   CB65   CB66   CB67   DDCBdd66 FDCBdd66 -
BIT 5,r     CB68   CB69   CB6A   CB6B   CB6C   CB6D   CB6E   CB6F   DDCBdd6E FDCBdd6E -
BIT 6,r     CB70   CB71   CB72   CB73   CB74   CB75   CB76   CB77   DDCBdd76 FDCBdd76 -
BIT 7,r     CB78   CB79   CB7A   CB7B   CB7C   CB7D   CB7E   CB7F   DDCBdd7E FDCBdd7E -

CP r        B8     B9     BA     BB     BC     BD     BE     BF     DDBEdd   FDBEdd   FEnn

DEC r       05     0D     15     1D     25     2D     35     3D     DD35dd   FD35dd   -

IN r,(C)    ED40   ED48   ED50   ED58   ED60   ED68   -      ED78   -        -        -

INC r       04     0C     14     1C     24     2C     34     3C     DD34dd   FD34dd   -

LD B,r      40     41     42     43     44     45     46     47     DD46dd   FD46dd   06nn
LD C,r      48     49     4A     4B     4C     4D     4E     4F     DD4Edd   FD4Edd   0Enn
LD D,r      50     51     52     53     54     55     56     57     DD56dd   FD56dd   16nn
LD E,r      58     59     5A     5B     5C     5D     5E     5F     DD5Edd   FD5Edd   1Enn
LD H,r      60     61     62     63     64     65     66     67     DD66dd   FD66dd   26nn
LD L,r      68     69     6A     6B     6C     6D     6E     6F     DD6Edd   FD6Edd   2Enn
LD (HL),r   70     71     72     73     74     75     -      77     -        -        36nn
LD A,r      78     79     7A     7B     7C     7D     7E     7F     DD7Edd   FD7Edd   3Enn
LD (IX+d),r DD70dd DD71dd DD72dd DD73dd DD74dd DD75dd -      DD77dd -        -        DD36nn
LD (IY+d),r FD70dd FD71dd FD72dd FD73dd FD74dd FD75dd -      FD77dd -        -        FD36nn

OR r        B0     B1     B2     B3     B4     B5     B6     B7     DDB6dd   FDB6dd   F6nn

OUT (C),R   ED41   ED49   ED51   ED59   ED61   ED69   -      ED79   -        -        -

RES 0,r     CB80   CB81   CB82   CB83   CB84   CB85   CB86   CB87   DDCBdd86 FDCBdd86 -
RES 1,r     CB88   CB89   CB8A   CB8B   CB8C   CB8D   CB8E   CB8F   DDCBdd8E FDCBdd8E -
RES 2,r     CB90   CB91   CB92   CB93   CB94   CB95   CB96   CB97   DDCBdd96 FDCBdd96 -
RES 3,r     CB98   CB99   CB9A   CB9B   CB9C   CB9D   CB9E   CB9F   DDCBdd9E FDCBdd9E -
RES 4,r     CBA0   CBA1   CBA2   CBA3   CBA4   CBA5   CBA6   CBA7   DDCBddA6 FDCBddA6 -
RES 5,r     CBA8   CBA9   CBAA   CBAB   CBAC   CBAD   CBAE   CBAF   DDCBddAE FDCBddAE -
RES 6,r     CBB0   CBB1   CBB2   CBB3   CBB4   CBB5   CBB6   CBB7   DDCBddB6 FDCBddB6 -
RES 7,r     CBB8   CBB9   CBBA   CBBB   CBBC   CBBD   CBBE   CBBF   DDCBddBE FDCBddBE -

RLC r       CB00   CB01   CB02   CB03   CB04   CB05   CB06   CB07   DDCBdd06 FDCBdd06 -
RRC r       CB08   CB09   CB0A   CB0B   CB0C   CB0D   CB0E   CB0F   DDCBdd0E FDCBdd0E -
RL r        CB10   CB11   CB12   CB13   CB14   CB15   CB16   CB17   DDCBdd16 FDCBdd16 -
RR r        CB18   CB19   CB1A   CB1B   CB1C   CB1D   CB1E   CB1F   DDCBdd1E FDCBdd1E -

SET 0,r     CBC0   CBC1   CBC2   CBC3   CBC4   CBC5   CBC6   CBC7   DDCBddC6 FDCBddC6 -
SET 1,r     CBC8   CBC9   CBCA   CBCB   CBCC   CBCD   CBCE   CBCF   DDCBddCE FDCBddCE -
SET 2,r     CBD0   CBD1   CBD2   CBD3   CBD4   CBD5   CBD6   CBD7   DDCBddD6 FDCBddD6 -
SET 3,r     CBD8   CBD9   CBDA   CBDB   CBDC   CBDD   CBDE   CBDF   DDCBddDE FDCBddDE -
SET 4,r     CBE0   CBE1   CBE2   CBE3   CBE4   CBE5   CBE6   CBE7   DDCBddE6 FDCBddE6 -
SET 5,r     CBE8   CBE9   CBEA   CBEB   CBEC   CBED   CBEE   CBEF   DDCBddEE FDCBddEE -
SET 6,r     CBF0   CBF1   CBF2   CBF3   CBF4   CBF5   CBF6   CBF7   DDCBddF6 FDCBddF6 -
SET 7,r     CBF8   CBF9   CBFA   CBFB   CBFC   CBFD   CBFE   CBFF   DDCBddFE FDCBddFE -

SUB A,r     90     91     92     93     94     95     96     97     DD96dd   FD96dd   D6nn
SBC A,r     98     99     9A     9B     9C     9D     9E     9F     DD9Edd   FD9Edd   DEnn

SLA r       CB20   CB21   CB22   CB23   CB24   CB25   CB26   CB27   DDCBdd26 FDCBdd26 -
SRA r       CB28   CB29   CB2A   CB2B   CB2C   CB2D   CB2E   CB2F   DDCBdd2E FDCBdd2E -
SRL r       CB38   CB39   CB3A   CB3B   CB3C   CB3D   CB3E   CB3F   DDCBdd3E FDCBdd3E -

XOR r       A8     A9     AA     AB     AC     AD     AE     AF     DDAEdd   FDAEdd   EEnn


- Table 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

s           BC        DE        HL        SP        IX        IY
----------------------------------------------------------------------
ADC HL,s    ED4A      ED5A      ED6A      ED7A      -         -
ADD HL,s    09        19        29        39        -         -
ADD IX,s    DD09      DD19      -         DD39      DD29      -
ADD IY,s    FD09      FD19      -         FD39      -         FD29
DEC s       0B        1B        2B        3B        DD2B      FD2B
INC s       03        13        23        33        DD23      FD23
LD s,mn     01nnmm    11nnmm    21nnmm    31nnmm    DD21nnmm  FD21nnmm
LD s,(pq)   ED4Bqqpp  ED5Bqqpp  2Aqqpp    ED7Bqqpp  DD2Aqqpp  FD2Aqqpp
LD (pq),s   ED43qqpp  ED53qqpp  22qqpp    ED73qqpp  DD22qqpp  FD22qqpp
POP s       C1        D1        E1        -         DDE1      FDE1
PUSH s      C5        D5        E5        -         DDE5      FDE5
SBC HL,s    ED42      ED52      ED62      ED72      -         -


[Due to insufficient space the remaining tables, which were supposed to be]
[printed with part 2 of the article, were actually printed in the next    ]
[issue with part 3 (see ZX8212B.TXT). JG.]


--
Another Fine Product transcribed by:
Jim Grimwood (jimg@globalnet.co.uk), Weardale, England
--
