asm6809(1)
asm6809(1) π
Okay bestie, welcome to the asm6809 manual. This is the 6809 cross-assembler, and she's iconic. π
π NAME π
asm6809 β 6809 cross-assembler
π¦ SYNOPSIS π¦
asm6809 [OPTION]β¦ [SOURCE-FILE]β¦
π DESCRIPTION π
asm6809 is a portable macro cross assembler targeting the Motorola 6809 and Hitachi 6309 processors. These processors are most commonly encountered in the Dragon and Tandy Colour Computer. No cap, that's the whole vibe. β¨
β¨ OPTIONS β¨
-B,--binβ output raw binary file (default)-D,--dragondosβ output DragonDOS binary file-C,--cocoβ output CoCo RS-DOS (βDECBβ) segmented binary file-S,--srecβ output Motorola SREC file-H,--hexβ output Intel hex record file-e,--exec addrβ EXEC address (for output formats that support one)-8,-9,--6809β use 6809 ISA (default)-3,--6309β use 6309 ISA (6809 with extensions)-d,--define sym[=number]β define a symbol--setdp valueβ initial value assumed for DP [undefined]-P,--max-passes nβ maximum number of passes to allow symbol values to stabilise [12]-o,--output fileβ output filename-l,--listing fileβ create listing file-E,--exports fileβ create exports table-s,--symbols fileβ create symbol table-q,--quietβ don't warn about illegal (but working) code-v,--verboseβ warn about explicitly inefficient code--helpβ show help--versionβ show program version
If more than one SOURCE-FILE is specified, they are assembled as though they were all in one file. Fr fr. π«Ά
πΈ USAGE πΈ
Text is read in and parsed, then as many passes are made over the parsed source as necessary (up to a limit), until symbols are resolved and addresses are stable. The fastest or smallest representation should always be chosen where there is ambiguity. The way she just chooses the optimal form? Obsessed. β¨
Output formats are: Raw binary, DragonDOS binary, CoCo RS-DOS (βDECBβ) binary, Motorola SREC, Intel HEX.
Additional optional output files are:
- A listing file is an annotated copy of the source file with addresses and generated code prepended to each line.
- An exports file contains a list of all macro definitions and symbols flagged for export with the
EXPORTpseudo-op. Suitable for inclusion in subsequent source files. - A symbols file contains a list of all non-local symbols. Suitable for inclusion in subsequent source files, but beware multiple definitions errors if two source files include a common set of symbols.
Home page: <https://www.6809.org.uk/asm6809/>
π¦ Differences to other assemblers π¦
Motorola syntax allows a comment to follow any operands, separated from them only by whitespace. To an extent, this assembler accepts that, but be aware that as spaces are allowed within expressions, if the comment looks like it is continuing an expression it will generate bad code (or raise an error if the result is syntactically incorrect). Example:
0000 8605 lda #5
0002 C60A ldb #5 * 2 twice first number
A strict Motorola assembler would generate bytes C6 05 for the second line, as the β* 2β would be ignored. For consistency, it is best to introduce end of line comments with a ; character. An asterisk (*) can introduce whole line comments.
An unquoted semicolon always introduces a comment. The alternate form of the 6309 instructions AIM, OIM, etc. listed in some documentation that uses a semicolon as a separator is not accepted. She said nope to that separator. π
A symbol may be forward referenced; any time a reference is unresolvable, another pass is triggered, up to some defined maximum.
In 6809 indexed addressing, the offset size will default to the fastest possible form, e.g. if the offset is an expression that happens to evaluate to zero, the no offset form will be used. Prepend << to coerce a 5 bit offset, < to coerce 8 bits or > to coerce 16 bits.
asm6809 currently has no support for OS-9 modules or multiple object linking. Periodt.
π Program syntax π
Program files are considered line by line. Each line contains up to three fields, separated by whitespace: label, instruction and arguments. An unquoted semicolon (;) indicates that the rest of the line is to be considered a comment. Whole line comments may be introduced with an asterisk (*). Motorola-style end of line comments without a ; are accepted, but see the notes about assembler differences.
Any label must appear at the very beginning of the line. If a label is omitted, whitespace must appear before the operator field. Certain pseudo-ops may affect a label's meaning, but usually labels define a symbol referring to the current position in the code (Program Counter, or PC). A label may be followed by a colon (:) character, which is ignored.
The instruction field contains either an instruction op-code (mnemonic), a pseudo-op (assembler directive), or a macro name for expansion.
Pseudo-ops allow conditional assembly and inline data, can affect code placement and symbol values and be used to include further files inline. See the section on Pseudo-ops for more information. (That's later, bestie β keep reading. π)
Arguments are a comma-separated list: either instruction operands or arguments to a pseudo-op or macro. Permitted arguments are specific to the instruction or pseudo-op, but in general they may be:
- An expression.
- A register name, with optional pre-decrement or post-increment.
- A nested list surrounded by
[and]. This is generally only used to indicate indirect indexed addressing.
In addition, any argument may be preceded by:
#, indicate immediate value.<<, force 5-bit index offset.<, force direct addressing, 8-bit value or 8-bit index offset.>, force extended addressing, 16-bit value or 16-bit index offset.
π Expressions π
Expressions are formed of:
- A decimal number.
- An octal number preceded by
@,0oor with a leading0. - A binary number preceded by
%or0b. - A hexadecimal number preceded by
$or0x. - A floating point number: decimal digits surrounding exactly one full stop (
.). - A single quote followed by any ASCII character (yielding the ASCII value of that character).
- A symbol name, local forward reference or local back reference.
- Any of the above prefixed with a unary minus (
-) or plus (+). - A string delimited either by double quotes or
/. - A combination of any of the above with arithmetic, bitwise, logical or relational operators.
- Parenthesis to specify precedence.
The assembler uses multiple passes to resolve expressions. If an expression refers to a symbol that cannot currently be resolved, an extra pass is triggered. Similarly, if a symbol is assigned a value (e.g. by an EQU pseudo-op) that differs to its value on the previous pass, another is triggered until it becomes stable.
When not directly used for their contents (e.g. by FCC), strings can be used in place of integer values. The ASCII value of each character is used to represent 8 bits of the integer result up to 32 bits. Example:
0000 CC443A ldd #"D:"
β Operators β
The following operators are available, listed in descending order of precedence (where operators share a precedence, left-to-right evaluation is performed):
- Highest precedence:
+unary plus;-unary minus;! ~logical, bitwise NOT - Next:
*multiplication;/division;%modulo - Next:
+addition;-subtraction - Next:
<<bitwise shift left;>>bitwise shift right - Next:
< <=relational operators;> >=relational operators - Next:
==relational equal;!=relational not equal - Next:
&bitwise AND - Next:
^bitwise XOR - Next:
|bitwise OR - Next:
&&logical AND - Next:
||logical OR - Lowest precedence:
?:ternary operator
Division always returns a floating point result. Other arithmetic operators return integers if both operands are integers, otherwise floating point. Bitwise operators and modulo all cast their operands to integers and return an integer. Relational and logical operators result in 0 if false, 1 if true. Integer calculations are performed using the platform's int64_t type, floating point uses double.
π Conditional assembly π
The pseudo-ops IF, ELSIF, ELSE and ENDIF guide conditional assembly. IF and ELSIF take one argument, which is evaluated as an integer. If the result is non-zero, the following code will be assembled, else it will be skipped. Undefined symbols encountered while evaluating the condition are interpreted as zero (false) rather than raising an error.
Conditional assembly pseudo-ops are permitted within macro definitions and will be evaluated at the time of expansion, therefore positional variables can be used to affect macro expansion. She's flexible like that. π
π§ Sections π§
Code can be placed into named sections with the SECTION pseudo-op. This can make breaking source into multiple input files more comfortable. Without ORG or PUT directives, sections will follow each other in memory in the order they are first defined.
Within each section, there may exist multiple spans of discontiguous data. Some output formats are built different and can actually represent that. The others (looking at you, DragonDOS π) have to combine the spans first, padding the gaps in between with zero bytes. No gaps allowed, bestie.
β¨ Local labels β¨
Local labels are local to the current section, periodt. A local label is any decimal number sitting in the label field, and unlike every other label in your life, the same local label is allowed to show up multiple times. Repeat queens. π
When it shows up as an operand, a decimal number followed by B or F means a back or forward reference β to the previous or the next occurrence of that numerical local label in the section.
In this example the 1 label appears twice, but every use of 1B reaches for the closest one when searching backwards:
0000 8E0400 scroll ldx #$0400
0003 EC8820 1 ldd 32,x
0006 ED81 std ,x++
0008 8C05E0 cmpx #$05e0
000B 25F6 blo 1B
000D CC6060 ldd #$6060
0010 ED81 1 std ,x++
0012 8C0600 cmpx #$0600
0015 25F9 blo 1B
0017 39 rts
An exclamation mark (!) in the label field is treated as a local label numbered zero. Operands of < and > are considered equivalent to 0B and 0F respectively, so they can refer to that ! local label too. This whole thing is in here for compatibility with other assemblers, iykyk. π«Ά
Now here's the plot twist: because local labels can be repeated, their position is what tells them apart. So for that to work, all file inclusions and macro expansion must occur during the first pass β that way the absolute line count at which each local label is encountered stays identical between passes. Do not skip this. Fr fr.
πΈ Macros πΈ
Kick off a macro definition by dropping a name for it in the label field and MACRO in the instruction field. Close the definition with ENDM in the instruction field. That's it, that's the whole ritual. β¨
Use a macro by putting its name in the instruction field. Any arguments you hand it become available during expansion as a positional variable.
Positional variables can be used inside strings, or pasted together to build symbol names. Either way, they must be quoted β otherwise they get passed by value, and if they don't happen to be valid symbols all on their own, you get an error. π
The positional variables are written \{1}, \{2}, β¦ \{n}. For the first nine arguments the braces are optional, so \1, \2, β¦ \9 are valid alternatives. And for compatibility with the TSC Flex assembler, another form is accepted: &{1}, &{2}, β¦ &{n}. Inside a string, the shorter &1, &2, β¦ &9 still works, but since that can get confused with bitwise AND, it's not permitted anywhere else.
Here's a silly little example showing off positional variables and symbol pasting. Consider this macro definition plus the code that uses it:
go_left equ -1
go_right equ +1
move macro
lda x_position
adda #go_\1
sta x_position
endm
do_move
move "right"
rts
x_position rmb 1
And the main code generated comes out like this:
0000 do_move
0000 move "right"
0000 B60009 lda x_position
0003 8B01 adda #go_\1
0005 B70009 sta x_position
0008 39 rts
π Pseudo-ops π
Conditional assembly
IFcondition β the lines after this only get assembled if condition evaluates to true (non-zero).ELSIFcondition β the lines after this only get assembled if every precedingIFandELSIFpseudo-op evaluated to false (zero) and condition evaluates to true (non-zero).ELSEβ the lines after this only get assembled if every precedingIFandELSIFpseudo-op evaluated to false (zero).ENDIFβ terminate anIFstatement. That's the closer, bestie. π«‘ASSERTcondition[,message] β evaluates condition and emits an error message if the result is false (zero). The optional user-supplied message gets included in the error text. Very "speak now or forever hold your peace". π
Macro definition
MACROβ start defining a macro. The macro's name shall live in the label field. Subsequent lines, all the way up to the enclosingENDMpseudo-op, will not be assembled until the macro is expanded. Macro definitions may be nested; that is, using a macro may define another macro. Inception but make it assembly. πENDMβ finish a macro definition that was started withMACRO.
Inline data
FCBvalue[,value]β¦ β Form Constant Byte. Each value is evaluated either to a number or a string. Numbers get truncated to 8 bits and stored directly as bytes. For strings, the ASCII value of each character is stored in sequential bytes. β¨
Historically, FCB handled bytes and FCC (Form Constant Character string) handled strings. asm6809 treats them as synonymous, but it's rather more strict about what counts as a string delimiter. Picky queen. π
FCCvalue[,value]β¦ β Form Constant Byte, same as above. Each value is evaluated either to a number or a string; numbers get truncated to 8 bits and stored directly as bytes; for strings the ASCII value of each character goes into sequential bytes. (See theFCBnote above about the two being synonymous and about delimiters.)FCNvalue[,value]β¦ β identical toFCC, except a terminating zero byte gets stored after the data. Included to bump up compatibility with other assemblers. π«ΆFCSvalue[,value]β¦ β likeFCC, but the last byte in each value has its top bit set. This is the format used to represent keywords in the Dragon and Tandy Colour Computer BASIC ROMs. Iconic format, honestly.FCVvalue[,value]β¦ β likeFCC, but the ASCII is translated into the values typically required for display by the MC6847 VDG as present in the Dragon and Tandy Colour Computer. Retro display slay. πFCIvalue[,value]β¦ β likeFCV, but it inverts bit 6 for inverse video. Fancy. β¨FDBvalue[,value]β¦ β Form Double Byte. Each value is evaluated to a number, truncated to 16 bits, and stored as two successive bytes, big-endian.FQBvalue[,value]β¦ β Form Quad Byte. Each value is evaluated to a number, truncated to 32 bits, and stored as four successive bytes, big-endian.FILLvalue,count β insert count bytes of value. This is effectively the same as the two-argument form ofRZBwith its arguments swapped. πRZBcount[,value] β Reserve Zeroed Bytes. Inserts a sequence of count bytes of zero, or of value if you specified one. The two-argument form is effectively the same asFILLwith its arguments swapped.ZMBcount[,value] β alternate form ofRZBrecognised for compatibility with other assemblers.BSZcount[,value] β alternate form ofRZBrecognised for compatibility with other assemblers.
Code placement & addressing
ALIGNalignment[,value]β¦ β align to memory, next alignment bytes. Pads with value. If value isn't specified, this behaves likeRMBinstead. πORGaddress β sets the Program Counter, i.e. the base address assumed for the next assembled instruction. Unless it's followed by aPUTpseudo-op, this will also be the instruction's actual address in memory. A label on the same line defines a symbol whose value is the specified address.PUTaddress β modifies the put address. The Program Counter is unaffected, so the assumed address for subsequent instructions stays the same, but the actual data will be located somewhere else. Sneaky. πPHASEaddress β modifies the Program Counter; the PUT address is unaffected. Handy for assembling code that's going to be copied into place before it executes. Heads up: subsequent uses ofORGwill maintain the same relative offset. Stays in effect until theDEPHASEpseudo-op shows up. Phases can be nested. Any label on the same line gets the value of the execution address before the new phase offset is applied.DEPHASEaddress β ends a phase section. Undoes the offset applied to addresses by the last use ofPHASE. Any label on the same line gets the value of the execution address after the previous phase offset is removed.RMBcount β Reserve Memory Bytes. The Program Counter is advanced count bytes. In some output formats this region may be padded with zeroes; in others a whole new loadable section may be created. It depends. π€·SECTIONname β switch to the named section. The Program Counter continues from the last value it had while assembling this section, or follows the previous section if this one hadn't been seen before.CODEβ switches to a section named after the pseudo-op, i.e.CODE. Recognised for compatibility with other assemblers.DATAβ switches to a section named after the pseudo-op, i.e.DATA. Recognised for compatibility with other assemblers.BSSβ switches to a section named after the pseudo-op, i.e.BSS. Recognised for compatibility with other assemblers.RAMβ switches to a section named after the pseudo-op, i.e.RAM. Recognised for compatibility with other assemblers.AUTOβ switches to a section named after the pseudo-op, i.e.AUTO. Recognised for compatibility with other assemblers.SETDPpage β sets the assumed value of the Direct Page (DP) register to page for subsequent instructions. Any non-negative page is truncated to 8 bits; or specify a negative number to disable automatic direct addressing. See the section on Direct Page addressing for more info, bestie. π
Symbols
EQUvalue β short for "equate". This must be used with a label and defines a symbol with the specified value. That can be any single valid argument β an expression, a string, whatever. β¨EXPORTname[,name]β¦ β each name β either the name of a macro or a symbol β is flagged to be exported. Exported macros and symbols get listed in the exports output file, if one was specified.SETvalue β similar toEQU: it must be used with a label and defines a symbol with the specified value. UnlikeEQU, you can useSETmultiple times to assign different values to the same symbol without any error. Glow-up friendly. π
Files
END[address] β signifies the end of input. All further lines are disregarded. Optionally specifies an EXEC address to be included in the output, where supported by the output format. An EXEC address specified on the command line will override any value specified here. Command line stays winning. πINCLUDEfilename β includes the contents of another file at this point in the assembly. The filename argument must be a string, i.e. delimited by quotes or/characters.INCLUDEBINfilename β includes the binary data from filename (which, as withINCLUDE, must be a delimited string) directly. Straight in, no filter. π¦
β¨ Direct Page addressing β¨
Okay bestie, this one is so cool, listen. π«Ά The 6809 took the whole "zero page" thing that other processors do and said let's make it a vibe. It lets you do fast accesses to whichever page you want β the one the Direct Page register (DP) is pointing at. Main character energy fr. π
But here's the tea π β an assembler cannot keep track of what your code has set that register to. It's just not in its lane. However, knowing the value is genuinely useful when you're deciding which addressing mode to use for an instruction. So:
- The
SETDPpseudo-op, or the--setdpoption, tells the assembler "hey, assumeDPis this value." - Set it to a negative number to undefine it and disable automatic use of direct addressing. And heads up β that's the default. π
π LICENCE π
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. π
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. (Yeah, the caps lock is doing a lot, but it's doing it for a reason, okay? π)
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. π
And that's the whole page, bestie!! You read an entire manpage. Iconic behavior. β¨
This one's from asm6809-2.15, dated February 2025 β go forth and assemble, you absolute legend. π¦ππ
π¦ where this page comes from
- fedora 43: asm6809 2.16-2.fc43 Β· GPL-3.0-or-later
- fedora 44: asm6809 2.16-4.fc44 Β· GPL-3.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms