Hello User,

Here is the latest pack in the MEMOTECH firmware family. It enables you to 
roll up your software sleeves and get down to the job of closely controlling 
your ZX81 processor. You do this by by-passing BASIC when you wish and coding
directly with the Z80 Assembler language. You can now write economic 
routines tailor-made to your needs. If you are an absolute beginner at 
machine code then you should pay close attention to our introductory 
paragraphs and also get hold of a good teach-yourself Z80 handbook.

Good Luck from all at MEMOTECH!

What does an ASSEMBLER do?

If a ZX81 program is written in BASIC, the program is interpreted and 
executed a line at a time. While many users are quite happy with this, by 
modern computer standards the processing is very slow. It is rather like a 
man trying to speak French with a phrase book and looking up each and every 
word as he goes along.

Z80 Assembler code on the other hand is really the language spoken by the 
ZX81. You speak to it directly. Furthermore, by assembling the source code 
into machine code prior to execution, you make the execution itself extremely
drapid - in some cases hundreds of times faster than BASIC.

AOur Assembler pack offers two services: it allows you to enter and edit your 
source code, and it can then 'assemble' that code into executable code.

What can I run the ASSEMBLER with?

The ASSEMBLER has been designed to be compatible with MEMOTECH and Sinclair 
products wherever possible. It can be used with either 16K, 32K or 48K of 
RAM addresses above the 16K mark. Note however that the ASSEMBLER EPROM 
resides between 12K and 16K and therefore cannot be used simultaneously with 
the MEMOTEXT Word Processor or the MEMOCALC Spreadsheet Analysis Pack which 
also occupy the same area. These three software packs can be fitted together 
physically on the same system, but only one should be switched on (at the 
side) at a time.

The ASSEMBLER pack should precede any memory packs and go behind the High 
Resolution Graphics pack (if used).

How do I set RAMTOP?

At a later stage, when the ASSEMBLER is generating an object program for you,
it saves your source labels in a Label Stack which is situated above RAMTOP. 
Each label will occupy 8 bytes there, and you will have to set RAMTOP so that 
enough space is left above it (and below the physical limit of your RAM) to
house the Label Stack. In the case of a 16K memory pack alone, this will
mean setting RAMTOP lower than the default setting of 128 
{byte address 32768}.

Suppose you have a 16K configuration, and you need 50 labels:

Upper address: 32768
Space for Label Stack: 400
New RAMTOP: 32368

To lower RAMTOP by 400:

POKE 16388, 112
POKE 16389, 126
NEW

To calculate RAMTOP precisely, you should multiply the contents of 16389 by 
256 and add the contents of 16388.

How do I begin creating SOURCE Z80 CODE7

The ADD and EDIT options allow you to create a source code program in a 
character array. THIS ARRAY MUST LIE AT THE START OF THE VARIABLES AREA. 
Thus, before you start a new piece of source code you must first clear out 
any variables already defined and dimension your array. The array can 
contain as many lines as you like (as long as your memory is large enough) 
but must have a line length of exactly 22 characters. The last character of 
each line is used by the assembler routine to calculate addresses. Two extra
lines are reserved for use by the editor. So if you wanted to have space for
50 lines You would type:

CLEAR
DIM A$ (52, 22)

The array can be saved and reloaded like any normal array, within a program.

However if you wish to continue processing an existing saved string of 
source code, then you must be careful nor to clear the variables or 
dimension the area again or to activate the program with RUN . Re-entry to 
the program ,should take place with a GOTO statement (which can be stored 
with the original SAVE internal to the program).

Now you can summon the menu of editor/assembler routines by making a USR
call 
RAND USR 16258

This call can be used whenever you wish to move from BASIC to Assembler. To 
return, you simply use the QUIT option (5) list below. The source and object 
codes are preserved after QUIT.

If all is well you will get the following display after the USR call:

1-ADD (to initiate or extend your source code}
2-EDIT (to amend existing source code)
3-LIST (to list source code)
4-ASSM (to assemble object code from source code)
5-QUIT (to quit the ASSEMBLER routine)

Enter the value associated with the function you require.
Each of the four options is described in detail

How does the EDIT facility deal with the SOURCE STRING?

