SkillAgentSearch skills...

A09

A Morotola 6809 assembler. There are many like it, but this is mine.

Install / Use

/learn @spc476/A09
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

                      A Motorola 6809 Assembler

This is a standard, two-pass assembler that understands (as far as I can tell) most of the standard pseudo operations that other 6809 assemblers understand, plus a few others that I find handy.

NOTE: You will need to downlaod and install the following libraries to use the program:

https://github.com/spc476/CGILib
https://github.com/spc476/mc6809

Labels are restricted to 63 charaters in length, which I think is larger than most other 6809 assemblers. I also support a type of 'local' label that is easier to show than explain:

random		pshs	x,d
		ldd	#-1
.smaller_mask	cmpd	,s
		blo	.got_mask
		lsra
		rorb
		bra	.smaller_mask
.got_mask	lslb
		rolb
		orb	#1
		std	2,s
.generate	ldd	lfsr
		lsra
		rorb
		bcc	.nofeedback
		eora	#$B4
		eora	#$00
.nofeedback	std	lfsr
		anda	2,s
		andb	3,s
		cmpd	,s
		bhi	.generate
		leas	4,s
		rts

Labels that start with '.' are considered 'local' to a previous label not starting with a '.'. Internally, the assembler will translate the these labels:

.smaller_mask
.got_mask
.generate
.nofeedback

to

random.smaller_mask
random.got_mask
random.generate
random.nofeedback

The total length of a label, plus a 'local' label, must not exceed 63 chararacters, but I feel that such a feature, along with the generous limit for label length, can make for more readable code. One more example:

clear_bytes	clra
.loop		sta	,x+
		decb
		bne	.loop
		rts

clear_words	stb	,-s
		clra
		clrb
.loop		std	,x++
		dec	,s
		bne	.loop
		rts

The four labels defined are:

clear_bytes
clear_bytes.loop
clear_words
clear_words.loop

The two instances of '.loop' do not interfere, nor are considered duplicate labels, due to the internal expansion.

Expressions can be prefixed with '>' to force a 16-bit value; with '<' to force an 8-bit value, or '<<' to force a 5-bit value (useful for the index addressing mode).

foo equ $01

    lda     foo	; knows to use direct (8-bit) address
    lda     >foo	; force extended (16-bit) address
    lda     bar	; used extended, beause of forward reference
    lda     <bar	; force use of direct address
    lda     foo,x	; uses 5-bit offset because value is known 
    lda     <foo,x	; force use of 8-bit offset
    lda     >foo,x	; force use of 16-bit offset
    lda     bar,x	; uses 16-bit offset because of forward reference
    lda     <<bar,x	; force 5-bit offset
    lda     <bar,x	; force 8-bit offset

bar equ $02

And here's the generated machine code for the above code:

                   1 | foo     equ     $01
                   2 |

0000: 96 01 3 | lda foo 0002: B6 0001 4 | lda >foo 0005: B6 0002 5 | lda bar 0008: 96 02 6 | lda <bar 000A: A6 01 7 | lda foo,x 000C: A6 8801 8 | lda <foo,x 000F: A6 890001 9 | lda >foo,x 0013: A6 890002 10 | lda bar,x 0017: A6 02 11 | lda <<bar,x 0019: A6 8802 12 | lda <bar,x 13 | 14 | bar equ $02

And the warnings the assembler generated from the above code:

example.a:5: warning: W0005: address could be 8-bits, maybe use '<'?
example.a:10: warning: W0006: offset could be 5-bits, maybe use '<<'?

