This file contains the 3 .DOC files:
AZM-COM.DOC
PHASE.DOC
MAC-AZM.DOC
******************************************************************************
AZM-COM.DOC

The Z80MR creates two output files from an assembly language source file
with a .AZM extention. The assembly language file can be any combination
of Z80 mnemonics or assembler commands and pseudo-ops in the correct form
as described in the file Z80MR.DOC. Each line of the source program is 
seperated by a carriage return linefeed and can be created on any editor.

The object file is the executable machine code represented by ascii 
characters in a form known as Intel Hex Format. The object file will
have the same filename as the source file but will have a .HEX extension.
This format must be translated into the actual machine executable 
binary values in order to be run on a computer. This can be done with 
LOAD.COM or DDT.COM which came with your CP/M. (described later). Many
EPROM burners only accept the program to be burned in Hex format.

The listing file is the other ouput by the assembler. It is ascii
representation of the code actually produced by the assembler. There
are many options available for controlling what is included in the
listing file as described in Z80MR.DOC. The listing file will have the
same filename as the source file but will have a .PRN extension.

Invoking the Assembler.....................................................

To assemble the file TEST.AZM the following command can be used:

	Z80MR TEST <carriage return>

The assembler will read in the file TEST.AZM from the current drive and
create an object file TEST.HEX and a listing file TEST.PRN.

Controlling Output.........................................................

Either of the output files (or both) may be omitted. In addition, the files
may be located on different drives. Since the source file must always have
a .AZM extention we may use the extention to control the output.

	Z80MR TEST.sol

The letter in the 's' position tells the assembler where to find the source
file and may be any disk drive letter from A to D. The  letter in the 'o'
position tells the assembler where to locate the object file and may be
A-D as above or Z if the file is not desired. The letter in the 'l' position
tells the assembler what to do with the listing file. It can be any drive
letter from A-D or Z if the file is not desired. In addition the listing
file may be sent to the console if an X is in that position.

Loading Hex Files..........................................................

The object file must be translated from Hex format to machine executable
values by another program. If the program was written to ORG at 100H the
program may be loaded with the CP/M utility LOAD.COM. All of the programs
on this disk with a .COM extension are ORGed at 100H. This is where CPM
loads its transient programs. To load TEST.HEX with LOAD.COM just enter

	LOAD TEST

The extention of .HEX is assumed.

If you have a program that does not ORG at 100H you must use DDT to read
in the .HEX file which it does by translating the Hex format to binary
as it reads it into memory. Once in memory you may manipulate it with
DDT even SAVE an image of the program in memory actually creating a .COM
file. If you write a program that ORGs where CP/M resides you can wipe
out CP/M and have to reset the computer to recover. See the file PHASE.DOC
for some more information on ORGing files at High memory locations.

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
PHASE.DOC

PHASED code

One of the limitations of this assembler is the lack of a .PHASE directive.
This directive causes the assembler to generate addresses for a different
section of memory for labels than the actual place the code is to be loaded.
This is important for the Kaypro since when the ROM is called, the lower
32K of memory is no longer available. Simply ORGing at higher location
later in the program and jumping there will cause the entire area of memory
between 100H and the end point of the program to be saved resulting in
a huge .COM file when loaded with LOAD.COM. 

There are many ways to phase code and still end up with a reasonable sized
.COM file. Here I will present two of the most common methods.


Label+OFFSET Method........................................................

In order for code to be assembled in one area to run in another, our only
concern is how the addresses are calculated by the assembler. Normally, an
assembler sets a location counter when it sees an ORG pseudo-op. As it
produces each byte of the it increments the location counter to calculate
the next address. If it finds a label, it sets the label's address according
to this location counter. The programmer has another method of setting the
address of labels, with EQU. If every label in the program takes the form of
Label+OFFSET where the offset is a constant, then the assembler will produce
the code to run in high memory while creating a file that will load in low
memory. The following short program which re-loads your monitor ROM from
the ROM to RAM illustrates this.

;**************************************************************************
;**	Rom Save Program                                                 **
;**	Run and then enter SAVE 16 ROM.COM                               **
;**	ROM.COM will contain object code of your monitor ROM             **
;**************************************************************************

	ORG	100h

TRUE	EQU	0FFH
FALSE	EQU	0

OLD	EQU	TRUE		; TRUE IF NOT 10 OR 4-84

	IF	OLD
SYSPRT	EQU	1CH		; old kaypro 2's and fours
	ELSE
SYSPRT	EQU	14H		; tens, 4-84's, 2-84's
	ENDIF

OFFSET	EQU	8000h		; offset for calculating high addresses

	LD	DE,HISTRT	; the destination of the High memory code
	LD	HL,LODEND+1	; the source code is just beyond this loader
	LD	BC,HIEND-HISTRT	; the number of bytes to move (end - start)
	LDIR			; move it up there
	JP	HISTRT		; jump to it
LODEND:	NOP			; to calculate end of loader/start of high
				; memory code segment