The assembler software has one entry point. This has two functions. The 
first time the editor is used on a particular array, it finds the number of 
lines in your array, initialises the line and end-of-source-code pointers 
and places these variables in the first line of the array. This line is then
transferred into the calculator stack. On exiting the editor these variables
are transferred back into the array. Thus the variables always stay with the
source code array, even when it is saved. All subsequent entries to the 
editor miss out the initialisation stage, allowing you to re-enter and carry
on where you left off .

ADD

On entering the ADD option a listing is made of the last twenty lines of 
code (if they exist). The next line number is then printed, together with 
the cursor, at the bottom left of the screen, ready for the line to be built
up and entered to the array.

In order for the assembler to interpret the source code correctly it must be
in the right format. Each line has three parts; the label field, the 
operation field and the operand field. Each of these must be seperated by 
at least one space and must start from columns 1, 7 and 11 respectively.

Here is a little piece of code

1     7   11

      ORG 16514 Start column numbers 
      POS 60000
LABEL LD  BC,1000 
      RET 
      END

What are ORG, POS and END for?

Each source code program must start with an ORG and POS statement and 
terminate with an END statement.

ORG tells the assembler where the object
code is designed to run from. ORG should be below 32K.
POS tells the assembler where the object code will be assembled in memory.

END denotes the end of the source program.

For example:

ORG 16514
POS 16514
...
...
END

This assembles the object code at 16514 and also runs it from 16514. If POS
is set to 60000 then the program will still contain calls etc relative to 
16514 but the program will reside at 60000.

Error signals:

First statement is nor ORG
Second statement is not POS
Last statement is not END

Are there any special format aids for ADD mode?

A TAB function has been added to the normal SINCLAIR cursor operation. The 
TAB function is accessed via the colon key (shifted Z) and causes the cursor
to jump from anywhere in a given field to the start of the next one. Thus 
the keying sequence for the first line of the above program should be:

:ORG: 16514

followed by NEWLINE. In any case, lines with characters at coloumn 6 or 
coloumn 10 cannot be entered in the array. After each NEWLINE a new screen
listing will be made with the latest line at the bottom. The next line 
number and cursor will then be printed ready for you to complete. If you try
to add more code than there are lines in your array then the control will 
return to BASIC with error report 4.

How can I return to the menu when in ADD mode?

Position the cursor to the first column of the line (it may already be there)
and type STOP (shifted A}. This will return you directly to the menu. The 
current line is not added to the array.

Can comments be placed in the program?

Yes. They must be placed on a line by themselves and preceded by a 
semi-colon. These are ignored by the Assembler and so are not restricted 
to any other formatting demands:
; THIS IS A SUB-ROUTINE HEADING

Can I save my object code in a BASIC PROGRAM?

We recommend using a REM statemen which is the first statement in your 
BASIC program. The first byte will thus always be located at memory address
16514. To place your object code here, cite 16514 in both your ORG and POS 
statements. You should first have set up your BASIC program with a 
sufficiently large REM statement. However, the user normally only needs to 
save his source program in the string array, and re-assemble it on re-loading.

Can I copy a block of Machine Code (as a Subroutine for another program, 
for example)?
Easily! Listed below is a machine code routine to move any amounts of data 
from one position to another. It loads whatever is 'pointed' to by HL into
wherever DE is pointing. It then increments HL & DE. It also decrements BC 
and carries on loading and incrementing until BC=0

Line 3 loads HL (the from point) with an Address
Line 4 loads DE {the to point) with an Address 
Line 5 loads BC with the number of bytes to ,be transferred

When you have written your routine, and if you want to use it in more than 
one program make sure your assemble it above Ramtop Then run this machine 
code routine, setting HL, DE and BC to the values you require. Be careful 
not to overwrite code that you are using.

In the example below we copy a block of 200 (BC} bytes of machine code from 
position 60000 (HL) {which might be above RAMTOP) down to position 20000 
(DE), where it can be executed. The copy routine itself resides at 30000.

1       ORG 30000
2       POS 30000
3       LD  HL,60000
4       LD  DE,20000
5       LD  BC,200
6       LDIR
7       RET
8       END
9  ;THIS PROGRAM WILL
10 ;MOVE 200 BYTES
11 ;FROM 60000
12 ;TO 20000