(The reason we can't just apply those transformations is due to speed considerations, and complexity---each such change requires another pass, and that would lead a more complex assembler.)

Numbers can be specified in decimal, octal (leading '&'), binary (leading '%') and hexadecimal (leading '$'). The use of an underscore ('_') within numbers can be used to separate groups. Some examples:

122		decimal
12_123		decimal
%10101010	binary
%10_101_110	binary
&34		octal
&23_44		octal
$FF		hexadecimal
$F_ff_3		hexadecimal

There is a special form of value for use with the ANDCC, ORCC and CWAI instructions. Instead of an immediate value, like:

ORCC	#$50	; disable interrupts
ANDCC	#$AF	; enable interrupts
CWAI	#$AF	; enable interrupts and wait
ORCC	#$01	; set carry flag
ANDCC	#$FE	; reset carry flag

you can specify a "flag set", as:

ORCC	{FI}
ANDCC	{FI}
CWAI	{FI}
ORCC	{C}
ANDCC	{C}

This form will construct the appropriate values for the instructions. The flags are:

C	carry
V	overflow
Z	zero
N	negative
I	interrupt
H	half-carry
F	fast interrupt
E	entire state

There is a special form of value for use with the PSHS/PULS/PSHU/PULU instructions. Instead of a list of registers, you can specify no registers at all:

PSHS	-
PULU	-

This generates an operand byte of 0. This can be useful if you need a 5-cycle NOP instruction.

The assembler also supports a wide range of operators. Unary operators include:

>n	Force n to be 16 bits
<n	Force n to be 8 bits
<<n	Force n to be 5 bits (signed)
-n	Negate n
~n	2s complement n
+n	n
n!	Factorial n (floating point values only)

And binary operators include (grouped by highest to lowest, left to right assiciative unless indicated otherwise):

a ** b	a to the b power (right to left associative)

a * b	a * b
a / b	a / b
a % b	a mod b

a + b	a add b
a - b	a sub b

a << b	a shift left b bits
a >> b	a shift right b bits

a & b	a bitwise and b

a ^ b	a bitwise exclusive or b

a | b	a bitwise or b

a :: b	a * 256 + b (a MSB of word, b LSB of word) (int values only)

a <> b	a not equal to b
a <  b	a less than b
a <= b	a less than or equal to b
a =  b	a equal to b
a >= b	a greater than or equal to b
a >  b	a greater than b

a && b	a logical and b

a || b	a logical or b

The list of supported pseudo operations---if label "Non-standard", it's a non-standard pesudo operation for most 6809 assemblers.

.ASSERT expr [, "explanation" ]

	(Non-standard) Assert a condition when running tests;
	otherwise ignored.  If the expression is true, nothing
	happens; if the expression is false, the test fails, a
	dianostic message is printed, and the assembly procedure
	stops.  This can appear outside of a unit test.

.ENDTST

	(Non-standard) End a unit test; ignored when not running
	tests.

.FLOAT float-expr [, float-expr ... ]

	(Non-standard) Format a floating point number; default
	format except when using the rsdos or basic formats.  This
	will format a 32-bit IEEE-754 floating point number, which
	can be used with the MC6839.  For the rsdos and basic
	formats, this will generate the Color Basic floating point
	format (40 bits).  There may be some differences with a
	value generated from Color Basic itself, but may be "close
	enough" to be useful.  The format can be changed with the
	.OPT * REAL directive.

.FLOATD float-expr [, float-expr ... ]

	(Non-standard) Format a double length floating point number
	when using IEEE-754 floats.  For the rsdos and basic
	formats, this will generate the same value as .FLOAT, but
	generate a warning.

.NOTEST

	(Non-standard) All text up to a .ENDTST directive is
	ignored.  This is an easy way to disable a test without
	removing it.

.OPT set option data...

	(Non-standard) Supply an option from within the source code
	instead of the command line.  The following options are
	always available:

		.OPT * DISABLE <warning>

			Disable the given warning (see list below).
			Note that W0002, W0014, W0015 and W0016
			cannot be disabled with this directive given
			the nature of when they happen.  W0002 can
			be disabled with the ".OPT * USES <label>"
			directive; the others mentioned above only
			happen when using the test backend.

			All warnings are enabled by default.

		.OPT * ENABLE <warning>

			Enable a given warning.  Note that upon
			program startup, all warnings are enabled by
			default.  This is typically used to
			re-enable a warning after being disabled.

		.OPT * USES <label>

			Mark a label as being used.  This is used to
			supress W0002 warnings.

		.OPT * OBJ ('TRUE' | 'FALSE')

			Enable or disable the generation of object
			code.  This option is used to define
			variables for the direct page without
			actually generating data in the output file.
			Symbols, however, are defined.

			Default value is TRUE.

		.OPT * REAL ('IEEE' | 'MSFP' | 'LBFP' )

			Generate floating point values per the
			IEEE-754 ('IEEE') format, the Microsoft
			('MSFP') floating point format, or the
			format used by Lennart Benschop's floating
			point routines.

			Default value depends upon backend.

		.OPT * CT

			Generate a total cycle count in the listing
			file.

		.OPT * CC

			Clear the total cycle count in the listing
			file.

	The following options are only used when running tests.  The
	following options can appear inside or outside a .TEST
	directive unless otherwise specified.  If specified inside a
	.TEST directive, they only take effect when the test is run.

		.OPT TEST ORG <address>

			Set the starting address for assembling test
			cases.  This directive can ONLY appear
			outside of a .TEST directive, given the
			nature of the assembler.

			Default value is $E000.

		.OPT TEST POKE <address>,<byte>

			Write the byte value to the address in the
			virtual memory for the 6809 emulator.

		.OPT TEST POKEW <address>,<word>

			Write the word (16-bit value) to the address
			in the virtual memory for the 6809 emulator.

		.OPT TEST PROT <prot>,<address>[,<end-address>]

			Enable memory permissions for the given
			address(es).  The permissions allowed are:

				r	allow reads
				w	allow writes
				x	allow execution
				t	trace execution and writes
				n	remove any protections


			The first four can be all be used; 'n' is
			used to remove any existing protections on a
			memory location.

				.OPT TEST PROT r,$400	; ro of $400
				.OPT TEST PROT rw,foo	; rw @ foo
				.OPT TEST P
View on GitHub
GitHub Stars13
CategoryDevelopment
Updated20d ago
Forks2

Languages

C

Security Score

95/100

Audited on Mar 15, 2026

No findings