HISTRT	EQU	$+OFFSET	; BEGIN USING OFFSET	

	IN	A,(SYSPRT)	; get present sysport data
	SET	7,A		; bank select bit
	OUT	(SYSPRT),A
	CALL	MOVIT		; move the code routine
	IN	A,(SYSPRT)
	RES	7,A		; back to ram bank
	OUT	(SYSPRT),A
	CALL	TPAMOV		; now move to 100H for save
	JP	0		; back to CP/M

MOVIT	EQU	$+OFFSET

	LD	HL,0		; Source is at 0 (in ROM )
	LD	DE,OFFSET+1000H	; Load above us
	LD	BC,1000h	; pick up 4K (2732)
	LDIR
	RET

TPAMOV	EQU	$+OFFSET

	LD	HL,OFFSET+1000H	; destination becomes source
	LD	DE,100H		; move to TPA start
	LD	BC,1000H	; 4K bytes to move
	LDIR
	RET

HIEND	EQU	$+OFFSET	; end of code to be relocated

	END

Assemble this program (the source is on the disk as phase1.azm so you don't
have to type it in). Examine the listing file. Notice that the assembler
generated high memory addresses though the program loads low.

Using DDT.COM..............................................................

With this method you would split the above program into two parts, the 
loader and the code that is to be relocated. You can assemble the loader
and pick an arbitrary source address for the code to be relocated (say 200h).
Then you can assemble the relocatable portion with an high ORG. (8000H say).
Now you can join the two HEX files together with DDT.COM reading in the
high portion with an OFFSET. To get the offset use DDT's Hex sum and
difference command in the form of:

H<desired load address>,<ORG address>

The second number will be the OFFSET. The program we wrote above would go
together like this.


;**************************************************************************
;** Loader.azm             Loads relocating code to its destination     ***
;**************************************************************************

	ORG	100H

BYTCNT	EQU	100H		; we can either supply a value here that we
				; know will load enough code or assemble
				; the high code first and let the assembler
				; give us this value (examine print file)


HISTRT	EQU	8000H		; where the relocation code goes
HILOAD	EQU	200H		; where the other file goes

	LD	DE,HISTRT	; the destination of the High memory code
	LD	HL,HILOAD	;the source code is just beyond this loader
	LD	BC,BYTCNT	;the number of bytes to move (end - start)
	LDIR			; move it up there
	JP	HISTRT		; jump to it
				; memory code segment

	END


;**************************************************************************
;** Phase2.azm                                                          ***
;** Relocate with DDT                                                   ***
;**************************************************************************

TRUE	EQU	0FFH
FALSE	EQU	0

OLD	EQU	FALSE

	IF	OLD
SYSPRT	EQU	1CH		; old kaypro 2's and fours
	ELSE
SYSPRT	EQU	14H		; tens, 4-84's, 2-84's
	ENDIF

BYTCNT	EQU	HIEND-HISTRT

	ORG	8000h	

HISTRT:	IN	A,(SYSPRT)	; get present sysport data
	SET	7,A		; bank select bit
	OUT	(SYSPRT),A
	CALL	MOVIT		; move the code routine
	IN	A,(SYSPRT)
	RES	7,A		; back to ram bank
	OUT	(SYSPRT),A
	CALL	TPAMOV		; now move to 100H for save
	JP	0		; back to CP/M

MOVIT:	LD	HL,0		; Source is at 0 (in ROM )
	LD	DE,9000H	; load above us
	LD	BC,1000h	; pick up 4K (2732)
	LDIR
	RET

TPAMOV:	LD	HL,9000H	;destination becomes source
	LD	DE,100H		; move to TPA start
	LD	BC,1000H	; 4K bytes to move
	LDIR
	RET

HIEND	EQU	$

	END


Now we can use DDT to join the two files.

DDT LOADER.HEX
H200,8000