EDIT

On entering the EDIT option a listing appears with the last line situated 
in the centre of the screen. This is the last line used in this or any other
option, or the line containing an error -if one has been detected- after the
ASSM option. LINE= E is then printed at the base of the screen.

You can now choose to edit, insert or delete any line in the array. Press 
the appropriate initial on the keyboard to make your choice. The current 
option will be indicated by the cursar.

E = EDIT (default)
D = DELETE
I = INSERT

The editor is now waiting for a line number to be entered (followed by 
NEWLINE). Invalid line numbers will be rejected. Non-numerical characters 
cannot be entered. Enter 0 (zero) if you wish to return to the menu.
The following effects (including that of pressing NEWLINE} vary according to
the option (E,D or I).
In EDIT mode: Entering a line number causes that line to be brought down to 
the bottom of the screen where it can be edited in the normal way. Entering
NEWLINE alone causes the current line to be brought down (most likely to be 
the line you have just edited). To return to the menu and keep the line as 
it was, press STOP with the cursor in column one. To enter the edited line 
to the array press NEWLINE.
In DELETE mode: Entering a line number causes that line to be printed at the
bottom of the screen together with the option (Y/N} to delete it or not. 
Press key Y to delete it and return to the listing or key N to just return 
to the listing. Entering NEWLINE alone, again causes the current line to be
brought down ready for deletion. However, in this case, if a line has just 
been deleted then this means that the next line will be brought down. 
Hence blocks of code can be deleted without having to enter the line number 
each time.
In INSERT mode: Entering a line number causes a blank line with that number 
to be printed at the bottom of the screen. Having built up that line, 
pressing NEWLINE will insert it ABOVE the line having the same number and 
shift all the rest of the code down a line. To exit without inserting the 
line, press STOP (cursor in column one). Entering NEWLINE alone allows a 
blank line with a line number one greater that the current line to be built 
up and inserted. Thus after inserting one line, if NEWLINE alone is pressed 
to the LlNE=prompt, then the next line will be inserted after the last 
inserted line. In this way blocks of code can be inserted without having to
enter the line number every time.
Note that in INSERT mode, if you try to insert a line when there is no more
room left in the array, then you will be returned to BASIC with error report
4.

LIST

The LIST option allows you to list the source code either to the screen or 
to the printer.
On entering this option "P/T?" is printed at the lower centre of the screen.
Enter "P" if you want your listing on the printer, otherwise enter "T" for 
TV. Whichever option you choose a listing will be made on the screen, 
starting at the current line, togethr with the LINE = prompt. If the 
printer option was chosen then entering a line number will cause a listing 
to be made on the printer from that line to the end of the source code. 
If the TV option was chosen, then entering a line number will produce a 
screen listing of twenty lines of code starting at that line. Press
NEWLINE to see the next twenty lines or enter another number to list from 
there.
To return to the menu enter 0 to the LINE= prompt.
After you have successfully assembled a source code program, these listings 
will also include an address at the right hand side of each line. This 
addresss is the address of the first byte of code produced by that line, 
relative to ORG. Thus unless ORG is the same as POS this will not be the 
actual address of that byte, but the address of where that byte will 
eventually be when the code is moved to its running position. These 
addresses can either be printed in decimal or in hex. By keying 'D' or 'H' 
(for decimal or hex) the addressing mode can be changed. 'D' or 'H'-will 
appear in the cursor.

ASSM

This option assembles the source code, placing the object code at POS, but
assembling it so that it will run when placed at ORG.
The assembler works in FAST mode, so the screen wilI go blank while it is in
operation and will jump when it finishes.
If the assembler finds an error in the source code it will stop with an 
error report of the form:

ERROR x, LlNE=yyy

See later for a summary of error codes (x).

Pressing any key after an error signal will return you to the menu. The line
containing the error is now the current line, so entering EDIT mode and 
pressing NEWLINE will bring that line down for you to edit before trying to 
assemble the code again.

