Assembler
The assembler implements the full ISA and is stable. It was mainly developed by Florian Bauckholt and Nils Husung.
The assembler is based on customasm.
To run the assembler, you need to install a Rust toolchain and customasm via cargo install customasm
.
The customasm rules are contained in the isa/isa.s
file.
So if you are in the same directory, you can assemble files as follows:
customasm [-p|-o <out.bin>] isa.s [userspace.s|rom.s] <input.s> [...]
The -p
switch makes customasm print the code to stdout, by default in an annotated hex format.
You can select the format via the -f
option, see customasm --help
for the available formats.
If -p
is not given, a binary file will be generated.
By default, the name will be isa.bin
as name of the first input file is isa.s
.
Of course, you can change this using the -o
option.
userspace.s
can be used to output the code starting at address 0x2000
, where the general purpose RAM section begins.
However, the first byte in the binary will be the one located at address 0x2000
.
To write programs for the ROM, you can use rom.s
instead.
In this mode, only addresses from 0x0000
to 0x0fff
can be used (the assembler will generate an error if the code does not fit in there).
However, the file size will be 128 KiB to make minipro
(the program we use for writing to the flash chips) happy.
minipro
commandThe minipro
command we use for flashing the ROM is:
minipro -s -p SST39SF010 -w <file.bin>
Pseudo-Instructions
Besides mnemonics for the native instructions, the assembler also provides a few pseudo-instructions. In particular, these are:
shl
asadd acc, acc
rcl
asadc acc, acc
- Some alternative mnemonics for jumps, see
jcc
binop d, imm8
asmov acc, d; binop acc, imm8; mov d, acc
whered
is an arbitrary 8-bit operand ≠acc
andbinop
is any binary operation ≠cmp
cmp d, imm8
asmov acc, d; cmp acc, imm8
whered
is an arbitrary 8-bit operand ≠acc
binop d, r
asmov acc, d; binop acc, r; mov d, acc
whered
is an arbitrary 8-bit operand ≠acc
andbinop
is any binary operation ≠cmp
cmp d, r
asmov acc, d; cmp acc, r
whered
is an arbitrary 8-bit operand ≠acc
push ab
aspush a; push b
with variants forab
,cd
,pi
(little-endian in memory)pop ab
aspop b; pop a
with variants forab
,cd
,pi
xchg xx, yy
aspush xx; push yy; pop xx; pop yy
with variants forab
,cd
,pi
asserteq r, imm8
ascmp r, imm8; assertz
(using the pseudo-instruction above ifr
≠acc
)asserteq r, s
ascmp r, s; assertz
(r
ands
denote 8-bit operands)asserteq [imm16], imm8
asmov acc, [imm16]; cmp acc, imm8; assertz
asserteq [imm16], r
asmov acc, [imm16]; cmp acc, r; assertz
asserteq ab, imm16
asasserteq a, imm16[15:8]; asserteq b, imm16[7:0]
, correspondingly forcd
andpi
. There is no such instruction forsp
, because we cannot directly access the upper and lower byte ofsp
.assertflags flags
where the flags can be denoted in the styleSZVC
or__V_
._
means that the corresponding flag is unset (and not “don’t care”). The corresponding assembly code is:pushf ; 2x pushf to simply restore the flags
pushf
pop acc
cmp acc, flags
assertz
popfsetflags flags
asmov acc, flags; push acc; popf
where the flags are denoted as above.fail
asmov acc, 1; cmp acc, 0; assertz