8200 8200		; in this case both numbers are the same (we want
			; second
IPHASE2.HEX		; prepare to load file
R8200			; read in with offset
^C			; exit to CPM

SAVE 1 PHASE3.COM	; and the com file is created


			
ORGing High ( CP/M modifications ).........................................

DDT.COM can be used to load .HEX files anywhere in memory despite where the
load point (ORG) was set. It does this by reading the file in with a negative
offset with the R command. Usually CPM is modified by saving the SYSGEN 
image and then overlaying the image with the modified section and
re-SYSGENing.

Lets say you wrote a new BIOS for your Kaypro. The BIOS for the old Kaypros
ORGed at FA00H. You assemble it with the assembler with the ORG at FA00H.
The object file is KBIOS.HEX

If you want to overlay the present bios with your new bios immediately to
see if it works it is done as follows:
 
Enter DDT by entering

	DDT <carriage return>
	IKBIOS.HEX		; this sets up DDT for a file read
	R			; actually reads the file in and overlays
				; your old bios with the binary code
	^C			; returns you to CPM and if all is well
				; with your new bios you will warm boot

Now you want a permanent copy of your new bios on your system tracks. Once
done you will be able to copy your new system onto any disk with SYSGEN.
SYSGEN copies the system into memory but not at the same place the system
runs. The BIOS image actually begins at 1F80H in the SYSGEN image. We
must read the file in at 1F80H even though it ORGs at FA00H. We can do
this with DDT also. First we must save the SYSGEN image to a file.

sysgen
KAYPRO SYSGEN V2.2
SOURCE DRIVE (OR RETURN TO SKIP)a	; get the system from A: 
SOURCE ON A THEN RETURN			; enter a carriage return
DESTINATION DRIVE (OR RETURN TO REBOOT)	; enter a carriage return

save 40 cpm.com				; save it to a file	

Now we use DDT to work on it

	ddt cpm.com <carriage return>
	h1f80,fa00		; we ask for the sum and difference
				; of desired address - load address
				; DDT prints this. The second number is the
				; offset
	ikbios.hex
	r
	^C

Now when we return to CP/M we run sysgen to save the new image to system
tracks.
SYSGEN <carriage return>
KAYPPRO SYSGEN V2.2
SOURCE DRIVE (OR RETURN TO SKIP)       ;enter return (use the memory image)
DESTINATION DRIVE (OR RETURN TO REBOOT)  ;we will put it on B 
DESTINATION ON B THEN RETURN		 ; another return
FUNCTION COMPLETE
DESTINATION DRIVE (OR RETURN TO REBOOT)  ; one more return

Now when when we boot with the disk in drive B the new system will be loaded.
******************************************************************************
MAC-AZM.DOC

Most of the assembly language programs released on Micro Cornucopuia disks
are set up for the M80 assembler. If you've been wondering what the .MAC
extension is for, those are M80 source code programs. Many of the people
that got this disk did so to assemble the Kaypro Tinkerkit (source of the
rom monitor and bios) without spending $150 for M80. It can be done.

For the most part .MAC files can easily be translated to .AZM with very few
changes. Unfortunately M80 is as extremely versatile assembler which when
used to its full advantage contains some pseudo-ops and directives that Z80MR
does not understand. I will reveal the most common of these and provide
some help on getting around them in this file.

First things first.........................................................

Rename the file to have a .AZM extension. Edit the file. Near the beginning
of the file you will see the pseudo op that tells M80 what mnemonics you
will be using. M80 can handle both Z80 and 8080 mnemonics. You can even
switch in the middle of the program. Two pseudo-ops .Z80 and .8080 tell the
assembler which mnemonics to recognize. If there is a .Z80 there delete
it. If there is a .8080 there you will need to run the program through an
8080 to Z80 translator (like XLATE2.COM). 

At this point what I usually do is run the program through the assembler.
The assembler is very good at finding errors, so I let it tell me what it
doesn't like. You can run the program through the assembler without 
generating any output files (see AZM-COM.DOC) and still get the error
report on the console. A ^P before running the assembler will dump to the
printer as well. Now you can go back into the file and fix the syntax where
the assembler generated errors. 

Dual mnemonic files........................................................

XLATE2 is a great translator on 8080 only files. It also will only translate
the 8080 mnemonics in a file that has both. Unfortunately there are a couple
of Z80 mnemonics that are the same as 8080 mnemonics and will be dutifully
translated by XLATE2. The problem is that the mnemonics are the same but the
instructions they represent are not. So the file will assemble OK but will
run with unpredictable results. An example.

	JP	is a valid Z80 mnemonic. It is also widely used since
		it is an unconditional jump (JMP in 8080)

	JP 	is also a valid 8080 mnemonic. It is the jump on parity
		instruction.

So a Z80 JP is translated as if it was the 8080 JP which will make it
JP	P in the output file. Bad news. This in itself is enough to make
it too undependable to use on dual mnemonic files. To avoid the grief you
can do one of two things:

	Translate the 8080 sections by hand if they are small enough.

	Split the file into smaller files where the mnemonics change.
	Run the 8080 sections through the translator. You can let the
	assembler rejoin the files using the *INCLUDE statement or
	use pip or your editor to rejoin and assemble the whole mess.

What I'd really like to see is someone rework XLATE2 so that it would stop
translating when it saw .Z80 (and also comment the pseudo-op out) and
start again when it saw .8080 (and comment it out as well). Also some of
the other minor syntax changes could be fixed as well. Yes XLATE2 can be
assembled with Z80MR (it is a .MAC file). After removing the .Z80 at the
beginning of the file the only error I got was for the MOD operation on the
version number (MOD not supported by this assembler). My solution, just
enter the version number there. Having the assembler figure out the ascii
just wasn't that important.

Macros.....................................................................

The M80 macros go through Z80MR pretty well for the most part. There are
some syntax changes to be made.

Precede the parameters with # signs (including locals).

Also there are some macro pseudo-ops that are not supported (also not widely
used). If some one writes Z80MR macros to substitute for these (and a MOD
operator) please send it in and we'll include it in the macro library that
we are developing for this assembler.

.phase and .dephase........................................................

These are used to make the assembler generate label addresses for some other
part of memory than where the file will be loaded. The file PHASE.DOC 
offers some alternative ways of doing this.