As the assembler works through the source code, it inserts dummy values for 
all labels. Then, on its second pass, it replaces these for their true 
values. If you use a label that is not defined in your source code program,
then the dummy values for that label will remain in the object code. These 
dummy values are as follows:

0            For a single-byte data label.
0 and 0      For a two-byte data label.
0 and 0      For an address label.
255          For a relative jump label.

Because of the relatively disastrous consequences of these dummy values in 
CALLs and JUMPs, the assembler searches the object code for them, and if it 
finds any, tells you how many it has found using the message xx WARNS
Note that no line numbers are given and that only the CALLS and JUMPS to 
undefined labels are included in the count. Undefined data labels are not 
included.
If the assembler has not found any errors then it will print up the "P/T?" 
notice in the lower centre of the screen together with the WARNS notice, if
any have been found.

It is now possible to list the object code, either to the printer or to the 
TV screen. Press "P" for a listing on the printer, otherwise press "T". 
Whichever option is chosen the screen will clear and the LINE= prompt will 
be given. The listing can either be in decimal or in hex. This is signified 
by the letter of the cursor in exactly the same way as in the listing of 
source code. Enter "D" for decimal, and "H" for hex. If the "P" option was 
chosen entering a line number will cause a listing to be made on the printer
from that fine to the end of the program. If the "T" option was chosen, 
entering a line number will cause a listing of twenty lines of object code 
on the screen, starting at that line. Press NEWLINE to list the next twenty
lines; or enter another line number to list from there.

The object code listing has the following format:

Line ORG     POS     Object
No.  Address Address Bytes
AA   BBBBB   CCCCC   DDD EEE FFF

Enter O to return to the menu.

QUIT

This will return you to the BASIC mode. Note however that the option code 5
will appear on your BASIC screen. There is a possibility that line 5 of any 
existing BASIC program may be deleted if NEWLINE is pressed. Either avoid 
using line number 5 or remember to RUBOUT the 5 when you have re-entered 
BASIC.

Summary of error codes

Error Code Error
     1     First statement is not ORG.
     2     Second statement is not POS. 
     3     No such op-code or last statement is not END 
     4     Syntax error in operand. 
     5     No label space left (only applies to 64K rampacks). 
     6     Number too large (DEFB ahd DEFS onlyJ).
     7     Relative jump out of range or redefined label.

Additional information

1. Labels are not allowed in DEFS or DEFS statements.
2. Labels are not allowed as the offset to the index registers. 
   BIT 7, (IY + DATA) is not allowed 
   BIT 7, (IY + 255)       is allowed
   LD (LABEL), IY          is allowed
3. One statement is too long to fit in the twenty-one character line. 
   This must be written in two lines as follows, for correct assembly.
   LD (IY + disp) {disp and data being 
   numbers, labels are not allowed} data
4. A label in a program is given the value of the (ORG ) address at which it
   occurs . To assign an absolute address to a label, use the EQUATE 
   directive.
   For example:
   LABEL EQU 16514
   LD HL,(LABEL)
5. When using relative jumps, note that the displacement as specified in 
   the source code is placed directly into the object code.
   Thus JR 253 assembles as 24,253
6. The assembler assumes numbers are in decimal unless preceded by a "$"
   sign.
   E.G. LD A,255 OR
        LD A,$FF
7. Labels can be three to five characters long. The first character must be 
   a letter. Subsequent characters can be anything. All characters are 
   significant. DO NOT USE REGISTER PAIRS TO START OFF LABELS .
8. The DEFINE BYTE directive can be used to place single bytes of data 
   within the obsect code. When placing more than one byte at a time on a 
   line, separate the numbers with SPACES. Also ensure that there is space
   at the end of the line.
 
   For example
   DEFB 255 100 10 One space at end of line
   DEFB 255 100 100 No spaces - will not assemble
9. The DEFINE SPACE (DEFS) directive can be used to reserve up to 255 
   bytes at a time for data, tables etc. When found in the source code it 
   simply moves the address pointer on by the specified number of bytes.
 
MEMOTECH Z80 ASSEMBLER was written by Philip Le Sueur for MEMOTECH LIMITED. 
MEMOTECH Z80 ASSEMBLER C) R. BRANTON & G.A.C. BOYD
