Many years ago, Martin Allcorn wrote a Z80 assembler in
BBCBASIC for
RISCOS to run on his
Acorn Archimedes. These days, Martin runs his assembler
on a Raspberry Pi running RISCOS and uses it to do all the
development work for our MTX based add-ons. Although Martin
has made the assembler freely available, I don't think that
anyone else is using it, and any users of our hardware just
download compiled versions of EPROM code etc. as required.
Version Update - May 2021Martin
has rewritten the assembler in ARM assembly language and
renamed it
!A80. The new version
uses file type
080 instead of
281 so that "old" code can still
be built on the earlier version of the program. It's still a
RISCOS only program, tested on both RiscOS 4 (RiscPC) and
RiscOS 5 (Raspberry Pi). Martin adds, "there's no reason it
shouldn't work on older versions if anyone's daft enough to
try it, as I used the RiscOS 3 reference manuals when
writing it".
It builds the MTX ROMs (17k lines of
source) in about 8 seconds on a 200Mhz RiscPC. A RaspPi will
be faster, how much faster depends on the model and the
storage, Martin's model 3B finished the same build in under
4 sec. The slow bit is the writing out of the listing file,
and some SD cards are particularly slow and will hold the Pi
back, A really slow card might actually make a Pi slower
than the RiscPC despite the 3 to 5 times faster CPU!
The BASIC version took about 10x as long. The re-written
expression evaluator is MUCH better*** no +ASC"x" kludge to
insert character codes.
Martin feels that this is
much more like a "releasable" program, so has included a
License file and a help file in the distribution. (These are
accessible outside the ARCFS archive file in the Zip file
download at the bottom of this page.)
In another
improvement to the previous version, the Help file provides
some limited documentation of how to use the program.
Usage
Whilst Martin's assembler is fully functional, it does
have some "quirks" that make it a little awkward for a
novice to use, particularly as there is no documentation for
the assembler and it only runs on RISCOS. (The ARM assembler
version does now include some limited documentation as noted
above.)
In 2019, while Bill Brendling was
working to add
CFX-II emulation to his
MEMU-Pi
system, he needed to analyse some of the CFX-II code
during his debugging of MEMU-Pi. To make things easier, Bill
wrote an
assembler in Python 3 that worked with Martin's
assembler source files.
A copy of Martin's Assembler
can be downloaded
from the bottom of the page and Bill's Python based
assembler can be downloaded from
this page.
Documentation - BASIC Version - There isn't any.
ARM Assembler Version - help file included.
During the course of Bill's
discussions with Martin, a few snippets of information that
might be useful to anyone wanting to make use of Martin's
assembler or Bill's Python implementation came out. I have
included a few brief notes on this page.
Q. What is
the difference between ORG and OFFSET in your assembler? |
A. My assembler is
written in BBC BASIC and is heavily influenced by the
one in BBC BASIC. Because I'm running it on the 32 bit
Arm version of BBC BASIC I can build images greater than
64k in size. (I usually have it set to use 128k as
that's the size of most of my "stock" flash chips). To
do that the assembler keeps multiple pointers. |
|
ORG is the origin
of the code within the image equivalent of P% on the
BBC. |
OFFSET on the other
hand, is the option to assemble for a different address
like O% on the BBC. |
|
Offset assembly is heavily used when building paged ROMs
like the MTXPlus+ or the various CFX options What the
assembler does when it encounters OFFSET is calculate
the difference between the current assembly position and
the run time address and add (or subtract) them from any
future address calculations. |
|
Q. What
does OFFSET with no address mean? |
A. OFFSET on it's
own cancels the offset assembly by setting the
difference back to 0 (like aligning P% and O%). |
|
Building the SDX and CPM ROMs
is made more complicated by the references back to the
MTX ROM in the SDX extensions, and the CPM ROM having to
re-locate into RAM.
So the build script builds
the 3 basic ROMs first, so that all the BASIC/OS labels
are available to the SDX sources. The addresses could
have been hard coded as in the original source, however
the build code started from the MTXPlus+ code base and
for that the system ROMs can (and have) change so the
SDX ROM has to have access to the actual labels.
The Build also puts the ROMs in the same place within a
64k image as they would have been in the MTXPlus+. OS in
the first 8k, ASSEM next, and then BASIC in the
16-24k area, but offset to run at 8-16k. (In the MTXPlus+
build there are 7 page ROMs and 1 fixed which fills all
of the 64k space)
The CPM ROM sits in the MTXPlus+
ROM image in the 40-48k range, so the Origin for
assembly is #A000 (found in the CPMboot source file)
When running in ROM, the code will be at #2000 so
there's an offset instruction at the start of the same
file. Once CPM is running, it runs in RAM so uses a
different offset (see CPMzmon1).
The code you
pointed to in vectors, is to fill the last section in
high memory where the CPM BDOS has been patched to
expect the hardware drivers, the ORG statement tells the
assembler where to put it within the build space, since
offset assembly is already in use at that point, there's
no need for the matching OFFSET as the assembler
automatically keeps that in step, but the comment is
there in case there's issues.
The SDX ROM is
assembled into the 48-56k range, but with offsets so hat
the ROM based part is assembled for 8-16k, and the RAM
based part the occupy the correct area between the CPM
BDOS and BASIC's system variables. |
|
|
Q. How does your
assembler handle conflicting labels? Use the first
definition, the last one, something depending upon the
include nesting, or otherwise? |
A. Any inconsistent label and
the assembler will throw an error on pass 2, but only if
the run time address changes. So where you're getting
CPMtrust appearing to be at BFE7 (where it sits) and
FFE7 (where it runs), my assembler only sees the FFE7
address so there's no conflict. |
|
|
Q. What is the
significance of the ",281" at the end of the file names?
|
A. 281 is
the RiscOs file type I use for Z80 assembler source
code. The assembler creates a 2nd file to hold the build
number which increments each time a source file is sent
to the assembler. For the record I use 280 for the
file type for the Z80 binary, 180 for a Z180 binary and
181 for Z180 source. Both the Z80 and Z180 will assemble
the other assembler's files if they're included, though
the Z80 version will error if it encounters a Z180 only
opcode. |
|
|