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:
shlasadd acc, accrclasadc acc, acc- Some alternative mnemonics for jumps, see
jcc binop d, imm8asmov acc, d; binop acc, imm8; mov d, accwheredis an arbitrary 8-bit operand ≠accandbinopis any binary operation ≠cmpcmp d, imm8asmov acc, d; cmp acc, imm8wheredis an arbitrary 8-bit operand ≠accbinop d, rasmov acc, d; binop acc, r; mov d, accwheredis an arbitrary 8-bit operand ≠accandbinopis any binary operation ≠cmpcmp d, rasmov acc, d; cmp acc, rwheredis an arbitrary 8-bit operand ≠accpush abaspush a; push bwith variants forab,cd,pi(little-endian in memory)pop abaspop b; pop awith variants forab,cd,pixchg xx, yyaspush xx; push yy; pop xx; pop yywith variants forab,cd,piasserteq r, imm8ascmp r, imm8; assertz(using the pseudo-instruction above ifr≠acc)asserteq r, sascmp r, s; assertz(randsdenote 8-bit operands)asserteq [imm16], imm8asmov acc, [imm16]; cmp acc, imm8; assertzasserteq [imm16], rasmov acc, [imm16]; cmp acc, r; assertzasserteq ab, imm16asasserteq a, imm16[15:8]; asserteq b, imm16[7:0], correspondingly forcdandpi. There is no such instruction forsp, because we cannot directly access the upper and lower byte ofsp.assertflags flagswhere the flags can be denoted in the styleSZVCor__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 flagsasmov acc, flags; push acc; popfwhere the flags are denoted as above.failasmov acc, 1; cmp acc, 0; assertz