Getting Started
Installing
Add the package for the CPU you are targeting; it brings in the core packages:
dotnet add package MrKWatkins.OakAsm.Z80 # Z80
dotnet add package MrKWatkins.OakAsm.Z80N # ZX Spectrum Next
Building Assembly from C#
The Z80Assembly class has a static builder method for every instruction and directive. Build a
Source, assemble it, then write the bytes out:
using MrKWatkins.OakAsm.Ast;
using MrKWatkins.OakAsm.IO;
using MrKWatkins.OakAsm.Z80;
using static MrKWatkins.OakAsm.Z80.Z80Assembly;
var source = new Source(
ORG(0x6000),
LD(BC, "STRING"),
Label("LOOP"),
LD(A, [BC]),
CP(0),
JR(Z, "EXIT"),
RST10(), // ZX Spectrum ROM: print the character in A.
INC(BC),
JR("LOOP"),
Label("EXIT"),
RET(),
Label("STRING"),
DEFB("Hello World"),
DEFB(13, 0));
Z80Assembler.Instance.Assemble(source);
var output = new Output(source); // output.Regions has the assembled bytes and their locations.
Memory operands use collection expressions — LD(A, [BC]) is LD A, (BC) — and labels are
referenced by name, resolved at assembly time.
DEFB and DEFW take any number of values, so generated data can be passed straight through
without unpacking it — DEFB(bytes) for a byte[] or span, DEFW(words) for ushorts. Both
throw if given nothing to emit.
Parsing Assembly Text
using MrKWatkins.Ast.Position;
using MrKWatkins.OakAsm.Parsing;
using MrKWatkins.OakAsm.Z80;
var source = OakAsmParser.Parse(new TextFile("hello.asm", File.ReadAllText("hello.asm")));
Z80Assembler.Instance.Assemble(source);
if (source.ThisAndDescendentsHaveErrors)
{
// Inspect source.ThisAndDescendentsWithErrors for details.
}
Supported Directives
| Directive | Purpose |
|---|---|
ORG address |
Set the assembly location. |
EQU value |
Define a constant for the preceding label. |
DEFB value, ... |
Emit bytes or strings. DEFM is an alias, conventionally used for strings. |
DEFW value, ... |
Emit words. |
DEFS length[, fill] |
Reserve length bytes, filled with fill or zero. DS is an alias. |
ALIGN boundary |
Advance the location to the next multiple of boundary, filling with zeroes. |
INCLUDE "file.asm" |
Splice in another assembly file, relative to the including file. Available when assembling projects. |
INCBIN "file.bin" |
Place the bytes of a binary file in the output as-is, relative to the including file. Available when assembling projects. |
END [entry point] |
End of source, with an optional entry point given as an address or a label. Nothing after END is emitted. |
Expressions
Instruction and directive arguments can be expressions over numbers, labels and $, the current location:
ORG $8000
Start:
LD HL, Table + 2 * 4
LD A, 0b00001111 & Mask ; See operators below.
JR $ ; Jump to self.
Finish:
Size: EQU $ - Start
DEFW Finish - Start
Operators, highest precedence first:
| Operators | Meaning |
|---|---|
- ~ (unary) |
Negate, bitwise complement. |
* / % |
Multiply, divide, modulo. |
+ - |
Add, subtract. |
<< >> |
Bit shifts. |
& |
Bitwise AND. |
^ |
Bitwise exclusive OR. |
\| |
Bitwise OR. |
Brackets group sub-expressions, but an argument starting with an open bracket is a memory reference —
LD A, (Base + 1) reads memory, LD HL, Base + 1 is address arithmetic.
$ evaluates to the location of the containing instruction, so JR $ jumps to itself. Constant expressions for
relative jumps, e.g. JR 5, are raw displacements; expressions involving labels or $ are target addresses and
the displacement is calculated for you, with an error if the target is out of range.