Copyright (c) 1993,1994 L.C. Benschop
Parts Copyright (c) 2001-2022 Hermann Seib
Based on Lennart Benschop's C core that can be found somewhere on the 'net (last address known to me was http://koti.mbnet.fi/~atjs/mc6809/Assembler/A09.c), I built a complete Macro Assembler that is functionally better than the TSC Flex9 Assembler (no wonder, I got multimegabytes to play with, whereas this excellent piece of software works within 50K or so!). It can deliver binary, Intel Hex, Motorola S1, and Flex9 binary output files, plus Flex9 RELASMB-compatible relocatable object modules.
I taylored the original to my taste by working through the source code; since A09 has reached a level of complexity that doesn't really lend itself to following the "Use the Source, Luke!" principle if you just want to hack a little 6809 assembly program, I've added this documentation. Have fun!
Hermann Seib, 2022
a09 [-{b|r|s|x|f}[filename]]|[-c] [-l[filename]] [-ooption]* [-dsym=value]* sourcefile*
- -c
- suppresses code output (corresponds to ASMB's B command line option)
- -u
- shorthand notation for the UEX option (see below)
- -bfilename (default output mode)
- create a binary output file
if no file name is given, the extension .bin is used (.b on Unix) - -rfilename
- create a Flex9 RELASMB-compatible output file name
if no file name is given, the extension .rel is used - Attention: this file format is undocumented; my solution has been derived from some bits of information gathered on the Flex User Group mailing list and a bit of playing with the original. In my tests, the output was identical to RELASMB's; nevertheless, A09 might create modules that are incompatible with the original under circumstances that I don't know or haven't tested.
- -sfilename
- create a Motorola S-record output file name
if no file name is given, the extension .s09 is used - -xfilename
- create an Intel hex output file name
if no file name is given, the extension .hex is used - -ffilename
- create Flex9 ASMB-compatible output file
if no file name is given, the extension .bin is used - -lfilename
- create a list file (default no listing)
if no file name is given, the extension .lst is used - -dsym[=value]
- define a symbol (see TEXT directive below)
(roughly corresponds to ASMB's command line parameters 1-3) - -oopt
- defines an option (see below)
- sourcefile
- the assembler source file(s) to be processed.
At least one source file must be given; the first one also defines the default output and listing file names.
Over the years, A09 has learned quite a lot, and it can handle source files / list files in various formats. To allow their selection, I have expanded the scope of the OPT directive (see the FLEX9 Assembler Manual that can be found in the Documentation section on www.flexusergroup.com for details). Here's the list of additional options available in A09 (* denotes the default value for a mutually exclusive set):
SYM * | print a symbol table |
NOS | suppress symbol table printing (corresponds to ASMB's S command line option) |
MUL * | print multiple object code lines |
NMU | suppress printing of multiple object code lines (corresponds to ASMB's G command line option) |
LP1 | print a Pass 1 listing |
NO1 * | print Pass 2 listing only |
DAT * | print current date on formatted pages |
NOD | do not print the current date (corresponds to ASMB's D command line option) |
NUM | print line numbers (corresponds to ASMB's N command line option) |
NON * | do not print line numbers |
INV | print invisible lines |
NOI * | do not print invisible lines |
TSC | strict TSC Assembler compatibility |
NOT * | accept source code in a much more relaxed format |
WAR * | print warnings |
NOW | only print errors, suppress warnings (corresponds to ASMB's W command line option) |
CLL * | check line length (see the SETLI directive on that) |
NCL | do not check line length |
LFN | print long file names; on Win32 systems, this causes the file names displayed in warning and error messages to contain the full path name of the corresponding source file. |
NLF * | do not print long file names |
LLL * | list library file lines |
NLL | suppress listing of library file lines |
GAS | accept Gnu AS-compatible source code
This isn't fully implemented yet. At the moment, the only significant difference is that A09 accepts constants in the form 0xXXXX (hex), 0bXXXX (binary), 0NNN (octal) in addition to the "standard" $,%, or @ notation. |
NOG * | don't accept Gnu AS-compatible source code |
REL * | print the relocation table if in Relocating Assembler mode |
NOR | suppress printing of the relocation table |
M68|M09 * | both forms accept Motorola 6809 mnemonics |
H63|H09 | accept Hitachi 6309 mnemonics (still slightly experimental) |
M00|M02|M08 | accept Motorola 6800 mnemonics |
M01|M03 | accept Motorola 6801 mnemonics |
H01|H03 | accept Hitachi 6301 mnemonics (slightly experimental) |
H11 | accept Motorola 68HC11 mnemonics (very experimental) |
TXT | print the text table if text symbols are defined (see TEXT directive) |
NTX * | do not print the text table |
LPA | print listing in f9dasm patch format
This option makes it easier to create complex patches to be embedded in images processed by f9dasm |
NLP * | don't print listing in f9dasm patch format |
DLM | define label on macro expansion; see Issue #1 for details. |
NDL * | do not define labels on macro expansion |
RED | allow redefinition of EQU statements to code/data labels if the value stays the same |
NRD * | do not allow redefinition of EQU statements to code/data labels |
FBG * | fill gaps with the defined fill character in binary files |
NFB | do not fill gaps with the defined fill character in binary files Note: when used, A09 does not go back in the output file any more, so constructions like ORG $0100 (some code) ORG $0300 (some code) ORG $0200 (some code) result in the code at $0200 to be at the end of the binary file. |
UEX | automatically convert all undefined labels to external references if Flex9 RELASMB output is generated. This roughly corresponds to Flex9 RELASMB's U option. Setting this option is silently ignored in any other output mode. |
NUE * | undefined labels are undefined labels and thus produce errors |
Each of the above options has a corresponding text symbol that is set to 0 or 1, corresponding to the state of the option. This allows for conditional assembly, for example:
IF &H63 LDW Data SUBW #12 STW Data ELSE PSHS D LDD Data SUBD #12 STD Data PULS D ENDIF
A09 handles the full set of directives available in the FLEX9 ASMB and RELASMB programs (see the excellent Documentation section on www.flexusergroup.com for the manuals of these programs). Apart from these, it knows the following directives:
[label] BIN filename or [label] BINARY filename | loads the binary contents of the file given in filename at the current position | ||||||||
EXTERN label | is implemented as an alias to the EXT directive (see RELASMB documentation) | ||||||||
FILL value,bytecount | writes the 8-bit value value into bytecount consecutive memory locations
Note: if bytecount exceeds 255 and OPT MUL (see above) is set, only the first 255 bytes are shown in the listing. |
||||||||
IFD, IFND symbol[,skipcount] | assembles the block up to the next ELSE or ENDIF
directive if the symbol is (not) defined.
Attention: this directive is a little bit dangerous - if the symbol is defined after the IF(N)D directive, phasing errors can occur! |
||||||||
PHASE addr DEPHASE | tells the assembler that the following code shall be executed at
the specified address. This "shifting" is switched off by the instruction
DEPHASE.
This can be useful for generation of EPROM contents which contain overlayed code banks where code has to be stored at an address in the EPROM (governed by ORG), but is executed at a different address (governed by PHASE). |
||||||||
REP, REPEAT count | are implemented as aliases to the RPT directive (see ASMB documentation) | ||||||||
RZB, BSZ, ZMB nnn | works like the RMB directive (see ASMB documentation), but
it doesn't only reserve memory, but also zeroes the reserved bytes
Note: if nnn exceeds 255 and OPT MUL (see above) is set, only the first 255 bytes are shown in the listing. |
||||||||
SETLI nnn | sets the line length for listings (see the CLL option above); nnn is the number of columns that can be printed in a line (40-2000). If the NCL option is selected, A09 ignores the line width (default is 80). | ||||||||
SETPG nnn | sets the page length for paginated listings (see the PAG option in the ASMB documentation); nnn is the number of lines that fit on a page (10-1000, default is 66). | ||||||||
SYMLEN nnn | sets the maximum number of significant symbol characters; nnn is the number (6-32). For implications, see Symbols below. | ||||||||
label TEXT text | this corresponds to the -dsym[=value] command line
option (see above).The FLEX9 ASMB and RELASMB programs can accept up to 3
replacement strings from the command line; these can be used in the source
file as "dummy parameters" &A, &B, and &C (see section "COMMAND LINE
PARAMETERS" in the ASMB manual on page 50).
A09 can do more than that. The -d command line option and the
TEXT directive (which can, for example be given in a library file) allow
the definition of any number of text replacements (well... not really "any",
but 4000 should be no problem :-) which can then be used in the assembler
source as &label.
In addition to all options (see above), the following constants are predefined:
|
||||||||
TITLE text | is implemented as an alias to the NAM, TTL directive (see ASMB documentation) |
The symbol table produced by A09 is a bit more verbose than the original. For each symbol, it lists the symbol name, type, and value. The following symbol types can occur:
00 | constant value (from EQU) |
01 | variable value (from SET) |
02 | address within module (LABEL) |
03 | variable containing address |
04 | external label |
05 | variable containing external address |
06 | unresolved address |
07 | variable containing unresolved address |
08 | public label |
09 | macro definition |
10 | unresolved public label |
11 | parameter name |
13 | empty; should never occur |
14 | REG directive |
15 | TEXT directive (value is the index into the text table; if you want to see the last used replacement text for this label, set the TXT option) |
18 | Common data block name (value is the length of the common data block in this case) |
20 | Common data RMB label (value is the offset in the common data block) |
34 | local label (multiple definitions are sorted based on their address) |
38 | unresolved local label |
The Relocation Table is something which doesn't exist in the original. When in Relocating mode, A09 creates this table to show where a relocation is to be applied. For each entry, A09 lists the symbol name, type, and the relocation address. There can be a '-' prepended to the symbol name to indicate that the symbol is to be subtracted from the value at the relocation address (normally, the symbol is added). The relocation table uses the same set of types as the symbol table.
My version of A09 aims to reproduce the behaviour of the Flex9 ASMB and RELASMB products. As of now, it reproduces about 99% of the originals' functionality, and surpasses them in some areas. Some things still work slightly different or aren't implemented, however.
In ASMB and RELASMB, ! denotes a "logical NOT operator"; "logical" in this context means that each bit is inverted. A09's original core came with a slightly different syntax for that, which obviously has its roots in the "C" language the assembler is written in; there, ! denotes a logical NOT (meaning that everything that's not 0 results in 0, and zero results in 1) and ~ denotes a binary inversion, which corresponds to the ! in TSC's assemblers. I decided to keep A09's syntax, as it is more versatile - so ! has a slightly different meaning in A09 than in ASMB/RELASMB.
A09 normally handles symbols with up to 32 significant characters. This is far more than the 6 (ASMB) or 8 (RELASMB) places in the predecessors and normally quite convenient, but it can cause problems when
-
dealing with old sources that rely on the old maximum to work
-
creating RELASMB-compatible relocatable modules
When creating RELASMB-compatible relocatable modules, the number of significant places is automatically reduced to 8. To resolve issues with old sources, the SYMLEN directive has been added in V1.10 (see above). The symbol table always shows the symbols reduced to the number of significant places, since that's how they are treated internally.
This nice feature of RELASMB has been added to A09, too. Due to the completely different implementation, and since A09 doesn't have to work in the extremely limited address space available to a 6809, A09 isn't restricted to 100 local labels; you can define as many local labels as you want to. The only restriction is that the length of the all-numeric symbol must be less than the number of significant symbol characters (see above) so that the B and F character can be appended in references to the local label.
When in Relocating Assembler mode, you can define external labels (i.e., labels that refer to a location in another module, that are resolved by the Linker/Loader at a later time). These labels can be used in expressions, but in a more restricted way than in RELASMB, due to the way the parser works. If there is a mixture of relocatable and external elements in the expression, the relocatable elements have to be in pairs so that they effectively cancel each other's effect, just like in the original - but, additionally, the external label has to be either the last element in the expression or the paired relocatable elements have to be parenthesized. As an example,
rel1-rel2+ext1-rel2+rel1
would be flagged as an error while
rel1-rel2-rel2+rel1+ext1 (rel1-rel2)+ext1-(rel2-rel1)
would work.
The command line switch that instructs RELASMB to treat all undefined labels as external labels isn't implemented.
RELASMB's Fix Mode is not implemented. While that may be a nifty feature, it can easily be replaced by a combination of TEXT and IF directives, which offer a better control over what gets assembled and what doesn't.
In RELASMB, nested macro definitions are allowed; in A09, they are not. Nested macro calls, however, are possible; A09 allows up to 31 levels of macro call nesting.
Like in RELASMB, macros can be used to redefine mnemonics, but with a little twist that is either missing in the original or undocumented: if the need arises to use the original mnemonic in certain places, it can be prefixed with a backslash (\); in this case, A09 doesn't check for macros but uses the original mnemonic. Prefixing a macro name that doesn't overload a mnemonic with \ leads to an error.