You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
tions. Last time, I described the<br />
simple cases of adding or subtracting<br />
one (INC and DEC) from<br />
a register, or register pair. There<br />
are a number of machine code<br />
instructions which allow more<br />
complex addition and subtrac<br />
tion. For these, the choice of<br />
register is more limited than with<br />
INC and DEC. A single register<br />
addition or subtraction must<br />
always involve the 'A' register.<br />
Addition takes the form of adding<br />
the contents of the A<br />
register to another register or<br />
byte in memory (addressed by<br />
the HL pair), or a number<br />
(operand) in the program, and<br />
placing the result in the A<br />
register. Similarly, subtraction<br />
involves taking the value of a<br />
register, memory byte, or<br />
operand from the value in 'A'<br />
and placing the result back in the<br />
A register.<br />
Two byte arithmetic is more<br />
restricted. Addition involves<br />
taking the contents of the HL<br />
register pair, adding the contents<br />
of another register, and<br />
placing the result in HL. Subtraction<br />
involves subtracting a<br />
register pair value from the value<br />
in HL, and placing the result in<br />
HL. In single byte arithmetic,<br />
numbers are restricted to the<br />
range 0 to 255, whilst the range<br />
for two byte arithmetic is 0 to<br />
65535.<br />
A further complication is the<br />
carry flag. It is possible to add<br />
two numbers, then add the<br />
value of carry (0 or 11 to the<br />
result just before storing the<br />
final value. And it is possible to<br />
subtract the complement (1<br />
minus the value) of the carry flag<br />
from the result of subtracting<br />
two values, before storing the<br />
result. This gives two forms of<br />
add (ADD and ADC) and two<br />
forms of subtract (SUB and<br />
SBC); without and with the<br />
Table 1 Testing Flags<br />
a) Symbols and flag values<br />
Flag Flag = 1 Flag = 0<br />
C C (Carry) NC (No carry)<br />
Z Z (Zero) NZ (No zero<br />
P/V PO (parity odd) PE (parity even)<br />
S P (positive) M (negative)<br />
b) Valid operations, and their opcodes<br />
Unconditional Operation<br />
Flag: C<br />
JP (C3) JPC (DA)<br />
JP NC ID2)<br />
JR (18)<br />
CALL (CD)<br />
JRC (38)<br />
JR NC (30)<br />
CALL C (DCl<br />
CALL NC (D4)<br />
RET (C9) RET C (D8)<br />
RET NC (DO)<br />
carry flag. Confused? I'll try and<br />
explain.<br />
For simple arithmetic, it's<br />
easier to use the forms of add or<br />
subtract which do not use the<br />
carry flag value (ADD and SUB).<br />
So, if you are adding two<br />
registers or two register pairs, or<br />
subtracting two registers, use<br />
ADD or SUB. That way there is<br />
little chance of a mistake being<br />
made by an incorrect setting of<br />
the carry flag. The carry flag will,<br />
of course, be set (or reset) by the<br />
result of the addition/subtrac<br />
tion. For more complicated<br />
arithmetic, involving numbers<br />
held in several bytes, you'll want<br />
to use ADC or SBC. The purpose<br />
of involving the carry flag is that<br />
you can register whether or<br />
not there has been an addition or<br />
subtraction which has resulted<br />
in a value greater or smaller than<br />
that allowed by the restrictions<br />
on the register size. In this way<br />
you can carry a value to the next<br />
addition/subtraction, as you<br />
would carry one into the 'tens'<br />
column, having added 6 and 5 in<br />
the 'units'. Before using ADC or<br />
SBC it is usual to reset (for ADCl<br />
or set (for SBC) the carry flag<br />
before carrying out the calculation.<br />
The assembly language in<br />
struction to set the carry flag is<br />
SCF. There is no direct instruction<br />
to reset the carry flag, but<br />
this can be carried out by first<br />
setting the carry flag with SCF<br />
followed by the instruction CCF<br />
(complement carry flag), which<br />
inverts the value of the carry flag<br />
(0 to 1, or 1 to 0). The two in<br />
structions are one byte each<br />
(opcodes are 37 (SCF) and 3F<br />
(CCF), hex). The carry flag can<br />
be reset in one byte; I'll show<br />
you how next time.<br />
You'll see all the opcodes for<br />
the add and subtract in Table 2.<br />
Note that for two byte subtraction,<br />
only SBC is available, so be<br />
ZX PROGRAMMING<br />
Conditional Operations<br />
P/V<br />
JP PO (E2|<br />
JP PE (EA)<br />
CALL PO (E4)<br />
CALL PE (EC)<br />
RET PO (EO)<br />
RET PE (E8)<br />
sure to set the carry flag when<br />
using it for simple arithmetic. Fig<br />
2 in the examples section, later<br />
on, provides a BASIC program<br />
which should help to clarify any<br />
doubts about the different add<br />
and subtract instructions.<br />
Block loading<br />
The final piece of theory for this<br />
issue is the Z80's powerful<br />
block load instruction. It allows<br />
the values in a block of bytes (of<br />
any size) in memory to be moved<br />
to another location. It works like<br />
this:<br />
The starting address of the<br />
source block is loaded into the<br />
HL register pair, the starting address<br />
of the destination block is<br />
moved into DE, and the number<br />
of bytes to be moved goes into<br />
BC. Then one instruction LDIR<br />
performs the move. LDIR stands<br />
for LoaD Increment Repeat. The<br />
value in BC acts as a counter.<br />
The value in the byte addressed<br />
by HL is transferred to the byte<br />
addressed by DE: HL and DE are<br />
incremented, while BC is<br />
decremented, then the instruction<br />
repeats itself automatically<br />
until BC gets down to zero.<br />
There is a non-repeat alter<br />
native, LDI, where the byte<br />
value transfer takes place, and<br />
registers HL and DE are incremented,<br />
BC decremented,<br />
but the instruction is not<br />
repeated automatically. Begin<br />
ners to machine code would normally<br />
use LDIR, and this is<br />
shown in the examples.<br />
The Z80 offers an almost<br />
identical instruction called<br />
LDDR. To use this, the END addresses<br />
of the source and<br />
destination blocks are loaded into<br />
HL and DE, respectively,<br />
while BC still holds the number<br />
of bytes to be transferred. Each<br />
cycle of the instruction involves<br />
Z<br />
JPZ (CA)<br />
JP NZ (C2><br />
JRZ (28)<br />
HR N (20)<br />
CALL Z (CC)<br />
CALL NZ (C4)<br />
RET Z(C8)<br />
RET NZ (CO)<br />
transfer from (HL) to (DE), and<br />
all three register pairs<br />
decremented. LDD is the nonautomatic<br />
repeat version of<br />
LDDR. It doesn't really matter<br />
whether you use LDIR or LDDR<br />
unless there is some overlap between<br />
the source and destination<br />
blocks of memory. Then, the<br />
choice is critical if bytes are not<br />
going to be corrupted. I'll leave<br />
you to sort out which should be<br />
used, depending on whether the<br />
overlap is at the beginning or end<br />
of the source block! The block<br />
move opcodes are shown in<br />
Table 2.<br />
Examples<br />
The first two examples given<br />
this time are written in such a<br />
way that they will work on both<br />
theZX81 and Spectrum. Example<br />
1 is the flag demonstration<br />
program, and all details appear<br />
in f ig. 1 . Example 2<br />
demonstrates add and subtract,<br />
and should help explain any<br />
questions you might have on all<br />
the arithmetic instructions mentioned<br />
earlier. Fig. 2 contains the<br />
details of this.<br />
The final example carries out<br />
similar block move operations<br />
on both ZX81 and Spectrum;<br />
copying the display file to a safe<br />
area of RAM, then returning it<br />
'instantly'. Machine differences<br />
prevent the same code working<br />
on both machines, so ZX81<br />
users should refer to fig. 3, while<br />
Spectrum owners go to fig. 4.<br />
Next time we'll be looking at<br />
a stack which has little to do<br />
with chimneys, and some bit<br />
operations!<br />
Spectrum users should type in<br />
the following listing as shown<br />
(Figure IK A minor change<br />
should be made by ZX81 users.<br />
S<br />
JP P(F2)<br />
JP M (FA)<br />
CALL P IF4)<br />
CALL M (FC)<br />
RET P (FOl<br />
RET M (F8)<br />
ZX COMPUTING APRIL/MAY 19 85 8 9