home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ENTERPRS
/
CPM
/
UTILS
/
S
/
Z80ASM24.ZIP
/
Z80ASM24.DOC
< prev
Wrap
Text File
|
1991-10-06
|
18KB
|
530 lines
Z80ASM-DD 24 ---> Fixes to Z80ASM-20 09/12/87
<<< Z80ASM24.DOC >>>
by Dianna Dearborn September 12,1987
This document outlines a number of fixes and enhancements to Z80ASM 2.0
and identifies remaining the bugs that I'm aware of.
FIXES:
-----
-in JR and DJNZ relative addressing instruction operands to allow the
use of symbolic label references
-in JR and DJNZ instructions to allow the use of the $ symbol to repre-
sent current reference counter value.
-in the LABEL: character validation test to allow the use of the $ symbol
in labels
-in valid label test and error reporting routine
-in the "IBM" pseudo-op
ENHANCEMENTS:
------------
-in JR and DJNZ instructions, a displacement range test was added to trap
operand expression which evaluated outside the -126 to +129 byte limits.
-a routine was added to eliminate the initial page eject on the listing
output
REMAINING BUGS:
--------------
-in reserved word test for LABELS:
-in the reference value of the last LABEL: used in a source file.
OTHER:
-a discussion is included on some of the syntax rules of Z80ASM discover-
ed along the way
BACKGROUND:
----------
Some weeks ago, I started to do some serious Z80 assembly language
programming. I downloaded a copy of Z80ASM from a RCPM and started to
write code. My programs crashed immediately.
First thing that happened was the assembler got caught in an
5
Z80ASM-DD 24 ---> Fixes to Z80ASM-20 09/12/87
infinite loop and hung up. I narrowed that down to the use of a dollar
$ign in label names.
Second, there was a bug when using the dollar $ign symbol convention
to indicate the current value of the reference counter in operand expres-
sions in JR and DJNZ relative addressing instructions i.e., "JR $+12H";
it worked as expected in JP and CALL instructions. I found that using
"JR +12H" would work.
Finally, using LABELS: in the operands of JR as DJNZ instructions
crashed i.e., JR LOOP. Again, they worked with JP and CALL operands.
I found no way around this bug. I was left with the choice of either
counting the number of bytes of intervening instructions to calculate
the relative offsets (too much work, prone to error and difficult to
modify) or using only JP instructions. Neither was acceptable, so I
started to debug the assembler.
THE BUGS AND THE FIXES:
----------------------
$ in LABLE$: was indeed an infinite loop probably caused by a typo
in the original source code. The fix was simply to patch in the proper
address in the JP instruction.
Relative displacement errors were caused by a complete lapse of
thought in the mind of the programmer. While evaluating the operand
expressions, JP and CALL instructions create a two byte operand that is
the absolute destination address of the jump. Z80ASM handles them by
getting the reference counter of the current instruction, in the case of
"JP $+12H", and adding to it the value of the expression, and in the
case of "JP LABEL:", by getting the address of the label from the symbol
table and placing it in the operand. Both methods are combined in such
instructions as "JP LABEL:+12H".
JR and DJNZ relative addressing instructions were handled in the
same manor by the same routine as the absolute addressing instructions
and the seemingly random displacement values in their operands turned
out to be the low byte of the absolute address of the instruction's
destination. Relative addressing instructions require that the signed
DIFFERENCE between the current address and the destination address be
placed in the operand which will then be added to the PROGRAM COUNTER of
the Z80 prior to the jump. To accomplish this, I had to add code to
Z80ASM.
After fixing these three bugs, I found that there was, of course,
no trap for displacement range errors. This creates the possibility of
writing an operand expression that evaluates out of range but looks cor-
rect upon cursory examination and then sends your program to never-never
land. These errors can be quite difficult to detect. I added a range
test that is performed after the evaluation of the operand expression
and used the $ symbol, appropriately enough, to flag assembly listing
lines with range errors then forced the operand to 00.
6
Z80ASM-DD 24 ---> Fixes to Z80ASM-20 09/12/87
Along the way I discovered that the reserved word and valid label
length tests did not seem to work. The labels were only tested on the
first pass to validate them before putting them into the symbol table
but the results were not saved for the second pass. I changed the rou-
tine so that now at least the label length is tested on the second pass
and the results are passed on to the listing, however, using a reserved
word or defining a label twice will still cause your program to crash
without warning you of the error.
What actually happens is that on the first pass when a reserved
word or redefined label is detected, the label is not added to the symbol
table and the reference counter is not updated. On the second pass, the
error goes undetected, the op code and operand are evaluated, the refer-
ence counter is updated and all symbolic addresses from the line in error
are off by the number of bytes in the op code of the error line. I
thought about disabling the test altogether, however, this type of error
is easier to detect than one line with a reserved word where it doesn't
belong because every symbolic reference pass the bad line points to a
wrong address. The fix is messy and I need to get on with my project so
I'll save this one for another day -- at least you were warned!!
The other remaining label error has to do with the last label used
in the assembly. For some reason, the reference address (or EQUate
value) of the last entry in the symbol table gets trashed and, when re-
ferenced, will give erroneous results. The way around that is to make
sure that the last label used does not get referenced. I do this by
labeling the 'END' statement. My last line in the assembly is usually:
THEEND END 100H
Again, I'll fix this bug when I get more time to work on it.
While plowing through the Z80ASM code I found a (new to me) pseudo-
op called "IBM". It turned out to be an ASCII $tring formating in-
struction for messages. The routine had three major bugs and I'm certain
that it was never tested after it was written. I sorted it out to what
I think the programmer had in mind. Anyhow, it now works according to
the syntax rules discussed below.
And, lastly, the initial page eject for the listing was a real irri-
tation to me. I tested for page 1 and skipped the form feed in the
header. The page number is stored as one byte of two BCD digits (maximum
of 99) and "rolls over" at page 100 to 00. If your program is more than
100 pages long, then page 101 will not eject but page 102 will catch up.
This is untested and probably will remain so.
Principally, I tried to keep Z80ASM intact as much as possible. In
some places, I corrected the original code without altering the rest of
7
Z80ASM-DD 24 ---> Fixes to Z80ASM-20 09/12/87
the routine. In the label routine, I altered the order of routine and
changed only the JP addresses. The rest of the changes required the ad-
dition of new code. To make room for the new code, I moved the main
look-up table at the end of the program to higher memory, staying within
the last page, and added the new routines to the end of the program.
TESTING:
-------
I've tried to test Z80ASM thoroughly with benchmark programs and
others that I've written, however, I am sure that the original programmer
thought he (she?) did also -- at least well enough to write a bigger and
better assembler. So help me. Run the assembler on some of your succes-
sful programs and compare them. If there is any bugs, please let me
know. I'll try to fix all of the real ones.
EPILOG:
------
This was fun for me (she's crazy!!). I didn't know the insides of
assemblers before I started and now I have an appreciation for both as-
semblers in general and, particularly, the work of 'LCS' -- I learned a
lot! I suppose the ultimate irony, after all this work, would be someone
telling me that there is a more effecient, fully featured, bug-free as-
sembler readily available in the public domain!!
I have one more feature to add when I have time -- I feel lost with-
out a symbol table so I'll dump that to the listing some day. The way I
get around that now is call DDT with a null program and check out the
symbol table left in memory starting at 22A2H.
About the version number, I worked it up to 24 to keep track of my
work and, vainly enough, added my initials to easily identify this ver-
sion with the fixes from any others in RCPM land.
From the skeletons left in the code, it's become obvious that other
features were planned for Z80ASM but never implemented. Maybe I'll work
on them some day. Perhaps add a routine to allow lower case alpha en-
closed in quotes. If you have any ideas for new features or know of
other bugs, please share them with me and I'll see what I can do.
I'd like to hear from any users of this version -- tell me about
your experiences, both the good and the bad. Send E-mail to:
Diamma Dearborn
Data Tech RCPM 408-238-9621.
San Jose, CA.
8
Z80ASM-DD 24 ---> Fixes to Z80ASM-20 09/12/87
NOTES ON SYNTAX FOR Z80ASM-DD 2.4
DISCRIPTION OF Z80ASM:
---------------------
Z80ASM is a two-pass assembler. The first-pass creates the symbol table
and the second pass does the assembly. The assembler accepts as input
an <filename>.ASM source file written in ZILOG assembly language and out-
uts both an Intel formatted
<filename.HEX> object file and an assembly listing to the printer in
realtime, either of which may be disabled. This assembler does not
create any intermediate files, <filename.PRN> or <filename.SYM> files.
The symbol table is created starting at 22A2H and may be expanded up to
CCP base without harm. There is no trap for symbol tables that overwrite
CCP. The maximum number of symbolic entries is dependent on the memory
available with the system configuration and the aggregate length of each
symbol plus 4 bytes per symbol.
All program I/O is done through FDOS calls to 0005H. All read, write and
working buffers, except the symbol table, are internal to the program.
This assembler was written in 8080 assembly language probably as a boot-
strap to writing a more effecient and fully featured Z80 assembler.
INVOKING Z80ASM:
----------------
The format is:
A>Z80ASM <filename>[.LH ]
The assembler expects an input source file named <filename>.ASM. The
optional .LH extension is the (L)isting output and (H)ex file output de-
feat option mechanism. The true state of the option (defeated) is in-
voked by typing 'N' in the appropriate location, any other character
enables the function. Without the extension both Listing output and .HEX
file output functions are enabled. When the listing function is dis-
abled, only assembly line errors will be listed. For example:
<filename>.N will disable the listing function but
create a <filename>.HEX file as output.
<filename>.xN will disable the .HEX file output but
a listing is printed. Where x is any
permissible CP/M .typ char except a space
SOURCE CODE FILE LIMITATIONS:
----------------------------
Source code files may be of any length acceptable to CP/M, however, there
is a practical limit to the size of the symbol table which is not written
to a file but held in memory between 22A2H and CCP base.
1
Z80ASM-DD 24 ---> Fixes to Z80ASM-20 09/12/87
SOURCE CODE LINES:
-----------------
Source code lines may not exceed 80 characters including CR & LF and
must be terminated by LF (0AH). Most routines test for CR to exit.
LOWER/UPPER CASE TRANSLATION:
----------------------------
Presently, ALL lower case ascii characters are translated to upper case,
including strings enclosed by single quote marks.
OPCODES AND OPERANDS:
--------------------
Opcodes may NOT start in column 1. Opcodes and their operands follow the
rules established by Zilog in the Z80-Assembly Language Programming Man-
ual.
RESERVED WORDS:
--------------
Certain symbolic names are reserved as key words in the operand fields.
They are:
Register names: A, B, C, D, E, H, L, AF, BC, DE, HL, AF'
Flag Conditions: C, NC, Z, NZ, M, P, PO, PE
Using a reserved word as a smybolic reference in the operand field will
give erroneous operand values.
EXPRESSIONS:
-----------
Expressions are operand entries and may be unary (single term) or binary.
Elements of the expression are connected by the arithmetic operators +
(addition), - (subtraction) , and * (multiplication).
Expression elements may be numbers which begin with a numeric digit,
symbolic references which begin with an alpha charater (LABELS: and
EQUates), $ symbol for the current value of the reference counter and a
single ASCII character enclosed in single quote marks which equates to a
hexadecimal number. Expressions are terminated by any other characters,
usually a space or comma.
Expressions are evaluated from left to right, parentheses are not per-
mitted. Expression evaluation results are limited to 2 bytes (16 bits)
in length with a maximum unsigned value of 65,535.
NUMBERS:
-------
Numbers MUST begin with a numeric digit, leading zeroes will suffice.
Numbers may be written in hexadecimal, decimal or binary bases. Hexa-
decimal numbers must be followed immediately by the 'H' radix indicator.
Binary numbers must be followed immediately by the 'B' radix indicator.
Decimal numbers are not followed by a radix letter indicator.
2
Z80ASM-DD 24 ---> Fixes to Z80ASM-20 09/12/87
LABELS:
------
Labels MUST start in column 1. A label is a string of one or more char-
acters and must begin with an alpha character. Valid characters are A-Z,
0-9, $, period (.) and trailing colon (:). Labels are terminated by any
other character, usually a space or comma. Labels may be up to 11 char-
acters in length (excluding colons), all characters are unique. Trailing
colons are optional and ignored by the assembler i.e., LABELS: = LABELS.
Examples of valid labels are:
LABEL LABEL: LABEL$ LONG.LABEL LONGERLABEL
WARNING: at present the reserved word trap does not work.
An opcode or reserved word in an expression or starting in
column 1 will cause your program to crash! Also, the last
label stored in the symbol table will give erroneous values,
therefore, DO NOT reference the last label in the body of a
program.
PSEUDO-OPS:
----------
Pseudo-ops are instructions to the assembler and as such do not generate
object code. Psuedo-ops are summerized below:
ORG e Sets the reference counter to the value of
expression e.
EQU e Sets the value of a label to e. Can occur
only once per label.
END e Signifies the end of source code -- all code
after END is ignored. Expression e evaluates
to the program starting address for .HEX
files loaded with LOAD (e = 100H is normal)
EJECT Forces a new page in listing.
DEFS e Reserves e bytes of memory. Advances
reference counter RC = RC + e.
DEFB e Defines one byte of memory to equal value e.
DEFB '$tring' Defines n bytes of memory as the ascii
equivalent of the characters in the $tring
enclosed by single quote marks. n
equals the number of chars in the string.
DEFW e Defines two bytes of memory to be equal to
the value of e. e is stored in memory as low
byte -- high byte, ie., CRLF EQU 0D0AH...
DEFW CRLF... produces 0A, 0D in consecutive
bytes of memory.
3
Z80ASM-DD 24 ---> Fixes to Z80ASM-20 09/12/87
IBM e Defines n bytes of memory as the hex equiva-
lent of the ascii elements in the expression
e where n is the number of elements and takes
the form:
IBM c1,c2,'$tring',c3,...,cn
where values of c are the hex representation
of ascii characters without base indicator
(H) and elements are seperated by a comma.
Strings are enclosed by single quotes and
each character of a string is considred an
element. Single quotes may be included by
defining cx = 27 (H). Symbolic equivalents
are not allowed (ie., CR EQU 0DH...IBM
CR,..). e is terminated by a CR. Usage
example, a $ terminated message:
IBM 0D,0A,'MESSAGE',0D,0A,'$'
where e is an expression as defined above.
MACRO, CONDitional, EXTERNAL and GLOBAL pseudo-ops and LOGICAL
operators are not implemented in this version of Z80ASM.
COMMENT LINES:
-------------
Comment lines are defined as any string following a semicolon (;) in a
line. Comments may start in any column and are ignored by the assembler.
ASSEMBLER ERROR MESSAGES:
------------------------
Assembly error messages are one character codes which are placed in the
first column of the line containing the error in the output listing.
L Label length error -- label > 11 characters long
M Label is either a reserved word or previously defined (not
implemented in version 2.4)
O "Overflow" -- indicates that the op code as spelled was
not found in reference table.
U Undefined label in the operand field
$ Displacement range error -- range = -127 < expression <+130
- Dianna Dearborn
4