home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
messroms.de
/
2007-01-13_www.messroms.de.zip
/
ASZMIC
/
IMAGES
/
ASZMIC10.ZIP
/
ASZMIC01.TXT
< prev
Wrap
Text File
|
1997-06-28
|
136KB
|
3,231 lines
--------
Project 81 presents:
Etext of the ZX-Aszmic manual (etext #2)
converted to etext by Adam Bergstrom.
Project 81 is the official sister page of Project 64. Its goal is to
is to preserve ZX81/80 documents like manuals and some other. By translating
manuals into etexts, the documents will exist for a long time. Each manual
is also a bit of computer history and should be preserved.
The 'Project 81' needs your partizipation! If you have manuals
or ZX81/80 related documets just send an e-mail to me what you want
to convert. You can also send me an e-mail if you desperately need some
information.
The contributors of Project 81 do not take any responsibility for the accurrance
in this etext. Please use the information given ihn this text at your own risk.
The Project 81 homepage is located at:
http://www.hh.schule.de/hhs/mjaap/project.htm
----
Comprocsys limited
ZX.ASZMIC
manual
C FRAZER JOHNSON
Contents
1 Insertion & Overview
2 First Steps
3 First Steps continued
4 More Debug Operations
5 Text Operations
6 The Assembler
7 Program Execution & Test
8 Graphics
Appendices
1 General Information
2 The Shift Keys
3 Debug Commands
4 System Addresses
5 Z80 Instructions
Application Note *1
***** All rights reserved. Manual & ROM contents copyright ***
INSERTION & OVERVIEW Chapter 1
Congratulations on your decision to buy ZX.ASZMIC. If you have had previous
experience of assembly and debug systems you may wish to proceed immediately
to the first 3 appendices, which summarise the ASZMIC features for you.
Otherwise the next 3 chapters contain a series of worked examples to help
give you a feel for ASZMIC usage. Chapters 5,6 & 7 are a more general
discussion of the features; chapter 8 introduces you briefly to the graphics
possibilities; and appendices 4 thru 6 contain useful reference information.
What exactly is ASZMIC? It was designed to be an ultra low cost program
development station for assembly language. As such it gives you all the
facilities you need to write and edit programs, assemble them and then run
and debug them in a controlled environment. Since the programs may also be
run on an '81 fitted with ASZMIC we tried to document some of the useful
routines in the monitor itself to help free you from that curse of assembly
language programming....Input/Output...., and we parametrised the display
routine to release the graphics possibilities which were latent in the
hardware. Unlike some of the other offerings on the market ASZMIC is almost
completely independent of Basic, and you should bear in mind that the
personality of the computer is completely transformed. ASZMIC tips its hat in
the direction of Cambridge and then does its own thing. If you are experienced
with microcomputer development systems then much of ASZMIC will be familiar
to you; but if you are used only to Basic then ASZMIC will give you a power
which you could never achieve when everything you did was filtered thru the
Basic interpreter. This is unfortunately a power for both good and evil; since
ASZMIC does what you tell it to then a command which is, shall we say, less than
wise can easily wipe out the system. Fortunately you will not do this very often.
1.1 INSTALLATION
ASZMIC is a direct replacement for the Basic Rom in the ZX81. To insert it
in your computer you must first seperate the case by removing the 5 screws
from the base of the ZX81; three of which are concealed under the peel-off
rubber 'feet'. Then remove the three screws which hold the printed circuit
board onto the lid and,taking care not to pull the 'tails' from the touch
panel out of their holders, fold back the circuit board and rest it and the
lid on a clean surface. If you do pull out the 'tails' they can be pushed
back in without too much difficulty.
If you now look at the component side of the board; calling the edge with
the edge connector 'top', that closest to the keyboard 'bottom' and the edge
with the power, cassette & t.v. connections 'left', then the Rom lies at the
bottom of the board. You can look at the diagram on p. 162 of the ZX8l manual
to see the Rom identified (and beware1 in the picture it is inserted upside
down). Although modern technology has made MOS circuits much more tolerant
than they used to be you may feel more secure working on a large sheet of
aluminium kitchen foil which is connected to a radiator or earth of
some sort, or a metal draining board is excellent. Avoid wearing nylon
clothing and try to earth yourself before touching any circuit not in its
socket on the board. The Basic Rom will probably be in a 28-pin socket, even
though it has only 24 pins, so there will be four empty 'holes' in the socket
above the Rom. ASZMIC also has 24 pins so when it is inserted it also should
be positioned at the bottom of the socket with four empty 'holes' above it.
ASZMIC should be inserted so that the 1 on the label lies towards the left.
Remove the Basic Rom by gently levering it up from top and bottom with a fine
screwdriver until it lies loose in the socket, and then lifting it away. If you
are too hasty you may bend the pins. Put it on a little bit of foil. ASZMIC's
pins may now need to be bent slightly inwards so that you can press it into the
socket, but not too much since the socket generally makes contact on the
outside of the pins and you run the risk of a bad contact on one or more pins
if you bend it too much. Push ASZMIC carefully into place.
Before putting everything back together again you might like to connect up
the power and t.v. lines and check that you have a blinking cursor.
If not then you have a bad connection and you should try to remove and replace
ASZMIC a couple of times
If you plan to use both ASZMIC and Basic alternately then you may wish to
invest in one of the boards available which will hold both Roms. Capital
Computers Ltd can give you details. When we were developing ASZMIC we cut a
hole in the lid of an '81 (from 4 to 6 back from the touch keyboard for
about 5 cms and if you cut more than a mm into the keyboard you will kill it)
and pic-a-backed a zero insertion force socket onto the ZX8l Rom socket.
This worked surprisingly reliably, but a dual Rom board will give you the ability
to preserve regions of memory when you transfer control.
1.2 ZX80 INSTALLATION
The circuit board on the ZX80 is more accessible than on ZX8l; you just have to
remove plastic pins to release the lid and the Rom lies on the right. ASZMIC
should be inserted with the 1 closest to the UHF modulator (metal box). You
will not be able to use the G command with a ZX80, and a steady display will
not be maintained under Edit operations.
Some ZX80's suffer from excessive load on the Al2 address line which can lead
to difficulties in reading the key group 6 thru 0. This can be cured by soldering
a 4.7K resistor between the left hand (keyboard) side of D7 to the earth plane
below IC11 & IC17.
FIRST STEPS WITH ZX.ASZMIC Chapter 2
2.1 POWER UP
After connecting the power to your ZX80/81 you will have a clear screen,
except for a funny little character towards the bottom left (End-of-Data)
and a blinking cursor on the line just above it. The speed of blink identifies
which mode ASZMIC is in..... Fast blink means EDIT, slow blink means DEBUG.
With 16k of memory on the system you will be in DEBUG mode but if you are
using a "bare" machine then you will be in EDIT mode. Shifting between
EDIT & DEBUG modes is achieved by use of the Shift 9 & Shift E keys. Experiment
by pressing Shift 9 (DEBUG) and Shift E (EDIT) alternately, and watch what
happens to the cursor blink rate. There is only one difference between EDIT
and DEBUG modes, but that is an important one. When you hit newline (we shall
write newline as /NL/ in future) in DEBUG mode the line you have just finished
will be passed to the Command Interpreter. In EDIT mode you just start a new
line.
2.2 EDITING
Press Shift E to get yourself in EDIT mode. The cursor will be blinking quickly.
Now type A. An "A" appears on the screen & the cursor is advanced to the right.
Type A again, but this time leave your finger pressing on the key. After
half a second ASZMIC will start writing A's at a rate of 8 per second. Take
your finger off the key before the line is full. This illustrates the very
useful key repeat feature built into ASZMIC. It works on all keys, including
/NL/. Now type /NL/ & then press B for a second or two, type /NL/ and press C
for a second or two, type /NL/ and repeat the process till you have 5 or 6
lines on screen. Notice how the display is scrolled up with each /NL/. Now
type a final line of, say, G's but do not press /NL/ at the end. Instead
press Shift 5 (CURSOR LEFT) & keep your fingers on the keys. The cursor will
move left along the line till it comes to line start. Press Shift 8 (CURSOR
RIGHT) continuously & watch the cursor advance along the line to line end.
Press Shift 5 (CURSOR LEFT) again until the cursor lies in the middle of
the line.Type 12345. The figures are inserted in the middle of the line.
What actually happens is that everything under and right of the cursor is
shifted right, the character you have typed is placed under the cursor, and
then the cursor is shifted one place to the right.
2.2.1 RUBOUTS
Press Shift 0 (RUBOUT). The 5 you have just typed will disappear. This is
the first type of rubout in ASZMIC, and is the typing error rubout. The
character to the left of the cursor is deleted and everything past it moved
left one place. Press Shift 5 twice to position the cursor over the 3.
Press Shift Q (EDIT RUBOUT) and watch the 3 disappear. This is the second
type of rubout; the editing rubout. The difference is that Shift 0 is more
convenient when you are typing in a fresh line, and Shift C is better when
editing a file. Experiment a bit with them if you like. Edit Rubouts do not work
when there is only one character remaining on a line. You can rubout /NL/'s
with Shift 0. Shift Q can also delete the "padding" blank ASZMIC inserts before
a /NL/; which can give problems with assembly & merging.
2.2.2 VERTCAL CURSOR OPERATIONS
Reset your ZX80/81 (turn off & on again). We ask you to do this quite often
because if you have only 1K of memory these examples will soon fill up the
text area. Enter DEBUG mode with Shift 9. Type D 0/NL/ .
ASZMIC responds with 0000 F5
Keep your finger on the /NL/ key until ASZMIC has printed 0030 3E and then
type . (period) followed by /NL/ followed by E/NL/ to get back to
EDIT mode. You have actually done a Dump & Modify of the first 49 monitor
locations but we want it just to have some text to play with. Now press Shift
7 (CURSOR UP) and hold it down. Watch the cursor move up the screen until it
reaches the top, and then watch the text scroll down until the cursor has moved
onto a blank line. Now press Shift 6 (CURSOR DOWN) and watch the cursor move
down until it is on the final line just above the End-of-Data character. It
will not move down any further. Now press Shift 4 (PAGE UP) a couple of times
and see how you flip up through the text. Press Shift 3 (PAGE DOWN) to reverse
the process.
2.2.3 DELETING A LINE
Move the cursor up to 0020 7E or thereabouts. Now press Shift 1 (DELETE LINE).
The line will vanish. Repeat the process and sucessive lines will vanish
until you are back down above the End-of-Data character. You cannot delete this
final line with Shift 1; you have to rub it out character by character. This
is to protect the vital End-of-Data character which is used as a "stop" for
many ASZMIC operations. Now press Shift T (TOP). The cursor and display
jump up to the very top. This is useful if you want to search down through
large texts, but is most important because the top line has a special significance.
It is the Shift Macro line, but more of that later. Now press Shift 9 (DEBUG)
and notice how you have jumped down to the bottom line and entered DEBUG mode.
Press Shift E (EDIT) and note that you have not only entered EDIT mode (fast
blink) but also jumped back to the point where you were when you last pressed
Shift 9. This enables you to toggle between EDIT and DEBUG modes without having
to search for your place all the time.
2.2.4 FILES & FILEMARKS
Unlike the BASIC rom, ASZMIC does not construct a special display file for
you, but instead uses most of memory as one big text area over which you
move the T.V. screen as a sort of window. A lot of operations are controlled
by a special character, the (sterling) sign, which acts as a delimiter.
Since blocks of text seperated by signs are treated as files, we call the o
a filemark. It is used by itself to indicate the end of a file, and is
needed for print, assembly, cassette save, merge, and file deletion operations
to tell ASZMIC that it is time to stop. You indicate the start of a file by a
name which is particular to it & does not also occur in the body of the file.
It is good practice to have a filemark as the first character of the name. Thus:-
oNURSERY.RHYME
1
2
BUCKLE MY SHOE
3
4
KNOCK ON THE DOOR
o
is an example of a file, and can be printed, saved, edited etc. by
referencing the name oNURSERY.RHYME . A filename can be any combination of
alphanumeric characters (0-9 A-Z) and . (period) and is terminated by any
other character.
Home the cursor (Shift 9) & type /NL/ . Then press Shift E to get into EDIT
mode & move the cursor till it blinks on the D of your original D 0 line at
the top of the dump. Now press Shift 2 (delete file) . All the text from the
cursor to the filemark will have been wiped away.
2.2.5 RUNNING OUT OF SPACE
Reset the ZX80/81 and hit Shift 9 (DEBUG, as you probably know by now).
Type D 0 5000/NL/ . The screen will go blank for several seconds because
ASZMIC is generating 625 lines of formatted dump for you. Unfortunately
it would take more than a 16k memory pack to contain so much text, even if
ASZMIC had not divided up your memory into 3 parts for text and 1 for programs.
When the display comes back try typing in a character. Nothing happens. You
can move the cursor around (try it) but you cannot insert any fresh text. To
use ASZMIC further you must delete some text. Move the cursor up 4 or 5 lines
(Shift 7) and then hold Shift 1 continuously depressed. You will delete the
last few lines. You can now insert characters (100 or more) until you run out
of text space again.
2.2.6 MACROS
We may as well use this mass of text for something. Press Shift T. This
takes the cursor up to the top line. Now type E 40 but, since you are in
DEBUG mode, do not press /NL/ to execute the command but instead press Shift 9
(DEBUG) to home the cursor on the bottom line. Now press Shift R (Shift macro).
The effect of this is to execute the top line as a DEBUG statement, irrespective
of what mode you are in. E 40 is a DEBUG command to enter EDIT mode
and position the cursor at the start of the first occurrence of the string "40"
above its current position, so you will see the cursor blinking quickly on the
"4" of a "40". Press Shift R several times and see how each "40" in the dump is
successively searched out. You can have almost any DEBUG command or concatenation
of commands on the top line and this is a way of doing a lot of work with a
single keystroke. (there is another sort of macro, a Command Macro, built
into ASZMIC and we will look at it when we discuss file merging)
Now delete the dump by pressing Shift 9, typing /NL/ ( is not a valid DEBUG
command and is ignored by the Command Interpreter), pressing Shift T, and
then holding down Shift 6 to move the cursor down to the "D" of D 0 5000,and
then pressing Shift 2 (delete file). You should have cleared out everything.
2.2.7 MERGING
Reset the ZX80/81. Type Shift E (EDIT). Type the following:
>D 0 1/NL/
D 0 2/NL/
D 0 3/NL/
D 0 4/NL/
D 0 5/NL/
o/NL/
Now press Shift G (merge) once. Everything between the > and characters
has been. duplicated. Try it again. Every time you press Shift G a further 5
lines are copied down at the cursor position. Move the cursor up to the D of
a D 0 3 and press Shift G. The 5 lines have been inserted before the D 0 3,
because that is where the cursor was. Now type Shift 9 (DEBUG).
In EDIT mode the Shift G is a pure merge key. Now that you are in DEBUG mode
the effect is rather different, because every time ASZMIC writes a /NL/ to
the text area in DEBUG mode it passes control to the Command Interpreter.
Press Shift G. Every "D" line has been copied, but since each line is a dump
command, it is followed by the appropriate dump. Just by pressing 1 key we have
executed 5 lines of DEBUG commands. This is called a Command Macro.
Normally in EDIT mode merging you will want to copy one piece of text into
another. You do this by identifying the text to be moved by the > and
characters, putting the cursor at the point you want the text merged into,
pressing Shift G, and then, if you want the original text deleted, positioning
the cursor on the > character and pressing Shift 2 (delete file). Simple,
flexible, and, for the poor sweated labourer who wrote ASZMIC, easy to
implement. Check Appendix 4 for the symbols SHFTD & SHFTF. If they
appear then you have 3 merge keys. Shift D is like Shift G but uses * as
merge start identifier, and Shift f uses < .
2.3 WHAT NEXT?
You have now covered all the Shift keys which control the EDIT functions. If
you look at Appendix 2 you will see a formal summary of each Shift. Try
setting up some text of your own and working with it. Then look at Appendix 3
for a summary of the DEBUG commands. We are going to look a little more
closely at them, although not in alphabetical order, since some of the
commands are more complex in their implications than others.
FIRST STEPS CONTINUED Chapter 3
3 SIMPLER DEBUG COMMANDS
Everything that you can do in EDIT mode you can also do in DEBUG mode .
The difference is that the Command Interpreter is called in DEBUG mode when
you press /NL/. However if you do any editing in DEBUG mode then you cannot
rely on Shift E (EDIT) to take you back to the point where you exited from EDIT
mode. It will take you back to the location in memory where the cursor WAS, but
you may have edited in something different there (such as a /NL/, in which case
the cursor will not appear).
3.1 D for DUMP
Reset your ZX8l. Hit Shift 9 to ensure you are in DEBUG mode. Type D :4300 12/NL/
and you will get a display of the form:-
4300 00 00 00 00 00 00 00 OC
4308 00 00 00 00
This is an example of a Dump Range command. It introduces an important new idea,
that of a FIELD. The command itself is just a letter D, followed by a field which
defines the starting address for the dump and then a field which defines the
number of bytes which are to be dumped from successive locations. The : (colon)
identifies the 4300 which follows as being a hexadecimal value. Lock at the
definition of the field types in ASZMIC which you will find in Appendix 1.
The use of fields defined there is common throughout ASZMIC with one exception
which we shall discuss in a moment. Fields are seperated by one or more blanks
or a comma, but not both. The first field can start immediately after the DEBUG
command letter, but an intervening blank often looks better.
There is another form of dump which we call Dump & Modify. Type D :4300/NL/
ASZMIC responds with:-
4300 00
and the cursor is waiting on the line for input. Depress /NL/ 2 or 3 times.
With each press the next location and its contents are printed out thus:-
4301 00
4302 00
4303 00
How do you get out of this? Press . (period) followed by /NL/ and you are back
in ordinary DEBUG mode again. So where does the Modify come in? Type
D :4300/NL/ again. Now type 1 4 7 C 12/NL/ followed by . (period) and /NL/.
Then do a dump range of the form D :4300 6/NL/ . The response is:-
4300 01 04 07 0c 12 00
Compare this with the result of the first D :4300 12 that you did. Dump &
Modify is the exception to the ASZMIC field rules that we mentioned earlier.
Numbers are ASSUMED to be hexadecimal even without the : (colon) prefix. If
you want to type in a decimal number use 0+decimalno. For a more dramatic (?)
demonstration reset your ZX81,enter DEBUG mode, type 15 or 20 o signs, then look
for the address of DSPBGN in appendix 4 and add 55 to it (e.g. :40B4+55). After
terminating your oo's line with /NL/ type D :40B4+55/NL/ & then 1C/NL/ 1D/NL/
etc. You can see the o signs being overwritten with the characters corresponding
to the codes that you typed in.
3.2 C for COPY
Reset the ZX8l (if you have 16K of memory you need not do this all the time).
Enter DEBUG Mode (Shift 9). Type the following commands:-
D :4300 20/NL/
D :4300/NL/
1 2 3 4 5 6 7 8 ./NL/
D :4300 20/NL/
C :4300 :4308 8/NL/
D :4300 20/NL
Take a deep breath and look at what you did. First you dumped 20 locations which
were all 0 (the machine zeroes memory on reset). Then you did a Dump and Modify
of the first 8, and a Dump Range to verify that they had been modified. You
then copied 8 bytes from the location :4300 to the location :4308 (the bytes
are counted UP from the addresses you give) and finally you dumped the 20 locations
again to verify that the copy had taken place.
The format for Copy is C from to count. It has logic in it to ensure
that if you specify overlapping memory regions then the data moved to the
destination region is not corrupted. The copy goes from top to bottom or
vice versa as required to ensure that the source region is not overwritten
by the destination region before the source bytes have been copied.
3.3 F for FILL
Reset the ZX81 & enter DEBUG mode. Type F :4300 :4310 :AA/NL/ .
Then type D :4300 16/NL/ and note that you have filled the region with AA
codes. The format is F from to fillerbyte . The command is most often used
to initialise regions of memory (notably to zero them out; zero is the default
fillerbyte if you do not specify a third field)
3.4 E for EDIT
E by itself just shifts back to EDIT mode. If followed by a symbol
then ASZMIC searches up for the symbol and positions the cursor at
its start. Great for getting to a file when you have a lot of text. You have
already used this command in 2.2.6 MACROS so we will not give any examples.
Look at the description of the subroutine CMPSTR (used by E & many other
ASZMIC commands) to see what constitutes a valid comparison.
3.5 H for HORRIBLE JUMP
The format for this is H field and the result is a jump to the address
specified by the field whilst still in the context of the Command Interpreter
You presumably have a program at the address which does something for you and
then RET's to ASZMIC. Your routine can analyse further fields on the line using
GETFLD, so this is a way of linking in your own personalised commands. If you
want an example try looking up the address of INICON in Appendix 4
and then doing an H to that address (remember the :). INICON is the start of
the ASZMIC initialisation so the effect should be the same as resetting the
ZX81.
3.6 M for MACRO
This is an extension of the Shift G key. Reset the ZX8l and enter DEBUG mode.
type: -
=D 0 8/NL/
o/NL/
+D 16 8/NL/
o/NL/
Then type M=/NL/ a couple of times and M+/NL/ a couple of times. The dumps
specified are generated. The character after the M specifies the start character
for the command macro, unlike Shift G , which always uses > as a start
character. You thus have a wide choice of macros.
3.7 O for OLD REGISTERS
In DEBUG mode type O/NL/. You will get a pair of intimidating lines
each with six 4-digit hexadecimal numbers on it. These are the registers which
are saved in the register context area (REGIM). See the definition of O in
Appendix 3 to tell you which is which. They do not mean too much until you
start executing programs and generating Breaks in them, which causes the
registers to be saved in the Image area. It is a very good idea to put an
O in the Shift Macro line when you start a session with ASZMIC, since the
Shift Macro line is executed for every break condition, and you normally
are interested in register contents when a break has occurred.
If you are feeling dynamic try looking up the addres of REGIM in Appendix
4 and then modifying some locations between (REGIM) and (REGIM)+24 and
noting the effect on the Old Register dump lines.
3.8 P for PRINT
This command will do precisely nothing for you if you do not have a Sinclair
printer attached. If you do then reset the ZX81 and enter EDIT mode. Type:-
oPRINT. FILE
ANY
SORT
OF
RUBBISH
WILL DO
o
and then hit Shift 9 to enter DEBUG mode.
Type P oPRINT.FILE/NL/ and the file will be printed. If you want to terminate
the printing prematurely (e.g. if you forgot the o sign which terminates the
printing) you just have to hit the Break key.
This concludes the simpler DEBUG commands. In the next chapter we shall be
looking at some of the more complex, and interesting, ones.
MORE DEBUG OPERATIONS Chapter 4
4 SAVING & LOADING
It is now time to look at the ASZMIC cassette interface. This uses the same
recording format as the BASIC Rom, so that it is possible, using some tricks
described in the chapter on text ops, to read in a program saved by BASIC,
modify it with ASZMIC e.g. writing REM's full of machine code, and then write
it back so that it can be loaded by BASIC again. The price you pay for this
compatibility is the dreadful slowness of the interface, but of course you are
used to that by now.
When ASZMIC writes out a file to cassette it first writes out a title line
which identifies the program or file which follows, waits 5 seconds, and then
writes out the file or memory region you specified. When you are loading from
cassette ASZMIC detects the title line and writes it to screen, using the 5
second pause before data to display it to you. You thus get a catalogue of
everything on the tape built up for you, which is informative and soothing
because you know that your system has not disappeared into one of those black
holes which lurk around cassette reading.
4.1 K for KASSETTE (sic)
Reset your ZX81, enter EDIT mode and type in a file, such as:-
oLIMERICK
THERE WAS A YOUNG LADY FROM EXETER
SO LOVELY THAT MEN CRANED THEIR NECKS AT HER
AND ONE WENT SO FAR
AS TO WAVE FROM HIS CAR
THE DISTINGUISHING MARK OF HIS SEX AT HER
o
Now enter DEBUG mode, connect your cassette recorder just as you do for
BASIC, and type in :-
KoS "POETRY" oLIMERICK/NL/
The sequence K o S space is very important. If you do not write it like
that, with only 1 blank between S and ", then ASZMIC will not recognise it
as a file title and you will never ever (unless you are very smart) be able
to read the file back.
After you hit /NL/ you have S seconds to turn on your cassette recorder. It
does no harm to turn it on early. The screen then blanks out for half a second
and the title line is written out. The display returns for a further 5
seconds and then the file itself is written out. The display comes back again
when the save is complete. You can abort a save at any time with the BREAK key.
Stop the recorder .
Now type F :4300 :4320 :BB/NL/ to set a region of memory to "BB" codes.
Do another save, but this time of a memory region:-
KoS "MEMSAVE" :4300 :4320/NL/
Cassette operating procedure is as above. Rewind the tape.
4.2 L for LOAD
Reset the ZX81 and enter DEBUG mode. Type:
L "NOTHING"/NL/
and start the recorder in playback mode with the same volume setting that
you use for BASIC. After a while the screen will light up with:-
KoS "POETRY" oLIMERICK
for 5 seconds and then blank out again. A little later there comes another
5 second burst but this time the line:-
KoS "MEMSAVE" :4300 :432
has been added to the display.Since there is no file called "NOTHING" on
the tape you may as well hit BREAK to come back in EDIT mode. Now rewind the
tape, enter DEBUG mode and, using the same procedure as above but with:-
L "LIMERICK"/NL/
load the file you first saved. Check that it is O.K.
Reset the ZX8l, enter DEBUG mode and rewind the cassette. Check that :4300
to :4320 contains zeroes (D :4300 32/NL/) and load the second file with:-
L "MEMSAVE"/NL/
Dump :4300 to :4320 to verify that it now contains "BB" bytes.
EASY?
4.5 A for ASSEMBLE
The ASZMIC assembler was developed from a 1K assembler (yes, 1K) written for
NASCOM 1 and normally called, with mixed emotion, the "Dirty Dog" assembler.
It is a 2 pass assembler with full Zilog mnemonics. If you are not familiar
with Zilog's assembly language then it might be a good idea, to put it mildly,
if you bought a book on the subject. There are references in Chapter 26 of
the ZX81 manual.
Reset the ZX81, enter EDIT mode and type the following sequence (we are going
to assume that you know enough to terminate each line with a/NL/):-
oFILE
ORG :4300
START LD HL,0
LD DE,0
LD B,10
LOOP INC DE
ADD HL,DE
LOOPEND DJNZ LOOP
RST 0
o
This is a program. Please always start every program with an ORG directive to
tell the assembler where it should be located. It will probably start at
(TXTLIM) if you do not, but that default may not necessarily be in your version
of ASZMIC. Now we are ready to do an assembly. Enter DEBUG mode and type:-
A oFILE 1
The "1" is an option to say that you want an assembly listing. Almost
instantaneously ASZMIC comes back to you in EDIT mode (It can assemble at up
to 300 statements a second) with a listing showing the code generated for
each statement, plus the location in memory it has been assembled at.
Enter DEBUG mode and dump the program (D :4300 14) to see that it really has
been assembled for you. We call this generated machine executable code "object
code" .
Now delete all the text in the text area, but do not reset the ZX81
because we do not wish to lose the program.
4.6 J for JUMP
We are now going to execute the program. It generates the sum of the numbers
from 1 to 10 in the HL register. To help us see what is happening we are
going to use a Shift Macro (which is automatically executed whenever a BREAK
condition is encountered. BREAK means breakpoint,single step,RST 0 code or
externally generated NMI interrupt). Hit Shift T, type O (not 0) without a
newline and then Shift 9 to home back in DEBUG mode. Check Appendix
3 for the O command if you have forgotten it. Type:-
J :4300
You now have a dump of the registers at the end of the program. Look at HL.
It should contain :0037, which is the hex equivalent of decimal 55. DE should
contain :000A which is 10 of course.
4.7 B for BREAKPOINT
Let us now try to execute the program again, but this time with a breakpoint
inserted to stop execution "in midstream". Type B LOOPEND/NL/ (the DJNZ
instruction) and then J START /NL/. Now take a look at the registers. Both
DE and HL should contain :0001, and B should still contain :0A, since the
breakpoint takes effect before the instruction at whose location it was
inserted is executed.
Breakpoints work by saving the byte at the breakpoint location and substituting
a RST 0 (:C7) code. When you hit a breakpoint in the course of normal execution
the "normal" byte is put back there ( check with D LOOPEND 1).
Now type B /NL/. Since you did not specify an address the breakpoint was reinserted
at the previous breakpoint location ( check with D LOOPEND 1 again). Type B 0/NL/
to clear the breakpoint.
4.8 G for GO
Now type G/NL/. You have advanced one instruction. Type it a couple more times.
This is called single stepping. You can see the Program Counter (PC) changing
as well as the registers you are working with. Since we did not specify an
address with the G command it used the saved Program Counter address in the
register image area (PCl in REGIM).
Now why not try executing 20 instructions before jumping back to the monitor?
Type G START 20/NL/ .The "START" tells the G command where to go and the "20"
tells it to execute 20 instructions before it comes back to you. You will
see that the Program Counter,which points to the next instruction to be
executed, is :4308, HL is :0015, DE is :0006 and B is :04. If you add it all
up you will see that this is the sixth time through the loop and we have in fact
executed 20 instructions. Then type J /NL/. This shows how J without an address
will just continue the program to its end.
We sneaked in a little subtlety without mentioning it to you beforehand.
You have used the symbolic names FROM YOUR PROGRAM in DEBUG instructions, and
they worked. That sort of thing makes debugging a program very much simpler.
By the way, if you try single stepping through a breakpoint then you will single
step into the breakpoint logic, which may not be exactly what you had in
mind.
4.9 I for Immediate
WE conclude this chapter by looking at the Immediate instruction facility in
ASZMIC, which to the best of our knowledge is unique. It is a way of giving
you the sort of interactive capacity you have in BASIC by allowing you to
specify assembler statements which are immediately executed in your program
context, and function as an extension of the program itself without
the need to recompile.
Clean up the text area if you have a 1K system. Type I LD HL,1/NL/
and look at the HL register in the "O" dump. It contains :0001. Type I EX DE,HL/NL/
and note that the DE and HL registers have been exchanged. You can put any
instruction in an Immediate command, and even define labels with the = (EQU)
directive, but relative jumps and the other directives (ORG,DEFB,DEFW,DEFM)
are meaningless and can crash the system when the I command tries to execute
them.
Finally try I LD HL,1+2+3+4+5-15/NL/ and look at HL in the register dump. It
should be zero, thus demonstrating how you can do simple arithmetic with
fields.
We now recommend that you look at the formal definition of the DEBUG commands
in Appendix 3 to see what you have been doing all the time. There is one
more Debug command, the N command, which is used in conjunction with a
special board which holds both Basic & ASZMIC roms to switch between roms
whilst preserving memory. Its use is described in the board documentation.
TEXT OPERATIONS Chapter 5
This and the next 2 chapters contain di scussi on around features of ASZMIC
to help 'flesh out' the bare bones of definition in the Appendices and the
exemplars of the previous chapters. They should not be taken as comprehensive
descriptions of everything which is available.
5.0 INTRODUCTION
The second partition in ASZMIC memory, lying between DSPBGN & (TXTLIM), is
used for text preparation and editing. On a 16K system this means you have
around 12000 characters available; more if you move up the TXTLIM pointer
yourself. ASZMIC treats this as an allowed space in which you can insert
characters at will, and your T.V. screen becomes a window which is moved
over this enormous area under control of the Editor Shift keys. There is no
specific display file as with BASIC, but instead the whole text area is a
display file, and the BASIC notions of program, variable and display space
are no longer relevant. This is a- software utilisation of one of the
main strengths of ZX81 viz. that it allows most of memory to be mapped onto
a video display. We force a few conventions of our own onto this space to make
life a bit more meaningful for you.
5.1 FILES
The first convention is to introduce a protocol which divides up the
text in the text area into identifiable sections. We call these sections files.
A file is identified by a symbol whose first character is a f (sterling) sign
left justified on the first line of the file. This symbol, plus its preceding
o sign, becomes the NAME of the file. The end of a file is signalled by a o
sign as the first character of a line. We call the o signs FILEMARKS in
consequence. The ASZMIC character string comparison routine CMPSTR is coded
to recognise a comparison of strings beginning with o only if the
destination string is the first on a line. This all sounds a bit complicated
but it works out very well in practice, because if you start every
file with an unique filename, and terminate it with a filemark, the ASZMIC
commands will unerringly pluck out the file you are interested in from the
text area and process it for you. The convention is fully integrated into
the Debug commands
This means that you can have as many files as you like, subject only to
space restrictions. We should point out that the Debug commands will often
work if you have specified an invalid filename for a file i.e. one not starting
with a filemark but there are no guarantees. Forgetting the terminating
filemark can be a nuisance for cassette ops and printing, and a total disaster
if you then try to assemble or merge the endless file.
5.2 MERGING & DELETING
We implemented these functions as Edit Shift operations, rather than Debug
commands, to give extra flexibility and to tie up with the 'Show it
rather than tell it' philosophy of a full-screen Editor. The cursor
is used to identify the starting point for merge & delete operations; and a
filemark is used to terminate the operation. When a merge key is pressed
ASZMIC searches from a little past the shift macro line down to a little
beyond the current end of data pointer to find the merge start character
( > for Shift G < for Shift F * for Shift D ) and then copies the source
text down (or up) to the cursor position until it finds a filemark in the
source text. Long merges can blank the screen for a moment.
At one extreme this is a conventional file merging operation, at the other it
becomes a text macro. You can, for example, copy in a file of subroutines
from tape and merge them into a program. You can also, if you are writing a
program with a lot of data in it, code something like > DEFB o high up in
the text area and then whenever you hit Shift G the string DEFB will
be incorporated into your program. This can save quite a lot of typing.
When you want to delete the source file/string which you have merged you just
position the cursor onto the merge character and press Shift 2
and, Presto, it has been deleted. A filemark will always stop a delete or merge
operation. Failure to terminate a merge source string with a filemark will mean
that the poor computer will go trying to merge on forever. You can break
back to ASZMIC. Deletes just refuse to work if they cannot find
a terminating filemark.
5.3 EDITING
You have covered the EDIT functions pretty comprehensively in Chapter 2, so
here we will just give a few hints & tips. Remember the use of the E string
command as a Shift Macro when you want to search out all occurrences of a name
in a file. Hitting /NL/ in the middle of a previously written line will convert
it to 2 lines, and Typing Rubout can be used to concatenate lines by deleteing
a /NL/. Please try not to edit in the top 20 lines of the text area unless you
are working with a shift macro. These lines are really padding to preserve a
clean display and deleting them could mean that you generate an illegal display.
In particular using type rubout to delete the /NL/ at the very beginning of
display can leave the vital (but invisible) start of data marker exposed with
later disastrous consequences. Editing out the blank which ASZMIC ensures
is before every /NL/ can also cause you to lose the cursor in some circumstances
and can cause cosmetic errors in assembly and merging. Writing more than a few
lines with more than 36 characters in them on any one display page can also
cause ASZMIC to position the cursor off the visible page, although this does no
harm.
When you want to insert lines in a text you should position the cursor
on the line above the desired insertion point, hit Shift W to get to the end of
the line and then hit /NL/ to create a new blank line. Shift 7 followed by Shift
6 will take you back to the beginning of a line. Remember that Shift Q rubs out
under & forwards whilst Shift 0 rubs out backwards.
5.4 PRINTING
The way the printer operates is determined by 2 bits in ASSFLG. This flag is
set automatically by the Assembler (it is in fact the options byte) and zeroed
at assembly termination (unless you used the Break key to escape from an assembly)
so if you want to control the printer you have to set these bits yourself.
Bit 1 set to 1 will route almost everything ASZMIC, as opposed to you, writes
to printer and Bit 5 will set the printer in fine pitch mode with 64 chars per
line.
You can fool the printer into writing double height characters if you want. If
you write a line of up to 32 characters and then pad it out with blanks (no
/NL/ ) to a total of 48 characters, and then type in the 32 characters again in
EXACTLY the same order you will get, not a long line with 2 messages, but
a single message with double height characters when the line is printed.
This can be effective for titling, and if you do it a lot you will learn to use
the merge facility as a convenient way of generating the double texts. If you
get the number of blanks wrong the effect is, well, interesting but hardly
legible. This technique will also work for fine pitch printing but double up
to 64 chars of message and 32 padding blanks.
Remeber the use of the Break key to get you out of print situations when you
have forgotten the terminating filemark. Finally, printing takes place indirectly,
that is ASZMIC jumps to the print routine via an address in RAM. If you alter
the contents of PRTJMP to the address of your own print routine then ASZMIC
will use yours instead of the Sinclair interface built in. Print is entered with
the stack containing the start of the line to be printed, and your routine must
clear this and exit with a RET with HL pointing at the first character after the
/NL/ which terminated the line.
5.5 CASSETTE OPERATIONS
Your cassette recorder should function with ASZMIC at the same volume and tone
settings as with Basic. ASZMIC should in fact work rather more reliably since it
maintains a tone to the recorder until just before recording starts; so that the
automatic gain control on most low cost cassette recorders will not be so
obtrusive as it is for Basic. If you want to set up your recorder for a new tape
brand then try recording a sequence of blanks ( KoS "NULL" :7000 :7FFF );
just after switch on when the program area is empty works very well. Try loading
it back in with your recorder volume control set to minimum and then watch the
effect as you slowly increase the volume. The screen will change from "white &
swimmy" to a series of well defined striated bands to a predominantly black
screen when the volume is too high. The volume control is best set in the middle
of the "band" region.
5.5.1 HEADERS & FILES
Since there are 2 types of "file" we can manipulate with cassette; genuine
text files and defined regions of memory, we have to give each tape file a
seperate identification since memory regions do not have file names. When
you issue a save command to ASZMIC it writes out the command itself as a
header and then pauses before writing out the file proper. On playback the
syntax of the save command represents a virtually unique character sequence
which ASZMIC recognises, and causes it to be displayed for a few seconds
to identify what is on tape. If the identification in the header and the
Load command correspond then ASZMIC checks the rest of the header to find
out if it is loading text or memory and reacts accordingly. You always come
back from Load in Edit mode. There are a couple of extra features associated
with loading a memory region. The first is that the region into which the
saved program/data is loaded is offset by the contents of the OFFSET variable,
so you can do a relocated load from tape. The second is that if you analysed
the contents of LABSTK & LABEND and wrote out a Symbol Table to tape, then if
you followed the 'end of region' definition with a space and then the letter L
ASZMIC will recognise the load as a Symbol Table and set LABEND accordingly.
LABSTK is unchanged so you must have the same size memory and not have
relocated the Symbol Table before the save. A small feature but Symbol
Tables are sometimes worth saving for library or debug purposes.
The physical seperation of header and file on tape gives you the chance to
do some very complex things by juggling and over-recording. This is for the
benefit of those hardy souls who are not content till they have abused a
system to a maximum, or the more practical who wish to recover a poor
recording. The details you have to work out for yourself. Note that if
RDCASS is called before the tape has run onto the half-second silence
before a file or header it can pick up rubbish (depending on volume setting
and screen contents at record time). The silence will, however, synchronise
it onto a byte boundary so that the file may be displaced but will not be
corrupted.
5.5.2 CREATING BASIC PROGRAMS
There IS one creative abuse of the cassette recorder which we must mention.
For those of you who do not have a board which holds both ASZMIC
and BASIC Roms the cassette recorder is the most accessible form of
communication between the two. In the Application notes you will find a
listing for a general purpose program which simulates the context of a Basic
program with a single REM in it. By placing your own code at the indicated
point you can cause it to be incorporated into the REM. A cassette save of
the program will then be loadable by Basic, for the example given the
identifier "123456789" is used, and you can then add lines of genuine Basic
and reference the code in the REM by a USR (16514). Your code should not
affect the HL' register. You will need to use the OFFSET facility when
assembling the program. On a 16K system ORG .4000 and OFFSET = :3000 works
very well, but you must have a 9 byte header since the first 9 bytes
of the variables in Basic are not recorded.
If you want to go back in the other direction (it takes all sorts.....) then
you must start by initiating a save of a memory region large
enough to hold the Basic program. You can abort it with Break as soon as the
memory starts to be written out; all you want is the header. Then back the tape
so that you are just before the data which began to be recorded. If you then
perform your save of a basic program it can be loaded back by ASZMIC. You will
have to abort the load manually when the Basic program is complete.
Alternatively you can write a very small program which uses RDCASS to get bytes
from the tape and store them. This latter approach is probably quicker and more
controllable.
In the beginning ASZMIC had a super fast cassette interface with parity
checking and lots of goodies, plus an offset ASCII character set and an
RS232 style printer interface. We changed it all to give you Sinclair
compatibility on characters, printer & cassette so we hope that someone
does make use of this, otherwise it was all wasted.
THE ASSEMBLER chapter 6
Before discussing the Assemhler section of ASZMIC we should look at what an
assembler does for us. Unlike BASIC, assembler statements are closely
related to the actual operations of the Z80 cpu. The Z80 has a well defined
set of logical, arithmetic and data movement operations which it can
perform operations which are relatively easy to understand even if it
takes a little time and practice to use them to perform 'useful' work.
Unfortunately the instructions which direct these operations when they are
read in from memory are more meaningful to the digital decoding logic in the
Z80 than they are to flesh and blood.
6.1 MNEMONICS
The first thing an assembler can do for us is to allow us to write down the
instructions for the Z80 in a form which is more expressive for us, and then
translate them to the Z80 codes; for example CCF as an abbreviation for
Complement Carry Flag is easier to remember than hexadecimal 3F. This can
be extended further by allowing us express the Z80 instructions in terms
of operations on operands meaningful in terms of the Z80 internal architecture
(which is relatively comprehensible) and having the assembler decode the fields
down into valid instructions. The assembler thus enables us to write Z80
instructions in terms of our conceptual picture of the ZOO.
6.2 SYMBOLS
The other thing that the assembler can do for us is to allow us to use symbols
instead of the binary codes that the ZOO enjoys to represent data and
addresses. Data items can be written in the decimal or character formats
which we are used too. The ZOO works with defined addresses in memory. Very
often we do not know as we code a program where its constituent routines
and entry points lie. We can give them symbolic names, called LABELS, and
let the assembler bear the burden of assigning precise addresses to them.
Some of the symbols the assembler uses are self-defining, things like numeric
constants, and the rest tend to be labels which can either be explicitly
defined with a directive to the assembler, or can appear as the first field
of a statement in which case they are assigned the address at which the code
generated by that statement will lie in memory. This address is called the
location of the code, the assembler keeps track of it by an internal variable
called the location counter, and there is a special symbol, the $ sign, which
the assembler interprets every time it encounters it as the value of the
location counter at the point of encounter. Thus the statements:-
LABLAB JP LABLAB
JP $
have the same effect when assembled.
6.3 HOW DOES IT DO IT?
When the assembler reads through your program for the first time, and it
encounters a label used as an argument in a statement, then if the label has
been previously defined to the assembler the address or value associated with
it can be incorporated in the instruction, but if the label is something like
a jump address further down in the program then the poor old assembler is
stuck for a value. The solution to this problem is that the assembler always
assembles your program twice (makes what the refined refer to as a second pass
over over the program). The first pass pretends to generate code, but really
only generates a table (The Symbol Table) which at its conclusion contains
a defined value for every label. The second pass can then reference the Symbol
Table to substitute valid values for symbols and generate executable (object)
code, fancy listings and error messages. Whilst we are talking about the Symbol
Table let us slip in a few definitions. A label which is encountered as an
argument before it is defined is called a forward reference, a label which
is defined more than once in a program is called a duplicate definition, and a
label which is referenced but never defined within the program is called
an unsatisfied reference unless you have found some way to define it into
the Symbol Table ( e.g. Immediate statements or use of force pass 2
option) externally in which case it is called, surprisingly enough, an external
reference.
6.4 OPTIONS
When you use the A command to tell the Command Interpreter to invoke
the Assembler you specify a file which is to be assembled, and also an OPTIONS
field, which tells the Assembler how it is to work. Some of the options are
pretty obvious. You can elect to generate an assembly listing...very important
when debugging your program. You can elect to have the listing and any error
messages directed to printer, with 64 characters per line if you want.
You can suppress the generation of object code...............
..useful in the first stages of checking a program and in other circumstances
too.
Then you can select some less obvious options. They are concerned with the
linking together of seperate programs into a functioning whole. Normally
when you initiate an assembly you zero out the Symbol Table, but you can elect
to preserve it if you wish. Why? To allow your program to use external
references defined in it. You can also elect that the assembler will proceed
immediately to pass 2, which from our discussion earlier should be disasterous
Why? Because when coupled with the Symbol Table preservation option this allows
us to assemble together many seperate programs with cross-references into a
functioning whole.
If you look in Appendix 3 at the A command it summarises the options available
and the numbers which represent them. The options field is just the sum of the
numbers for the options you want . So if a listing on printer, normal pitch,
but with no object code is your desire the options field becomes 64+2+1 or,
if your mental arithmetic is good and your patience weak, you can write 67
directly
6.5 OFFSETS
There is a variable called OFFSET, whose location you will find in
Appendix 4, which has a special significance for both assembly and loading
from cassette. The value of this variable is normally zero, and it is used
as a relocation offset by the Assembler.
The way it works is this:- Normally when you code a program you expect
it to be assembled at the location you have specified with an ORG staement
so that it will execute at that location. We say that in that case the
EXECUTION LOCATION COUNTER and the LOAD LOCATION COUNTER are synchronous.
But what happens if you are writing a program which will not be executed
after assembly, but will instead be written out to an EPROM programmer to
generate an EPROM which is supposed to execute starting at location zero.
You have to write an ORG 0 statement at the start of the program so that the
program is internally consistent, but if you just left it at that the assembler
would try to generate the object code on top of the ASZMIC Rom. This would do
no harm but your object code would be lost. You need some way to tell ASZMIC
that it must place the object code somewhere else.
The OFFSET variable is the technique you use to achieve this. When ASZMIC is
writing out object code it adds the contents of the OFFSET variable to the
execution address to generate a load address at which each object byte is
to be situated. If, before an assembly, you set OFFSET to :7000 then
code which is supposed to execute starting at location 0 will in fact be loaded
into memory starting at address :7000.
Remember to reset OFFSET to 0 when you are finished. ASZMIC
will not do it automatically for you and you will have a fine old time
wondering where your next assembly has vanished to.
6.6 ASSEMBLING
You invoke the assembler by typing in A followed by the name of the file
you wish to assemble and, unless you want to take the default of object code,
no listing, error messages on screen, and new symbol table, an options
field to control the assembly.
You must obviously have first written the program you wish to assemble, using
the Editor or loading in a previously written file from cassette. Make sure
that the file containing the program obeys ASZMIC conventions i.e. that it
starts with a filename whose first character is a filemark, and that it is
terminated by a filemark as the first character of the line after the final
program line. Within the file the program lines, assembly statements, are
written according to the conventions used by ZILOG and MOSTEK, the
manufactures of Z80 chips (the only exception is the EQU directive). These
conventions are, in brief, that the first character of the statement should
be a blank unless you wish to specify a label at that point, and that any label
be terminated by = or blank. There then follows an op-code or directive
which must be terminated by at least one blank. If the op-code or directive
needs it there then come one or two arguments. If there are two arguments
they must be seperated by a comma without any preceding or following blanks.
The final field (argument, op-code or directive) that you write may be
terminated by a /NL/, a blank or a ; (semicolon). If a semicolon is found
then any characters after it on the line are treated as comments.
If the first character of a statement is a semicolon then the whole statement
is treated as a comment. If a label starting in column 1 of the statement is
terminated by an = (equals) sign then the assembler assumes you are using
an EQU directive to define the label, and searches for an argument after
the = sign (you can have intervening blanks if you want) which is evaluated
and assigned to the label.
Please note that the Assembler exits by using an RST 0 instruction instead
of a RET, so that you can use the O command to see the end of the
region for object code in the IX and IY registers.
6.6.1 DIRECTIVES
The ASZMIC assembler has two genuine directives, ORG and =, which do not
generate executable code, and three pseudo-directives, DEFB, DEFW, and DEFM
which do not generate EXECUTABLE code but produce object code which is a
representation of the data values expressed in the argument after the directive
itself. We touched on = in the last paragraph; so we will look
at ORG now. ORG causes the following argument to be evaluated and transferred
to the execution location counter (the IX register). You can use it at program
start to define where the program expects to be executing (and where object
code will be located if you have left OFFSET at 0) and in the middle of a
program to generate space. A cunning use of ORG in mid-program is a
statement of the type:-
ORG $+20
which will reserve 20 bytes of empty space in mid-program for use as a buffer
or whatever. ZILOG use a DEFS directive for this purpose which we did not
implement in ASZMIC because it was redundant. You cannot use forward references
in ORG or = directives (there are ways round this but please phone your
friendly local university computer department to find out about them
rather than us).
DEFB will quite simply generate one byte of object code with the value, modulo
256, of the argument in it. DEFW will generate 2 bytes but with the least
significant byte first in the way the Z80 expects so that:-
DEFW :1234
will produce what looks like :3412 in memory.
DEFM searches for a " (quote) sign and then transforms every character
after it to a byte in memory according to the Sinclair values assigned to each
character, until it finds another " which tells it to stop. This means that
you cannot have " signs in a DEFM argument. Do not try coding two together
to get round this, it just does not work.
6.6.2 OP-CODES and ARGUMENTS
Op-codes are the mnemonic representation of Z80 operations. You can read about
them in the Z80 assembly manual of your choice, and remind yourself
about what they are and what they do by browsing thru appendix 5. Arguments
are expressed in the standard ASZMIC form which you have been using already.
They are defined for you in the "FIELDS" paragraph of Appendix 1.
The only argument you will encounter which you do not use generally
throughout ASZMIC is the $ (dollar) symbol, which represents the value of
the execution location counter at the start of the statement in which the $
occurs. This has been a short paragraph for a large topic because this is
the information which you will hopefully have gleaned from your book on Z80
Assembly Programming.
6.6.3 COMMENTS
Comments are always said to be a VERY GOOD THING in a program of any sort,
and are particularly desirable in assembler programs because the code tends
to obscure function by detail ( the Devil's Data Dictionary claims that by
the time the average professional programmer has reached the twelvth line
of a program he has completely forgotten what the first six did). We follow ZILOG
conventions by allowing you to terminate a statement with a semicolon
and then fill up the rest of the line with commentary. Unfortunately the
screen can only have 36 characters on a line (32 for the printer) so that by the
time you have allowed 16 positions for location and code in an assembly listing
you are liable to lose long arguments from the program statement, never mind
comments tagged onto the end. They are still useful in the source code (sorry,
source code is the name for the programs you input to the Assembler). Option
bit 5 will remove the truncation effect, and also set the printer in fine
pitch mode to give you up to 64 characters per line.
The assembly listing consists of four distinct fields. The first is the
single byte error flag which is placed in column 1. The second is the
four hexadecimal digit location at which the code generated from each
statement will lie (i.e. the value of the Execution Location Counter at the start of each statement); the third is a hexadecimal representation of the
one to four bytes of code which each statement can generate (note that DEFM
can generate up to 5 bytes before truncation); the fourth is as much of the original
statement as the Assembler can fit into a 32 character line.
The listing, or error messages if a listing is not selected by the OPTIONS
field, will be routed to printer instead of to screen if bit 1 of the
OPTIONS byte is set.
6.10 LIBRARIES
If you are just beginning with assembly programming you can ignore this
section and the next one. They describe slightly exotic functions which you
probably will not want to use for a while. A library is a piece of object
code which contains frequently used routines accessible to many different
and independent programs. If you write a program which needs such a routine
you could always load in the source code from cassette (or microdrive when
they become available), merge it into your program and then assemble the
whole, but after a while you tend to find this a cumbersome and unecessary
procedure. How much more pleasant to load in your collection of useful object
code routines once (things like input and output routines, drivers for special
peripherals, multiplication and division routines and the like) and have
them available for all comers when required. Such a collection of routines
is called a library (no prizes for guessing why) and is characterised by the
fact that the routines within it are internally self sufficient1 and do not
need to reference any external program. A library contains definitions, but
no external references.
How would you use such a set of routines with ASZMIC? To begin with you would
assemble the library modules (module=constituent program) and save both the object
code (the library itself), AND THE SYMBOL TABLE WHICH ITS ASSEMBLY HAD
GENERATED. When you needed to assemble a program which referenced (used) some
routine in the library you would first load in the Symbol Table as
described earlier, and then perform an assembly with bit 2 ("4") of the
OPTIONS field set. This would mean that your program would start off
with a Symbol Table which defined the addresses of all the names in the
library programs, and references made to them would not be flagged as errors.
Of course when you came to execute the program you would have to be sure
that you had remembered to load the library into memory otherwise the result
would be disaster.
6.11 CROSS REFERENCING
The next stage in your development as a jejeune assembler prorammer is to
write programmes so large that you do not have enough memory to assemble
them as a single entity, or to cooperate with friends or colleagues
to write separate sections of the same programme. In this case you are
faced with a situation rather different from that we met with libraries,
because each separately coded and assembled section contains not only
definitions which other sections can use, but references to the other sections
as well. How do you handle a situation like this? It is probably simplest
to postulate an example with three separately coded but mutually (sic)
dependent programmes; PROGA, PROGB and PROGC. PROGA is coded and as its
final statement has ENDA=$. PROGB starts with an ORG ENDA
and terminates with an ENDB=$. PROGC starts with an ORG ENDB statement.
If you then assemble PROGA with an OPTIONS byte which includes bit 6
(no object code) and then assemble both PROGB and PROGC with an OPTIONS byte
which includes a setting of both bits 6 and 2 ( see Appendix 3) then you
will have built up a symbol table which includes label definitions from all
all three programs. You then assemble all three programs again, but this
time using an options field which includes both bits 7 and 2, and you will
have at the conclusion a single piece of object code which is internally
self consistent, always assuming that you have not made any errors.
What you did was to suppress object code the first time you assembled the
three programs in sequence so that at the end you were left with a Symbol
Table which contained all the symbol definitions for all 3 programs, plus a
bunch of error messages which, providing they refer only to unsatisfied cross
references, are irrelevant. Because PROGB and PROGC were assembled
selecting the symbol table preservation option the definitions ENDA and ENDB
were available in the Symbol Table at the time the ORG statements were assembled
so that the programs are automatically assembled to lie together in memory. The
second time we assembled each program we used a preserve Symbol Table option
so that all the definitions were available but, since the purpose of the
first pass of any assembly is just to build up the Symbol Table and we had done
that already, we also used a bit 7 (Force Pass 2) option to prevent the
creation of a lot of duplicate definitions.
6.12 VALETE
That pretty much covers all we wanted to say about the Assembler. The next
chapter tells you how to debug your assembled object code. It is a very good
idea to save your object code on cassette before you try to execute it for the
first time, since mistakes can wipe out the system, and if you want to use
program labels in your DEBUG commands you might also save the Symbol
Table. Remember that ASZMIC comes back in EDIT mode after an assembly and,
please, always start each program with an ORG directive.
PROGRAM EXECUTION AND TEST Chapter 7
When you have written and assembled a program you naturally want to execute
it. ASZMIC gives you two major commands for program execution and one for single
stepping thru a program (we are discounting possibilities such as referencing
the program in an immediate statement using CALL or JP). We shall start
by looking at the DEBUG statements available for program testing.
7.1 THE J COMMAND
This is your primary command for program test. It can be specified with an
address field, in which case the first instruction executed is at the address
specified, or by itself, in which case the address stored
in PCl when last a Break condition occurred will be used as a transfer address.
The J command is characterised by the fact that all the registers are loaded up
from the register image area (REGIM) before execution, and that the I register
is set to 1 to facilitate non-maskable interrupt (NMI) handling and Break
conditions. If your program does not perform register initialisation then you
can initialise the register image area using I or D commands.
This is all straightforward, but _if you J to your program and it contains a
fault, then your chances of getting back to ASZMIC to find out what happened
are slim unless you have an NMI interrupt button fitted to break you out of
unforeseen loops. Your first line of defence against the self-immolating
program is the breakpoint.
7.2 BREAKPOINT
A breakpoint is an RST 0 code. It can be inserted via the B command, in
which case ASZMIC will handle the restoration of the original byte and
manipulate the saved Program pointer value so that you can continue with
the instruction when you wish, or you can insert it yourself by the D
command or by placing it in the original code in which case you must perform
any skipping or replacement needed yourself. The conventional way to use a
breakpoint is to divide your program into logical sections, and then use
the B command to place a breakpoint at the end of the first section. When you
execute the program and come to the breakpoint you can check using the DEBUG
D and O commands that everything has gone as you wish, and then move the breakpoint
to the end of the next section and use the J command to execute the second
section. The process is repeated until you identify a section which fails. Very
often the mere identification of the part of the program which is failing will
concentrate your mind most wondreously and enable you to isolate and correct
the mistake. Remember that the RST 0 code is removed, and the original byte
replaced, when the breakpoint is encountered; so if you want to break again
at that point use the 3 commands G B J to get you thru the breakpoint,
restore it, and restart execution. If you have a breakpoint active
and load in another program on top of the one in which you had the breakpoint
then subsequent moving of the Breakpoint will restore the byte from the old
program into the new. Remember that you cannot single step through
a breakpoint without single stepping into the breakpoint handler.
7.3 THE G COMMAND
When you have isolated the section of a program which is failing you can then
examine its functioning in detail using the G command. This is the ASZMIC
single step feature. It has the effect of the J command but with an automatic
Break condition occurring after each instruction. Break conditions always
cause context saving in the REGIM area. If you want to step thru a number of
instructions before coming back to ASZMIC you can specify a step count as a
second field in the G command. In that case you have to specify the first
field, the address to GO to, explicitly even if it is the stored Program
Counter value.
The use of a step count with the G command can be extremely useful. Remember
that although you do not return to ASZMIC until the step count is exhausted
there is a break with context save and restoration after every instruction
so that execution is very much slower than it would be normally. Since the
single step feature works by using the ZX8l NMI coupled timer to simulate
a breakpoint, the breakpoint and single step breaks are handled by the same
code, and this gives you the facility to simulate a Rom breakpoint. If you
have a home cooked Eprom with routines starting at :2000, and you want a
breakpoint at :2122, then you use a B :2122-1 command and execute the Eprom
routine with a G :2000 32767 command. ASZMIC will then single step through
the Eprom code until it has executed the instruction before that at :2122,
and then it will think that it has encountered a breakpoint and stop
the single stepping.
The G command uses the ZX8l NMI interrupt timer in a special way, and is
thus not fully compatible with routines which drive the display since they
require an I register with 14 in it and an enabled maskable interrupt.
A little ingenuity with breakpoints and single stepping over non critical
sections will probably see you through problems like that.
7.4 THE O COMMAND
This command, which displays the saved registers from the REGIM context
save area, really comes into its own when you are program testing. The
registers are displayed as 2 lines in the order:-
PC HL HL' BC' DE' AF'
AF BC DE IX IY SP
The ' (prime) registers are the Z80 alternate registers. PC is the
Program Counter which tells you which instruction you are next due to execute.
SP is the Stack Pointer and the rest are the standard register pairs. We
are sorry that we could not print up headers above the dumped registers, but
it takes as much ROM space as a printer interface to do that and it burns up
the text area twice as quickly, so we felt that it was better to ask you to
refer to the documentation.
The O command is usefully placed as a Shift Macro when you are debugging
a program (i.e. hit Shift T and type O on the top line). Every Break
condition, be it breakpoint or single step, then gives you an automatic
register dump. If you have important variables in your program which you
also want to dump out each breakpoint you can concatenate commands on
the Shift Macro line, using ;/ (semicolon slash) as a delimiter between
each command and starting the command immediately after the /. This facility
is really meant for dump commands but most Debug commands WILL work there;
but do not use an I command since it will then chase its own tail for
eternity (purists call this a reiterative loop).
7.5 THE I COMMAND
We are told that some CP/M debugs have the equivalent of the I command in
them, which proves that it is such a good idea that many people will
discover it independently, not that we ripped off the notion from CP/M.
The I command enables you to write a line of assembler which is then
immediately assembled and executed for you. Before execution the registers
are loaded up using an internal form of the J command, and after the
assembled instruction is executed a breakpoint is forced
to save the context again, so that the I commands execute in the context
of your program. Providing you still have the original assembly Symbol Table
intact you can specify labels from your program in I commands, just as in
other Debug commands. The only snag is that an I command will change the
stored PC value, so remember to J or G to a specific address if you have
used I before them or you will start executing the ASZMIC stack. Use of I
is a good way to rectify some unimportant omissions in a program and continue
with mainstream testing.
The I command is normally used for priming registers, but any executable
command can be given. If you do not leave a space between the I and the start
of the assembler statement then you will be presumed to have started the
statement with a label which you are declaring via the = directive. The
only snag is that the label declaration logic in ASZMIC uses /NL/
as a delimiter so that the I is taken to be part of the label. You can declare
any label you like so long as it starts with I. Henry Ford would approve.
7.6 THE D, F & C COMMANDS
These commands are fairly straightforward in their operation, and we really
only mention them to preserve an illusion of completeness. Dump, and Modify,
are the kernel commands of any debug system. Fill is valuable for initialising
buffer or workspace areas to an initial value. C, whilst having its primary
use in the relocation of code assembled or loaded using OFFSET, can often be
useful to reinitialise complex data arrays from a 'spare' copy in memory when
you want to return to an earlier stage in a program for re-testing without
the trouble of reloading the program. F and C are excellent ways of wiping
out the system, so check for typing errors before hitting /NL/.
7.7 VALETE
Debugging a program, even more than writing one, is a black art in which luck,
logic and intuition are inextricably blended. Logic and intuition you must
supply for yourself, but we wish you all the luck in the world.
GRAPHICS & SPECIAL OPS Chapter 8
Aszmic offers high resolution graphics facilities. The display driver in
the Basic Rom uses a fixed number of rasters (lines) for every character
which it displays. This severely limits the graphics possibilities
available with Basic unless you install special hardware. ASZMIC has a
programmable driver which allows you to set the parameters which control
display yourself, and has also substituted for the Sinclair graphics
characters a special set which are independent of the hardware offsetting
based on raster count. The effect is that from a machine language
program you can plot on a 255 x 144 matrix, maintain a continuous display
(ZX81 only), and still have time to do computation for movement effects.
We suspect that although ASZMIC was really designed as a development
station for assembly language programs, and to a lesser extent as a
teaching tool, many people may use it just because it is the cheapest
way to give yourself a convincing 'Dungeons & Dragons' scenario on
the ZX computers.
8.1 THE ASYNCHRONOUS DRIVER
In the Application notes this program is identified as the KERNEL routine.
Its function is to create a blank display file, display it 50 times a second,
handle syncs & keyboard read, and hand over control to the user program when
it is not busy. From a user point of view all his program has to do is
manipulate the display file contents; the KERNEL takes care of all the rest.
If you are using a ZX80 you cannot use the KERNEL but must instead
build up your display, send it out using OFRM1, and handle
timing and frame sync yourself. If you have a ZX81 and use KERNEL then your
program can act as if the mechanism of display was invisible to it. Do not
take KERNEL as sacrosanct; we wrote it quickly (as did we all the graphics
examples) just to show thw possibilities. You can probably do better yourself
You might start by tuning NNN and IDLE (rasters at bottom of frame and sync
pulse length tuning respectively) so that they suit your television.
8.2 PLOT
The PLOT routine in the Application notes is fed by a subroutine CALL with
the B register containing the X coordinate and the C register containing
the V coordinate relative to screen bottom left. It computes the byte in the
display that contains the point, decodes what is in the byte and inserts
the new point, and then encodes the byte back again. UNPLOT does the same but
deletes the relevant point instead. It does not check for point out of range;
that you can put in yourself. It uses a shift and subtract algorithm to
compute line address, and a little bit of fiddling with the high order bit
in the desired byte to convert to and from the four points (pixels) which
each byte can contain.
8.3 LINE
There is another subroutine given which will use PLOT to generate a line
beteen two specified points. If the line is between XY & X'Y' then D=y, E=X,
B=Y' & C=X' when the subroutine is called. It uses a successive incrementing
algorithm to calculate the points needed with the increment maximised to
avoid redundent plotting. It works in theory, and in practice too, but other
algorithms can give lines which are subjectively more pleasing; particularly
when the line subtends only a small angle to one of the axes. A 'dotted line'
algorithm in particular can often look much neater since one tends to join
up the dots mentally with a much higher resolution than the screen can
achieve; but we hesitated to provide any 'psychological' subroutines. They
seemed to be straying too far from our path of self-imposed utilitarianism.
ULINE deletes a line between the two specified points.
8.4 UPROG's
This is the unlovely name we give to the application programs which create
requests for points and lines which PLOT & LINE generate, and KERNEL
displays. We offer two examples. STRUCTURES will generate diamond
patterns using plot which can look like futuristic space cages. MOIRE will
just write tightly packed lines to give a watered silk (who wears watered
silk nowadays?) effect. We suggest that you get down and write your own UPROG
to get the feel of the graphics. One useful technique that you can use is to
achieve translation of images on the screen by use of LDIR instructions. A
move of less than 37 bytes will translate on the X axis, and a multiple of 36
will give V translation. This is a much easier way of moving composite
images than painstakingly deleting and re-drawing them. You CAN also mix text
and graphics by starting the text on a raster ('V') which is a multiple of 8
from screen top and writing it 8 times on sucessive lines (V's). Remember
that if you put a byte with bit 6 set to 1 in the display then the
Sinclair hardware will try to execute it as an instruction, with results
varying from minimal to a full blooded system crash
8.6 OTHER RESOLUTIONS
You can alter the vertical resolution of each pixel by altering PIXSIZE in
the KERNEL, and the total number of vertical pixels by changing RASTERS, and
the number of blank lines at screen top by changing TOPS. If the product
of PIXSIZE and RASTERS is summed with TOPS and NNN, and the result is around
300, then you will still probably have a synchronised display. Cheap portable
T.V's seem most tolerant of liberties taken with display timing, and costly
colour sets the least. We have to be a bit general about this since there
are over ten billion display type alternatives. Choose one by muttering to
yourself
"TOPS changes blank space at screen top"
"NNN controls my compute time per frame"
"RASTERS controls the number of active lines in the display"
"PIXSIZE sets the vertical size of each pixel"
and looking at your application. We do not frankly see anyone wanting to
use a PIXSIZE larger than 2. Remember to change CLEAR and DISPEND if you
change the display file size or position.
8.7 SPECIAL OPERATIONS
When ASZMIC initialises at startup, it tests location :1000 at the end of
initialisation to see if there is a JP instruction there, and if so does a
CALL :1000. This means that you can add your own ROM onto a system with
ASZMIC and cause it to integrate itself into ASZMIC. You have seen already
how DADDR can be used to intercept coommand handling, PRTJMP to link in your
own printer routine and INTJMP to take over break conditions after context
save (that is what KERNEL does). There is one final reflection that we have
not previously mentioned. KEYJMP normally contains the address KEYRET. If
you put the address of your own handler there it can take over key
interpretation (BC contains the undecoded result from KEYBRD) and then either
jump back to keyret or RET to LIX if you have done all the work yourself.
The address SAVMEM can be used as a jump point if you ever want to reset ASZMIC whilst still retaining data in high memory, or to initialise it for a
>16K memory. The HL register is loaded up with the address which is to be taken as the top of memory and then a JP made to SAVMEM. This
roughly corresponds to a Basic "NEW" with RAMTOP altered
When you are debugging programmes it can be quite useful to have an external
non-maskable interrupt button. The J command supports this by loading up the
I register with 1 so that a single NMI pulse gives the effect of a breakpoint.
You should, of course, use a Schmitt debounced monostable to provide this
but we got pretty good mileage out of a 300 pF capacitor wielded on ZX80,
where in the absence of a G command you really need NMI. Failure to debounce
correctly may cause the screen to assume an "heiroglyphic" appearence but the
first key pressed cures this. On ZX80 bad debouncing can also fool ASZMIC
into thinking that it is living in a ZX8l; easily cured by providing a further
270 NMI pulses so perhaps you had better build a proper circuit instead.
8.8 THE END
We would like to apologise for a slight flippancy which seems to have
manifested itself in places in this documentation. We have felt increasingly
frustrated by our inability to do any more than sketch out the bare bones
of ASZMIC usage unless we issue a 3 volume set in a year or two: and
this manifests itself as a seeming lack of seriousness. There is just so
much which you can do with ASZMIC. We hope that you find it stimulating
and useful. In the future there will probably be quite a lot of supporting
hardware and software developed for it, and we are scheduled to work on a
microdrive version, so with luck it will prove a long term extension to the
capabilities of your ZX80/81.
C FRAZER JOHNSON
Nykoeping Sept. 1982
GENERAL INFORMATION APPENDIX 1
INITIALISATION
After turning on a ZX80/81 equipped with ZX.ASZMIC memory has been divided
into 3 partitions The first consists of system variables, buffers, stack
and register image area (REGIM). The second, which lies between DSPBGN and
(TXTLIM), is the text area. The third is the program and data area which lies
between (TXTLIM) and the top of memory. This area is sized to one quarter of
the available memory on the system. The pointers LABEND and LABSTK both point
to the top of memory. These pointers define the Symbol Table, and assembler
operations will cause (LABEND) to be the address of the current bottom of the
Symbol Table. (LABSTK) is always the top of available memory. The IY
register is loaded with :4000, the I register with 14, and the interrupt mode
set to 1.
If any key is held depressed for more than half a second it will
repeat at a rate of around 8 per second until released.
The screen contains 34 lines of up to 36 characters each. The ZX81 hardware
automatically generates a new line for longer lines but since the EDIT display
logic works by counting /NL/ characters this is a facility which should be
used sparingly.
EDIT & DEBUG Modes
ASZMIC has 2 modes: EDIT mode, identified by a fast blinking cursor, and
DEBUG mode, identified by a slower blink rate. The difference between them
is that in DEBUG mode the typing of a /NL/ (newline) causes the line just
terminated to be passed to the Command Interpreter. If the first letter of
this line lies in the range A-P then some action will be taken, since the
line is then assumed to be a command. It is otherwise ignored.
Keystrokes which do not pass control to the Command Interpreter use a
vertical synchronisation clock which does its best to hold the screen steady
whilst the keystroke is processed. The Command Interpreter disables the
clock for the duration of its operations. The overall effect is that scrolling
and cursor operations generate a slight flicker but still maintain a readable
display. This feature is not available on ZX80.
FIELDS
The Assembler and Command Interpreter both use a subroutine called GETFLD,
which is a general purpose field interpreter. The fields which are valid as
arguments are:-
a) A decimal number containing the characters 0-9 (1 to 5 digits)
b) A hexadecimal number identified by a : (colon) prefix and containing the
characters 0-9 A-F (1 to 4 digits)
c) A $ sign, meaning the current contents of the IX register (used as a
location counter by the Assembler).
d) One or two characters enclosed in quotation marks (").
Items a) thru d) are self defining fields
e) A Symbol. This is a character string consisting of 3 or more characters in
the range A-Z 0-9 . (period) and starting with a character in the range A-Z.
A symbol is only meaningful when it has been defined by appearance in the
label field of an assembled statement (via A or I commands). If a symbol
is preceded by a ? (question mark) WHEN REFERENCED AS AN ARGUMENT then the
rules for minimum number of characters and alphabetic start character are
relaxed. The ? is purely to identify the following string as a symbol,
and is not a part of the symbol itself.
f) Any combination of items a) thru f) seperated by + or - characters.
+ causes subfield addition, - causes subfield subtraction. Parentheses
are not used. ( A left parenthesis will cause BFLAG to be set non
zero).
Fields are terminated by a blank or comma , but not both.
Examples:-
"A*"
12345
:12345
FUDGE
ACCOUNTS.PAYABLE
$
12345+"A*"+:12345-FUDGE+$-?HL+ACCOUNTS.PAYABLE
FILES
A file is a portion of the text area which is identified by a filename
at its start and a filemark (o) as the first character of its terminating line.
The filename should have a filemark (o) as its first character and can contain
the characters A-Z 0-9 . (period).
Example
NOTHING
RUBBISH
FILEl
THIS IS AN
EXAMPLE OF
A FILE
MORE RUBBISH
The file FILE1 is defined as the 3 lines
THIS IS AN
EXAMPLE OF
A FILE
and may be used by commands such as A (not recommended in this case) P, K & E.
The user can define as many files as he wishes, providing each filename is
unique.
PARTITIONS
The user can create more file or program space for himself by manipulating
the TXTLIM pointer which defines the boundary between text and program areas.
Use Dump & Modify or Immediate statements. The symbol table may be relocated
by altering LABEND (low memory bottom of Symbol Table) & LABSTK (high memory
table top) pointers, and moving the content of memory between them if the table
was not empty.
If a non standard memory unit is attached to the ZX80/8l then the ways in
which memory can be divided up will depend on the decoding which the unit
provides. Bear in mind that execution of a program over the 32K boundary can
activate the ZX80/81 display logic hardware, which also relies on duplicate
mapping of the 16-32K & 48-64K regions for its effect.
USE OF ASZMIC ROUTINES
Internal subroutines exist in ASZMIC to aid the user in handling I/O
and various encoding and decoding functions. These must normally be used from
an ASZMIC context (System variables internally consistent, IY=:4000, I=14, IM 1,
22 bytes of stack available). Routines include:-
GETFLD decode a field
PUTDE encode a hex number
WRITA encode a single hex byte
WSTRNG write contents of print buffer to screen
NRM2 write a character to screen
OUTFRM write out a frame to screen
KEYBRD do basic keyboard decode
KEYINT translate decode to a character
RDCASS read a character from cassette
WRCASS write a character to cassette
PRNTER write a line to printer
& many others. See the application notes for definitions ,calling sequences
and examples.
ASSEMBLER
The Assembler is a small, very fast subprogram within ASZMIC which will accept
all standard ZILOG mnemonics for assembler statements. The DEFM,DEFW,DEFB & ORG
directives are supported. The EQU directive is supported in a nonstandard form
Instead of LABEL EQU value use LABEL=value without imbedded blanks.
The DEFS value directive is not supported: use ORG $+value instead, which has
the same effect of reserving (value) bytes of free space. There are no
conditional compilation, listing control or macro directives (hence the SET
directive is not implemented).
A comments field may be appended after every assembler statement if preceded
by a ; (semicolon). A ; in column 1 makes the whole line commentary.
Always start each file to be assembled with an ORG directive. ASZMIC will
probably default you at (TXTLIM) but this is not a design feature and may be
withdrawn.
ORG & EQU directives may not use forward references.
Assembler options (see A command in appendix 3) can be used to control object
code generation and routing of listings.
Errors tested for include label errors (undefined and doubly defined), Op-Code &
relative jump range errors. An error is indicated by a non blank column 1
and error lines are listed even if no list option has been specified.
Use of the Symbol Table preservation option, combined with the "force pass 2"
flag, enables many seperate programs with cross references to be assembled
seperately to generate a single piece of internally consistent object code.
The OFFSET variable can be used to generate an offset between load and
execution counters which enables code to be loaded at one location for subsequent
movement to and execution at another.
THE SHIFT KEYS APPENDIX 2
These are the keys which control the editing and macro functions of ZX.ASZMIC.
Shift 0 ..... TYPING RUBOUT
The cursor is moved 1 position to the left, the character under it is deleted
and all subsequent characters to the right are shifted left 1 place.
Positioning the cursor to the start of a line and then using
Shift 0 will delete the preceding /NL/ to concatenate the two lines.
Shift 9 ..... HOME TO DEBUG MODE
Set ASZMIC in DEBUG mode. Remember the current cursor position for use
by the Shift E keyin. Move the cursor to the bottom line of the bottom page
and move the display file pointers so that this line appears on screen. The
DEBUG mode flag automatically causes the cursor to assume a slow blink.
Shift 8 ..... CURSOR RIGHT
Move the cursor I character to the right but never onto a /NL/ character.
Shift 7 ..... CURSOR UP
Position the cursor at the left of the line above its current position. If
necessary scroll down the display so that the cursor remains on screen.
Do not move cursor onto or past an End-of-Data character.
Shift 6 ..... CURSOR DOWN
Like CURSOR UP, but cursor moves down & scrolling is upwards.
Shift 5 ..... CURSOR LEFT
Move cursor 1 character to left, but never onto a /NL/ character.
Shift 4 ..... PAGE FLIP UP
Move the display start up 27 lines. Position the cursor at the left of the
third line down from the new top of screen. Do not move display onto or over
an End-of-Data character.
Shift 3 ..... PAGE FLIP DOWN
As for PAGE FLIP UP, but the display is moved down 27 lines. If you move
to the final page then the cursor is positioned at the bottom line.
Shift 2 ..... DELETE FILE
All text from the current cursor position right to the first filemark ()
detected is deleted. No action if a terminating filemark not detected. If
the deletion moves the current cursor position onto the final display page
then the cursor is homed onto the bottom line.
Shift 1 ..... DELETE LINE
Delete the line which currently contains the cursor. Position cursor at
start of next line. Do nothing if the cursor is currently on the bottom
line of the final page
Shift T ..... GO TO DISPLAY TOP
Move the cursor to the Shift Macro definition line at the top of the display.
Display page is altered accordingly.
Shift R ..... SHIFT MACRO EXECUTION
Independent of the current ASZMIC mode (EDIT/DEBUG) pass the contents of
the Shift Macro line to the Command Interpreter for execution. Cursor
and display page are unchanged unless as a result of the executed DEBUG
commands. If the line is empty no action results.
Shift E ..... EDIT RETURN
Change the ASZMIC mode to EDIT. Position the cursor at the location it
had when HOME (shift 9) was last pressed. Alter display page if required to
keep cursor on screen. Effect unpredictable if editing has taken place whilst
in DEBUG mode. Fast blinking cursor identifies EDIT mode.
Shift W ..... RIGHT JUSTIFY CURSOR
Move the cursor to the rightmost position of the current line.
(note:- There is no corresponding left justification key. Use CURSOR
UP followed by CURSOR DOWN instead)
Shift Q ..... EDIT RUBOUT
Like TYPING RUBOUT, but the cursor is not shifted left and it is the
character at the current cursor position which is deleted. It is not
possible to delete the last character on a line with a edit rubout i.e. one which
lies beteeen 2 /NL/ characters.
Shift G ..... MERGE
Search down from beginning of display file to find a merge character (>).
Copy all text after it up to but not including a filemark (o) into the text
position identified by the current cursor position. Effect disastrous if
merge and filemark characters missing. In DEBUG mode if a /NL/ is copied then
the line it terminates is passed to the command interpreter, thus making the
copied text into a Command Macro. In DEBUG mode Shift G has the same effect
as a M> command (see M in Appendix 3).
UNSUPPORTED FEATURE:- The Shift D & Shift F keys may be implemented on
your system. They are like Shift G but with start character * and <
respectively.
Input of a normal character causes everything under & to the right of
the cursor to be shifted right one place and the character input is placed
under the cursor. The cursor is then moved one position to the right. The
EOD pointer is incremented.
Input of a /NL/ character will cause a trailing blank to be appended
to the line if the previous character was non-blank. The cursor is advanced
past the /NL/ to the start of the next line. The display page is moved down
one line (i.e. text is scrolled up a line). The EOD pointer is incremented
as required.
If input of a character would cause the EOD pointer to be incremented past
the (TXTLIM) text area upper partition then the character is ignored.
DEBUG COMMANDS APPENDIX 3
Whenever a /NL/ character is written to the text area by ASZMIC when in
DEBUG mode the line just terminated is passed to the Command Interpreter,
which identifies the command by the first letter on the line and calls the
appropriate handler subroutine. A first character not in the range A-P is
ignored.
Several DEBUG commands may be concatenated on a single line by using the
seperator character sequence ;/ (semicolon slash) and commencing the next
command immediately after the slash e.g.
D 0 3;/D 5 3;/D :7000 10
The contents of the Shift Macro line are also passed to the Command Interpreter
when a Shift R key is typed, and this line is also executed whenever a
BREAK condition is encountered (Breakpoint,RST 0,Single Step,External NMI ).
A ..... ASSEMBLE
A filename options
The named file is identified and assembled down to its terminating filemark
() under the control of the option field. If no option field is specified
the default is a 2 pass assembly with object code (executable machine code)
generation but no assembly listing and no preservation of a previous symbol
table.
The option field is converted to an 8-bit byte whose bits when set represent
the following options :-
BIT 7..(128).. force second pass
BIT 6..( 64).. do not generate object code
BIT 5..( 32).. Fine pitch mode on printer. No truncation of listing lines.
BIT 2..( 4).. keep and add onto a previous Symbol Table
BIT 1..( 2).. direct listing output to printer
BIT 0..( 1).. generate assembly listing
Thus an option field to generate a listing on printer without object code
would be :43 (decimal 67) or 64+2+1 (you can write it like that).
Assembler lines start with either a ; in column 1, in which case the line is
treated as a comment; another non-blank character, in which case the
character is assumed to be the first character of a symbol to be defined,
or a blank. There then follows an Op-Code or assembly directive delimited by
a blank, plus up to 2 argument fields seperated by a comma. A comment
field can terminate the line if it is preceded by a ; (semicolon). The file
is terminated by a line with a filemark (o) in column 1.
Example: -
EXAMPLE
ORG :7000
NRM2=:492 ;CHECK VALUE FOR YOUR SYSTEM
START LD HL,$+120 ;ACTUALLY THE ADDRESS OF TABLE
LD B,TABLEND-TABLE
LOOP LD A, (HL)
PUSH HL
PUSH BC
CALL NRM2
POP BC
POP HL
INC HL
DJNZ LOOP
; AND NOW EXIT TO ASZMIC
RST 0
;
ORG :7000+120
TABLE DEFM "TEST"
TABLEND=$
A $EXAMPLE
NOTE:- If the variable OFFSET is non-zero its value will be used to relocate
the object code produced, although the code itself will be generated to
execute at its ORG'd location.
B ..... BREAKPOINT
B address
B
If an address is specified then the current breakpoint is removed (saved
byte substituted back at the current breakpoint address) and the address
specified becomes the new breakpoint address. The byte at that address is
saved and a RST 0 (:C7) code substituted. When the breakpoint is encountered
in the course of program execution the saved byte is automatically restored
ready for recommencement of execution. If the B command is given without an
address then a RST 0 code is placed at the current breakpoint address.
C ..... COPY
C from to bytecount
An intelligent copy operation of the specified number of bytes from the
first address specified to the second. If the source and destination ranges
overlap the copy will proceed so as not to corrupt the data in the destination
range.
D ..... DUMP
D address bytecount
D address
In the first case a formatted dump of the specified number of bytes starting
at the address specified is produced. There are 8 hexadecimal bytes to a line
preceeded by a hexadecimal address. Long dumps may cause screen blanking for
a few seconds whilst the dump is generated. Break key aborts a dump.
The second example is of a Dump & Modify mode. The contents of the address
specified is displayed and ASZMIC waits for input. Successive bytes are placed
in memory starting at the prompt address. Input is terminated by a . (period)
after the prompt. This is the only case where hexadecimal fields do not have
to be preceded by a : (colon). The colon is assumed, and decimal values must
be input as 0+decimal field.
NOTE:- If bit 1 of ASSFLG has been set to route dump output to the printer
then the user must precede input on each line by at least 7 blanks.
E .... EDIT
E
E symbol
If no argument is specified ASZMIC merely sets itself in EDIT mode (fast cursor
blink). In addition, if a symbol is specified, the symbol is searched up for
and the cursor placed at its start. The display page is altered if needed.
No action is taken if the string is not found. (Any character other than .
0-9 A-Z will terminate the string comparison operation. o can be first char.)
F ..... FILL
F from to fillerbyte
The specified range is filled with the filler byte.
G ..... GO *** ZX81 ONLY ***
G
G address
G address stepcount
This is ASZMIC's single step feature. If no arguments are specified
then the context is restored from the register image area, and execution of
the instruction at the saved Program Counter address (PC1) takes place. A
single step break is generated at the end of the instruction, the new context
is saved in the register image area, (if the INTJMP variable has been
modified to contain an address other than INTRET a jump to (INTJMP) occurs
at this point) and the Shift Macro line is executed before returning control
to ASZMIC.
If an address is specified then it overwrites the saved Program Counter address
(PC1) & becomes the address of the instruction to be executed.
If a stepcount is specified then the operation proceeds as above, but after
context save and before Macro execution the saved step count is
decremented &, if still positive, then context is restored & the next
instruction executed. The rate of execution is typically a hundredth of
normal, so a large stepcount may take some time to work thru. Maximum
stepcount is :7FFF (decimal 32767). The G command will not work on ZX80.
NOTE:- The single step feature can be used to simulate a ROM breakpoint. Set
the breakpoint for the desired address-I & use G address 32767. Break
handling logic will then think it has reached a breakpoint; & terminate single
stepping, when the stop address is reached.
H ..... HORRIBLE JUMP
H address
This is not really so nasty. It is just a straightforward jump to the
specified address in the context of the ASZMIC Command Interpreter. HL register
points to the command line after the address, & the routine jumped to can do
processing in the ASZMIC context, terminating with a simple RET. An easy way
to link in your own commands.
I ..... IMMEDIATE
I assembler line
An unusual feature which enables immediate assembly and execution of assembler
statements. The assembler line follows immediately after the I (i.e. if a blank
follows the I then no label has been specified). The line is assembled into
object code in low stack, followed by a break code, and then executed
immediately using an internal form of the J command. It thus operates in the
saved program context of the REGIM area. After execution the new context is
saved just as for a normal BREAK.
Labels should only be defined via the Label=value statement form in immediate
statements, & the directives ORG, DEFM, DEFB, DEFW & the JR and DJNZ
instructions should be avoided.
J ..... JUMP
J
J address
This is just like the G command, except that there is no single step
break in execution, which continues under the program logic unless the B
command has been used to insert a breakpoint somewhere in the logic flow.
The effect of a breakpoint, or an externally generated NMI interrupt, is
similar to the single step interrupt.
K ..... CASSETTE SAVE
KS "i.d." ofilename
KS "i.d." from to
KS "i.d." from to L
ASZMIC uses the same recording protocol as the standard ZX80/81, but the way
in which it is used is rather different. ASZMIC can save either files or
regions of memory (which presumably contain programs or data). When you type
a K command there is a S second wait to allow you to turn on your recorder,
then the command line itself is written out to tape to identify the file, a
further S second pause ensues, and the file or memory region is written out.
The command must start with the 5 character sequence K FILEMARK S SPACE
QUOTE as shown above since this is used to identify a title line to the
cassette load routine.
The string enclosed in quotes identifies the file for the load routine, just
like a standard ZX80/81. The filename or memory region to be saved is then
indicated. If the memory range is followed by space L then the load command
will alter LABEND to contain the "from" value when the region is loaded.
L ..... LOAD
L "i.d."
In response to this command the cassette input is scanned continuously, and if
a valid title line is found it is written to screen and the display activated
for 5 seconds, thus generating a running catalogue of the tape contents. If
the "i.d."s of the Load Command and the saved title line match then the title
line is analysed to determine if a file or memory load is required, and the
following file is loaded. In the case of memory load the program/data is loaded
in the region specified on the title line unless the variable OFFSET has
been set to a non zero value, in which case this value is used as a
relocation offset for the region. If the region range in the title line is
followed by an L then the region will be presumed to be a Symbol Table, and
LABEND will be modified to contain the "from" value. This presumes
that save & load took place on the same size system.
Both K & L commands can be aborted by the Break key, which simulates a BREAK
condition.
M ..... MACRO
M character
This is very like Shift G, but you can specify the start identifier yourself
instead of using > as a default. Terminator is o as usual. Do not specify M
by itself, always give a character after it and remember it is the
first occurrence of the character (except for the Shift macro line) which
defines macro start.
N ..... NEW
N
Loads up BC with (TXTLIM). Sets HL to :3CA (Basic NEW command implementation)
Jumps to (TXTLIM). Used for special board ops.
O ..... OLD REGISTERS
O
The register image area is dumped as 2 lines of 6 four hexadecimal digit numbers
The registers appear in the order:-
PC HL HL' BC' DE' AF'
AF BC DE IX lY SP
where PC is the Program Counter, SP the Stack Pointer, and the prime suffix (')
indicates one of the alternate registers. We recommend that the user place an
O command in the Shift Macro line as a useful default, since the registers will
then be displayed whenever a BREAK condition occurs.
P ..... PRINT
P filename
The named file is written out to printer until a terminating file mark is
encountered as the first character of a line. The operation may be aborted
at any time by pressing the Break key.
NOTE:- If PRTJMP variable is set to a value other than PRTRET then the
address in it will be used as the address of the Print Line routine.
SYMBOL ADDRESSES APPENDIX 4
TO ENSURE THAT THE ASZMIC ROM CORRESPONDS TO THE VERSION DESCRIBED HERE;
CHECK THE 2 BYTES AT MKDEF AGAINST THE DECLARED VARIABLE "VRSION" IN
THE LIST. THEY SHOULD CORRESPOND; I.E VRSION E04 HAS MKDEF 04 0E .
ACOM2 0891 DCLPl 0881 EX3IR 0A3B GHXVAL 0BDE
ACOMIN 08C4 DCOMM 057A EX3IRX 0A42 GROUP0 095F
ACOMM 052D DCOMX 057F EXCFl 09A2 GROUPl 095F
AF1 40A6 DCONT 0895 EXCF2 09D0 GROUP2 097C
AF2 40A4 DEl 40AA EXCF3 0A3l GROUP3 0A49
ARG1 4001 DE2 40A2 EXTNAC 09CC GROUP4 0A4D
ARG2 4003! DECLOK 08A2 EXTNHL 0A27 GROUPS 0AAC
ASEXIT 086D DEFMNT 0934 FCOMM 0602 GROUP6 0AB9
ASSFLG 4005 DELAYS 00DC FILCHR 000C GROUP7 0AD0
ASSMBL 0870 DFILE 4023 FLDFND 4076 GROUP8 0AE3
AUDUMP 0223 DFLIP 032E FND2 0C83 GROUP9 0AF3
AXX 0547 DIGCON 0327 FNDLBL 0C72 GROUPA 0B03
BADDR 4007 DLLP1 00D6 FNDLCR 0028 GROUPB 0B30
BC1 40A8 DLLP5 00D4 FNDRCR 0030 GROUPC 0B3C
BC2 40A0 DLN1 03E0 FRAMES 4070 GROUPD 0B61
BCOMM 054C DLOOP1 058E FRMSND 00E5 GROUPE 0B68
BFLAG 4075 DLOOP2 0585 FRMSNX 00E8 GROUPF 0B71
BFLGST 0C2E DLY05 00D2 GlCOMN 096E HASH 08C7
BIGMEM 01A7 DMD2 05ED G2IN2 0B88 HASHDN 08DC
BLONE 055E DMDLP1 05DE G2SBCN 0B76 HCOMM 0652
BOPSAV 4006 DMODIN 05CB G2SUB 0008 HFLIP 0070
BRKCHK 030D DMOUT 05B0 G34TAB 0AA2 HL1 409C
BRKOD 00C7 DMPMOD 05B3 G3G4 0A83 HL2 409E
CALLAS 0823 DMPREG 0733 G42ER 0A40 HLRIN 0CD0
CCC 0BC3 DOLLAR 0C1E G4IN2 0A69 HLRTST 0CD7
CCOMM 0561 DONCHR 0C6E G4IN3 0A76 HMCHK 03F9
CDLP1 0481 DONE 0CB9 G4IN4 0A79 HOME2 0434
CHRTAB 0D92 DOTTIM 0804 G4REG 0A57 HOME3 0448
CINCRT 0470 DPG1 03FE G6INX 0ACE HOMLP1 044A
CKINV 0C9F DSPBGN 40B4 G6PA 0AC7 HRTIN1 0950
CLDIR 0577 DSPSET 019E G8NIXY 0AFl HRTLP 0953
CLNLP 0945 DSPTCH 0947 G92 0B00 HSHDN2 08FE
CLNUP 0941 ECOMM 05F0 GAHERE 0B18 HSHERR 0913
CLPRLD 0BE8 ECPOSN 401D GANOBR 0B23 HSHLP1 08CB
CMDSUB 0295 EDCODE 0080 GARNDX 0B12 IAENT 061A
CMPSTR 02A3 GAUNC 0B1B ICOMM 0655
CMPSTX 02B0 EDEXIT 05F7 GB01 0B3A IGNBLK 0020
CMRTXi 0512 EDIN 0ACA GBCOND 0B37 IMTAB 0AB6
CMSM1 02C3 EDINX 0AC9 GCENTX 022A INHERE 0C9F
COMINC 0C23 EDLP1 0775 GCHERE 0B48 INICON 017E
COMINT 0507 EDLP2 0776 GCINX2 0978 INIT 017C
COMMND 052D ELEM1 4072 GCNTSB 0250 INIT2 0189
COMRTX 0511 EOD 4021 GCOM2 0973 INIT3 0183
COMXTB 051D EODCHR 0005 GCOMM 0615 INTJMP 4019
CONLIN 0023 EODOK 04B8 GCUNC 0B5D INTRET 0lFC
CRCHAR 0076 EX102 09E1 GDLOOP 0B63 IX1 40AC
EX103 0A11 GELOOP 0B69 IXIY 4074
CREN1 045B EX104 09F6 GET2 0059 IYl 40AE
CRGEN1 0457 EX105 0A47 GETCHR 0226 JCOMM 0667
CRHNDL 0C24 EX107 0A81 GETFLD 0010 JGENT 0617
CSTR1 02B3 EX1213 09BB GFCHAR 0C61 JMP2 063D
CTAB 0D04 EX1NN 09AC GFDCLN 0BE1 JMPTYP 064D
CTAB2 0D4B EX1NTA 09BE GFDHEX 0ClA JPTAB 0BCE
CUDRET 048D EX2DBR 0A13 GFDLBL 0C89 KBD1 00F8
CUDRTX 0487 EX2IND 0A2A GFDLBX 0C86 KBD2 00FA
CURSOR 401F EX2NAF 09F9 GFDNUM 0C40 KCOMM 066B
DADDR 401B EX2NAG 0A07 GFDREG 0CBD KEYADD 027F
DBTLIM 0584 EX2NB 09E3 GFDTNM 0C38 KEYBRD 014
KEYINT 0277 NRMCHR 0491 RLOAD 0CE5 WRC1 0783
KEYINX 0275 NULIN2 04E6 RUBDNO 0380 WRC2 078B
KEYJMP 4017 NULINE 04D9 RUBOK 0378 WRCASS 0780
KEYRET 0254 NXTPLN 0818 SAVMEM 018D WREG 073C
KYRDLP 014F NXTSTP 087A SAVSTR 001B WREGL 0742
LABEND 4027 OCOMM 0733 SFILE 067E WRITA 031E
LABSTK 4029 OFFSET 400B SHFT0 0426 WSTR1 02F2
LBINX 08AC OFRM1 016D SHFT1 03BE WSTRG2 02E2
LCOMM 0687 OFRM2 0171 SHFT2 03E2 WSTRLP 02DC
LDF2 0719 OUTFRM 0169 SHFT3 0408 WSTRNG 02D6
LDLP1 06C3 PARSE 0826 SHFT4 0412 Xl 0010
LDLP2 06D2 PC1 409A SHFT5 0423
LDLP3 0703 PCHAR 07F8 SHFT6 0473 X2 0020
LDLPB 08A4 PCOMM 0752 SHFT7 04SF
LDN2 06BC PDOT 0809 SHFT8 0456 X3 0030
LDN6 06BB PDOTX 07F9 SHFT9 042D
LINEND 00C1 PRBUFF 402B SHFTD 0339 ZXJPND 0507
LIX 022D SHFTE 0398 ZXJPTB 04F5
LIX2 0236 PRCLR 0301 SHFTF 0330
LIXIMM 023B PREADY 07D9 SHFTG 0341
LIXSUB 00AD PRIGET 09245 SHFTQ 036C
LODFIL 0716 PRNTER 07CD SHFTR 03B1
LOOPGF 0BF0 PROFF 081E SHFTT 03B7
PRTJMP 4015 SHFTW 0394
LSTEXP 406E PRTRET 07D2 SHIFTS 0339
LX 4000 PSLP 0756 SHOME 03AE
PTCON 00CB SINGLE 0107
LY 4015 PUTA 0B9D SINGLX 01F2
PUTB 0B9C SNLP1 0698
LZ 406E PUTDE 0319 SNLP2 06A8
PUTDEF 0316 SP1 4080
MCOMM 01724 PUTENT 0BAE SRECUR 0679
MFLAG 4000 PUTNN 0B8E SSCNT 4009
MIDWAY 0C70 PUTNNX 0B92 START 0000
MKDEF 0016 PUTOUT 0BBF STENT 039F
MRGCHR 0017 QCOMM 0762 STKLOW 407A
MRGIN 0352 QUOTE 000B STMEND 400F
MRGLP1 035B RASCON 07E2 STRBOK 0773
MSKINT 004A RASPRS 0043 STRCDB 0763
MSMTCH 02D0 RASTER 0705 STRSCH 0762
NCOMM 0728 RCOMM 0762 TABLE 0082
NEGEND 0CB0 RCOMP 0D99 TEMP 400D
NEGFLG 4077 RCOMPX 0DB0 TEMP2 406C
NEGNOT OCAF RDC1 07A2
NGENT 0CB4 RDC2 07A4 TIMING 0066
NGHNDL 0C33 RDC3 0782 TXTLIM 4025
NLBLF 0C45 RDC4 0784 UPDG1 0418
NLONP 0023 RDC5 07C5 UPDG2 0421
NOBRK1 0623 RDCASS 07A2 USAMOD 4011
NOBXRK 061E RDCX 0780 V 0040
NOGCNT 061F REG 4078
NOLIST 0859 REGCOD 4079
NORMSV 0690 REGIM 409A
NOTBRK 0215 VRSION 0E04
NOTHL 0CEA REPEAT 406F WCNORM 08F8
NOTIXY 096C RESTOR 0628 WCRPT 08E1
NRM2 0492 RETNR 0C24 WCTAB 0DC7
NRM4 04A6 RLB 0B96 WCTABX 0DE4
ASZMIC SUBROUTINES Application Note 1
Appendix 4 contains a variable YRSION which de+ines the model
number of ASZMIC which you are using. This is also stored as a DEFW at
MKDEF in the Rom so you can check that the addresses given in App. 4
are correct for the Rom you are using.
NAME ... BRKCHK
FUNCTION ... Check break key; simulate BREAK condition if pressed
CALLING SEOUENCE ... CALL BRKCHK
EFFECT .... Also sets synch pulse level low
USES ... Abort routines
**********************
NAME ... CMPSTR
FUNCTION ... Compare two strings
CALLING SEOUENCE ... CALL CMPSTR (HL) points to found string-1,(DE) to base string
EFFECT end comparison on encountering a /NL/ or any character < - (if the found
string is not preceded by a character less than . (period) then the
comparison is declared invalid. If the first character of the found (& base)
strings is a filemark then a /NL/ must precede the o in the found string for
the comparison to be accepted).
If strings are the same then carry reset, HL points at the beginning
of the found string, DE points at the base string delimiter. If the strings are
not identical carry is set and HL,DE unchanged.
REGISTERS USED ... A,HL,DE
USES ... String identification
**********************
NAME ... COMMANDS
FUNCTION ...
CALLING SEOUENCE ... All commands have form *COMM, where * is DEBUG letter.
HL points at first non-blank char after DEBUG letter. They exit by RET (to LIX).
EFFECT ... Performs actions appropriate to the Command.
USES ...
**********************
NAME ... DFLIP
FUNCTION ... Set address jumped to for Command Interpretation
CALLING SEOUENCE . . . CALL DFLIP HL contains new Command Int. address
EFFECT ... Loads HL into DADDR, takes old value and returns
with it on stack. Uses HL.
USES ... User handling of newline character i.e. ASZMIC EDITOR used
as an input routine for user programs.
**********************
NAME ... DELAY5
FUNCTION ... Display for 5 seconds
CALLING SEQUENCE ... CALL DELAY5
EFFECT ... Send out a display for 5 seconds & return to caller.
FRAMES is loaded with 250 & FRMSND invoked. See FRMSND for details
of return. There is another delay called DLYO5 which sets sync
low and then loops for half a second before returning (uses A & DE).
USES ...
**********************
NAME ... EDLP1
FUNCTION ... Entry point for STRSCH which expects DE to point
to base string, HL to point to high end of search region
and BC to be search region size in bytes+1.
CALLING SEQUENCE ... CALL EDLP1 registers as above
EFFECT ... See STRSCH
USES ... Table search
**********************
NAME ... FNDLCR
FUNCTION ... find first newline char to left
CALLING SEQUENCE ... RST 40 HL points to text
EFFECT ... Positions HL to the left of the first newline found
left (below) its initial position. Uses A & HL.
USES ... Syntax analysis, text manipulation.
**********************
NAME ... FNDRCR
FUNCTION ... Find first newline char to right
CALLING SEQUENCE ... RST 48 HL points to current text position
EFFECT ... Positions KL to the right of the first newline char found
right (above) its initial position. Uses A & HL.
USES ... See FNDLCR
**********************
NAME ... FRMSND
FUNCTION ... Tramsmit a display file to screen until FRAMES
(if positive) becomes zero or a key is pressed.
CALLING SEQUENCE ... CALL FRMSND DFILE must contain address of a valid display file.
EFFECT ... Sends display file to screen; generates sync pulses;
reads keyboard and performs debounce; blinks cursor; returns
with carry set if key pressed,reset if FRAMES timeout.
KEYBRD value lies in BC and STMEND, not HL.
USES ... Display
**********************
NAME ... GETFLD
FUNCTION ... Analyse a field down to a 16 bit value
CALLING SEQUENCE ... RST 16 HL points at or before field start
EFFECT ... HL advanced to field terminator; field converted to 2 bytes in
DE and ELEM1. Zero flag set on return if no field found. Any
argument recognisable to ASZMIC may be in the field. Uses all
registers except BC, IX, IY,I.
USES ... Myriad
**********************
NAME ... GET2
FUNCTION ... Analyse up to 2 fields
CALLING SEQUENCE ... CALL GET2 HL points at or before start of fields.
EFFECT ... Uses GETFLD. Loads ARG1 and BC with first field value, ARG2
and DE with second field value. Zero flag set on return if less than
2 fields found before ; or /NL/ terminator. HLpoints after last field
processed. I,IX,IY unaffected.
USES ... Syntax analysis
**********************
NAME ... IGNBLK
FUNCTION ... Advance HL register to point at a non-blank character
CALLING SEQUENCE ... RST 32 HL points at character string
EFFECT ... HL advanced until a non-zero byte pointed to. A contains (HL).
USES ... Syntax analysis
**********************
NAME ... KEYBRD
FUNCTION ... Scan keyboard matrix
CALLING SEQUENCE ... CALL KEYBRD
EFFECT ... Read the keyboard matrix into H (D5-D1 + shift as DO),
plus 8 address line bits in L. Both H & L = :FF if no key
pressed. Uses A,BC,DE,HL. HL also stored in STMEND.
See ZX81 construction leaflet for key-address/data line connection.
USES ... Read keyboard; Initiate vertical sync pulse.
**********************
NAME ... KEYINT
FUNCTION ... Decode a key stroke
CALLING SEQUENCE ... CALL KEYINT BC contains HL pattern obtained from KEYBRD
EFFECT ... Both B & C must contain at least one zero bit if routine
is to return. Carry set on return if unallowed multiple key
depressions. Otherwise HL is absolute address of byte containing
the legal character and A is offset from TABLE start (HL=TABLE-1+(A)).
Note that the shifted keys A-G,Q-t,1-0 do not return a valid char.
USES ... Keyboard read interpretation
***********************
NAME ... LIX
FUNCTION ... Return point for all handlers in ASZMIC
CALLING SEQUENCE ...
EFFECT ...
USES ...
**********************
NAME ... MSKINT
FUNCTION ... Setup some aspects of ASZMIC context
CALLING SEQUENCE ... CALL MSKINT
EFFECT ... Loads I=14,IY=:4OOO, resets bit 0 of MFLAG, sets interrupt
mode 1. Uses A register.
USES ... Programs entered by J command may need this if they use ASZMIC routines
**********************
NAME ... OUTFRM
FUNCTION ... Transmit a single frame to screen
CALLING SEQUENCE ... CALL OUTFRM valid DFILE content required. B should
contain the number of lines to be written and C should
contain the number of blank rasters at screen top.
EFFECT ... Display a frame
USES ... Display
**********************
NAME ... OFRM1
FUNCTION ... Special purpose OUTFRM
CALLING SEQUENCE ... CALL OFRM1 like OUTFRM but in addition D
register must be loaded with no of rasters per line.
EFFECT ...
USES ... Graphics
**********************
NAME ... OFRM2
FUNCTION ... Specialised display
CALLING SEQUENCE ... CALL OFRM2 like OFRMI but in addition user is
responsible for the OUT instruction to
clear the vertical sync pulse and to load A with the
number of Ml's before the first horizontal sync pulse
is required.
EFFECT ...
USES ... Sophisticated graphics
**********************
NAME ... PRCLR
FUNCTION ... Clear printer buffer to zeroes
CALLING SEQUENCE ... CALL PRCLR
EFFECT ... Blanks out PRBUFF. Uses HL,BC,DE.
USES ... User abuse of PRBUFF
**********************
NAME ... PRNTER
FUNCTION ... Print a line on Sinclair printer
CALLING SEQUENCE ... CALL PRNTER HL points at start of line to be
written. Line is written out to printer until a /NL/
is encountered. On return HL points to char after the
terminating /NL/. Uses AF, BC,DE,HL.
EFFECT ...
USES ... Printing
**********************
NAME ... PUTDE
FUNCTION ... Hexadecimal encode
CALLING SEQUENCE ... CALL PUTDE HL points to output region, DE contains the
number to be encoded into the region.
EFFECT ... Uses WRITA to encode the contents of the DE register
as four hexadecimal digits starting at (HL). HL is incremented
past the last digit. PUTDEF is an entry point which presets HL to
PRBUFF+1. Uses HL, A.
USES ... Output routines
**********************
NAME ... RDCASS
FUNCTION ... Read a byte from cassette recorder.
CALLING SEQUENCE ... CALL RDCASS
EFFECT ... Returns with a byte read from cassette in the A register. Can
be aborted by Break key. Uses A,HL,BC,DE.
You have about 800 microseconds to process the byte before
RDCASS must be called again to catch the next byte.
USES ... Specialised tape analysis
**********************
NAME ... SHIFTS
FUNCTION ...
CALLING SEQUENCE ... All Shift commands are c&lled by the sequence
CALL SHFT* where * is the shifted character and must
have HL=(CURSOR) on entry. They perform action approprate
to the shift and then return to caller.
EFFECT ...
USES ...
**********************
NAME ... START
FUNCTION ... Breakpoint or , if 1=0, Restart
CALLING SEQUENCE ... RST 0
EFFECT ... Restart initialises ASZMIC. Breakpoint causes
saving of context and return to ASZMIC
USES ... Monitor return
**********************
NAME ... STRSCH
FUNCTION ... String search
CALLING SEQUENCE ... CALL STRSCH HL points at first char of base string
EFFECT ... If (HL)<DSPBGN+40 then HL first loaded from CURSOR (Shift
Macro use). Text area from (HL) to DSPBGN+50 searched to find
a destination string which matches the base string. Uses CMPSTR
so carry set if not found or set if found and HL & DE as for
CMPSTR except that if not found HL points at DSPGN+39. Uses
AF,BC,DE,HL. EDLPI is an entry point which expects DE to point to
base string, HL to point to high end of search region and BC to be
no of bytes to be searched+1.
USES ... Syntax analysis
*********************
NAME ... WRCASS
FUNCTION ... Write a byte to cassette recorder
CALLING SEQUENCE ... CALL WRCASS HL points to byte to be written out.
EFFECT ... Byte written out using Sinclair BASIC standard. On return HL
has been incremented and A contains byte just written. Uses
AF, BC, DE, HL.
USES ... Special cassette operations
**********************
NAME ... WRITA
FUNCTION ... Encode a byte
CALLING SEQUENCE ... CALL WRITA A contains number, HL points to encode region
EFFECT ... Number encoded as 2 hex digits. HL incremented past second
USES ... output
**********************
NAME ... WSTRNG
FUNCTION ... Write out PRBUFF to screen or printer
CALLING SEQUENCE ... Call WSTRNG PRBUFF contains at least I non blank char.
EFFECT ... Presets B to length of PRBUFF. Fills PRBUFF backwards with
/NL/'s until a non-blank char found. Drops thru to WSTRG2. Uses A,B,HL
USES ... Output
**********************
NAME ... WSTRG2
FUNCTION ... See WSTRNG
CALLING SEQUENCE ... CALL WSTRG2 B preset to max no chars to write
EFFECT ... If bit 1 of ASSFLG is set then PRNTER invoked followed by PRCLR
and return. Presets DE to PRBUFF. Drops thru to WSTR1.
USES ...
**********************
NAME ... WSTR1
FUNCTION ... Write string to screen
CALLING SEQUENCE ... CALL WSTR1 DE points at string start. B preset to
max no of chars to be written.
EFFECT ... Writes out from (DE) to screen, increments until B count
exhausted or a /NL/ written. Drops thru to PRCLR. Uses all
registers except IX,IY,I.
USES ... Output
**********************
EXAMPLES
Invoke by H command. Use = directives to declare the addresses of the
undefined symbols as defined in Appendix 4. USE AN ORG DIRECTIVE APPROPRIATE
TO YOUR SYSTEM MEMORY SIZE.
1 Write a char to screen
START LD A,'X'
CALL NRM2
RET
2 WRITE OUT A STRING TO SCREEN
START LD DE,STRING
LD B,7
CALL WSTRl
RET
STRING DEFM "ABCDEFG"
3 ADD 2 NUMBERS AND DISPLAY RESULT. CALL BY H START NOl NO2
START RST 16 ;GETFLD
PUSH DE
RST 16 ;GET 2ND NO
POP HL
ADD KL,DE
EX DE,HL
CALL PUTDEF
LD (HL),:76
CALL WSTRNG
RET
4 PALINDROME. INVOKE WITH H START. IMPORTANT BECAUSE IT SHOWS YOU HOW
TO LINK IN YOUR OWN PROGRAM AS A COMMAND INTERPRETER, AND HOW TO
RESTORE ASZMIC AT END. AFTER THE H START YOU TYPE IN THE LINE
TO BE INVERTED.
START LD HL,HANDLE; ADDRESS OF USER C.I.
CALL DFLIP; SWAP CI ADDRESSES
JP LIX ;JUMP TO ASZMIC CONTEXT STILL ON STACK
;
HANDLE RST 48; FNDRCR
RST 40; FNDLCR
SET 7, (IY) ; SET EDIT MODE
LOOP LD A, (HL)
PUSH HL
PUSH AF
CALL NRM2
POP AF
POP HL; CHAR WRITTEN
DEC HL
CP :76 ;DID WE WRITE A /NL/?
JR NZ,LOOP; LOOP IF NOT
POP AF ;CLEAR LIX RETURN ON STACK
POP HL ;ASZMIC CI ADDRESS STORED BY DFLIP
LD (DADDR),HL; RESTORE ASZMIC CI ADDRESS
RES 7,(IY) ;ONLY IF YOU WANT TO RETURN IN DEBUG MODE
RET
5 PRINT NUMBERS FROM 0 TO 6. USE H START
START XOR A
LD HL,PRBUFF
LOOP LD B,A; SAVE A
CALL WRITA
LD A,B; RESTORE
INC HL; SPACE
INC A
CP 7
JR NZ,LOOP
CALL WSTRNG
RET
6 PRINT A LINE
START LD HL,TEXT
CALL PRNTER
RET
TEXT DEFM "SAMPLE TEXT"
DEFB :76; /NL/
7 CREATE A BASIC PROGRAM WITH A SINGLE REM STATEMENT WHICH CONTAINS
MACHINE CODE WHICH YOU CAN WRITE YOURSELF . SEE THE FINAL SECTION
IN CHAPTER 5 .
ORG :4000
DEFM "l2345678"
DEFB "9"+128 ;FINAL TITLE CHAR INVERTED A LA ZX8l
DEFB 0
DEFW 1
DEFW DFILE
DEFW DFILE+1
DEFW VARS
DEFW 0
DEFW VARS+1
ORG $+9
DEFW MEMBOT
DEFW 512
DEFW 0
DEFW :FDBF
DEFW :37FF
DEFW DFILE
ORG $+9
DEFW -l
DEFW 0
DEFW :2l8C
DEFW :4018
ORG $+32
DEFB :76
MEMBOT ORG $+32
DEFW 256
DEFW DFILE-PROG
PROG DEFB :EA ;REM
;
;
; PUT HERE THE CODE WHICH YOU WANT TO BE INCLUDED IN THE REM
;
;
DFILE=$+1
DEFW :7676
DEFW :7676
DEFW :7676
DEFW :7676
DEFW :7676
DEFW :7676
DEFW :7676
DEFW :7676
DEFW :7676
DEFW :7676
DEFW :7676
DEFW :7676
DEFW :7676
VARS DEFB 128
8 GRAPHICS PROGRAMS . .. ... SEE DESCRIPTION IN CHAPTER 8
ENTER BY H :7000
;DEFINITIONS FOR E04 ASZMIC CHECK FOR YOUR VRSION
ORG :7000
INTJMP=:4019
DFILE=:4023
PCONE=:409A
TXTLIM=:4025
FRAMES=:4070
OFRM1=:16D
MFLAG=:4000
RESTOR=:628
KEYBRD=:145
STMEND=:400F
SAVMEM=:18D
NNN=46
TOPS=1
PIXSI ZE=1
IDLE=30 1
RASTERS=255
DISPEND=: 6501
DSTART=: 4100
;
; KERNEL ROUTINE
;
KERNEL LD HL,ONEP
LD (INTJMP),HL ;INTERCEPT BREAK PROCESSING BY OWN HANDLER
CALL CLEAR ;SETUP DISPLAY
LD HL,UPROG
LD (PCONE),HL ;PRIME CONTEXT SAVE TO RETURN TO UPROG
;
ONEP CALL KEYBRD ;READ KEYBOARD (RAW)
LD HL, (FRAMES)
INC HL
LD (FRAMES),HL ;BUMP FRAME COUNT
LD B, IDLE
DJNZ $ ;YOU JUST KEEP ME HANGIN' ON
LD D,PIXSIZE
LD B,RASTERS
LD C, TOPS
CALL OFRKl ;WRITE OUT A PART FRAME
LD A,1
LD (MFLAG),A ;LET NMI INTERRUPT HANDLER KNOW IT MUST BREAK ON 0 COUNT
LD C,NNN+NNN+1 ;SETUP C FOR B COMMAND
EXX
JP RESTOR ;GO INTO MIDDLE OF B HANDLING
;
;SETUP DISPLAY FILE,,,,COULD BE IMPROVED
;
CLEAR LD HL,DSTART
LD DE,DSTART+2
LD BC,:2400
LD (HL),:76 ;/NL/
LD (DFILE),HL
INC HL
LD (HL),0
LDIR
RET
;
; PLOT & UNPLOT SUBROUTINES Y->B X->C
;
PLOT LD D,15
JR $+4
UNPLOT LD D,0
LD A,3 ;MASK FOR PIXEL NO IN BYTE
AND C
SRL C
SRL C
INC A ;C IS NOW X BYTE, NOT PIXEL
LD E,l6 ;BIT MASK
LOOP1 SRL E
DEC A
JR NZ,LOOP1 ;LOOP UNTIL 0-3 CONVERTED TO 8,4,2,1 IN E
CP D ;UNPLOT
JR NZ,ENT2 ;J IF NOT
LD A,E
CPL
LD D,A ;MASK OUT BYTE
ENT2 PUSH DE
LD HL,DISPEND ;PREPARE TO COMPUTE Y ADDRESS
LD DE,:l200
LD A,B
LD B,8
LOOP2 RLCA
JR NC,NOSUBT
OR A
SBC HL,DE ;SUBTRACT ONLY IF BINARY POWER PRESENT IN Y VALUE
NOSUBT SRL D
RR E ;SHIFT SUBTRACTOR
DJNZ LOOP2
ADD HL,BC ;ADD ON X TO GET TARGET BYTE
; NOW PROCESS THE BYTE TO PUT IN THE PIXEL
POP DE
LD A, (HL)
BIT 7,A ;GET ROUND INVERSE TRICKERY
JR Z,$+3
CPL ;CONVERT 7,2,l,0 TO 3,2,1,0
AND 15
;
OR E
AND D ;PIXEL NOW IN
; REENCODE
CP 8
JR C,NOTINV ;DO NOT NEED INVERSION
CPL
AND :87
NOTINV LD (HL),A
;
;FOLLOWING CODE JUST CAUSES SUBROUTINE TO LOOP AROUND UNTIL
;A FRAME HAS BEEN SENT. IT IS NOT ESSENTIAL BUT SLOWS PLOTTING
;DOWN A BIT
;
NLINE LD DE,FRAMES
LD A, (DE)
LD B,A
LOOPX LD A, (DE)
CP B
JR Z,LOOPX
;END OF DELAY CODE
RET
;
;LINE OR UNLINE FROM XY TO X'Y'
;
; X->E Y->D X'->C Y'->B
;
LINE LD A,15
JR $+3
UNLINE XOR A
LD (DORDEL),A ;MEMORY TO DETERMINE PLOT OR UNPLOT
LD HL,XMID
;INIT CELLS
XOR A
LD (HL),A
INC HL
LD (HL),E
INC HL
LD (HL),A
INC HL
LD (HL),D
INC HL
LD (HL),C
INC HL
LD (HL),B
;
;NOW CALCULATETHE INCREMENTS
;
LD L,C
LD D,A
LD H,A
SBC HL,DE
PUSH HL ;X'-X
LD L,B
LD H,A
LD A, (YMID+l)
LD E,A
SBC HL,DE ;HL NOW Y'-Y
POP DE
;LEFT JUSTIFY INCREMENTS TILL ONE >= 128/256
JUSTIFY LD C,L
LD A,H
RLCA
RL L
ADC A,0
EX AF,AF'
LD B,E
LD A,D
RLCA
RL E
ADC A,0
JR NZ,JSTDUN
EX AF,AF'
JR Z,JUSTIFY
JSTDUN LD E,B
LD B,H
;
; DE IS XINC BC IS YINC
;
LLOOP LD HL, (XMID)
ADD HL,DE ;INCREMENT
LD (XMID),HL
LD HL, (YMID)
ADD HL,BC
LD (YMID),HL
EXX ;PRESERVE INCREMENTS
LPLOT LD A, (XKID+l)
LD C,A ;X
LD A, (YMID+1)
LD B,A ;Y
LD A, (DORDEL)
LD D,A
CALL UNPLOT+2 ;PLOT OR UNPLOT THE NEW POINT
LD HL,XPRIM
LD A,(XMID+l)
CP (HL)
INC HL
EX AF,AF'
LD A,(YMID+1)
CP (HL)
EXX
JR NZ,NYLIM ;HAVE NOT REACHED Y LIMIT
LD BC,0 ;ZERO YINC IF AT Y LIMIT
NYLIM EX AF,AF'
JR NZ,NXLIM
LD DE,0 ;ZERO XINC IF A X LIMIT
NXLIM LD A,D ;USE XINC + YINC BOTH 0 AS END OF LINE TEST
OR E
OR B
OR C
JR NZ,LLOOP
RET
;
;DATA REGION
;
XMID DEFW 0 ;ORDER IS IMPORTANT
YMID DEFW 0
XPRIM DEFB 0
YPRIM DEFB 0
DORDEL DEFB 0
;
**********************************************************
MOIRE
**********************************************************
UPROG LD SP,:7F00
MAINLOOP LD DE,:4078
LD BC,:101
MLOOP PUSH DE
PUSH BC
CALL LINE
POP BC
POP DE
INC D
INC D
INC B
INC B
INC B
INC B
LD A, 250
CP B
JR C,OUTCOD
LD A, (STMEND)
AND 1
JR NZ,MLOOP
; ZXCV PRESSED HERE
LD HL,:8000 ;FIRST LOC OF UNAVAILABLE MEMORY
JP SAVMEM
OUTCOD CALL CLEAR
JP MAINLOOP
**********************************************************
STRUCTURES
***********************************************************
UPROG LD SP,:7F00
JR OUTCOD
MAINLOOP LD IX,XVAR
CALL PROSUB
LD IX,YVAR
CALL PROSUB
LD B,(IX+VAR)
LD A, (XVAR)
LD C,A
CALL PLOT
LD A, (STMEND)
AND 1
JR Z,OUTCOD
JR MAINLOOP
;
OUTCOD LD HL,DUMMY
LD DE,XVAR
LD BC, 12
LDIR ;INIT VARIABLE REGION
CALL CLEAR
LD HL, (FRAMES)
LD A, (HL)
AND 15
INC A
LD (XVAR+1),A
INC HL
LD A, (HL)
AND 7
INC A
LD (YVAR+1),A
JR MAINLOOP
;
PROSUB LD A,(IX+VAR)
ADD A, (IX+DIR)
LD (IX+VAR),A
CP (IX+MAX)
JR NC,OUTCOD
CP (IX+LOW)
JR NC,POSCHEK
LD A,(IX+INC)
CPL
ADD A, (IX+LOW)
LD (IX+LOW),A
CALL DIDLIM
POSCHEK LD A, (IX+VAR)
CP (IX+HIGH)
RET C
LD A, (IX+INC)
ADD A, (IX+HIGH)
LD (IX+HIGH),A
;
DIDLIM LD A, (IX+DIR)
NEG
LD (IX+DIR),A
LD A, (IX+INC)
;
DEC A
JR NZ,$+3
INC A
;
LD (IX+INC),A
RET
;
; DATA
;
VAR=0
INC=1
DIR=2
LOW=3
HIGH=4
MAX=5
XVAR ORG $+6
YVAR ORG $+6
DUMMY DEFB 75
DEFB B
DEFB -1
DEFB 70
DEFB 90
DEFB 135
DEFB 110
DEFB 12
DEFB 1
DEFB 90
DEFB 130
DEFB 240
DEFB 0