A Game Boy assembler and disassembler provided as a standalone Lua
module. The syntax is strict and the command language is minimal; in
particular, there are no macros and there are no global labels,
although global labels may be implemented on top of lgbtasm using
defs.
lgbtasm is known to work with Lua 5.1 and LuaJIT. Other Lua versions will probably need minimal adaptation. All code examples provided here assume a LuaJIT interpreter in order to embed hexadecimal values in string literals.
lgbtasm is used in the original Oracles Randomizer, as well as in some of my ROM hacks.
Downloads: single file (lua, 28K), archive (zip, 12K)
This module uses bgb/no$gmb syntax and enforces a strict style: numbers are
undecorated (no $, etc.) and hexadecimal, a, is required in mnemonics
that feature it, spaces do not appear after ,s, parens are used for
"dereferencing" memory, and all keywords are lower-case. User-defined
symbols such as labels are case-sensitive. A label and instruction cannot
appear on the same line.
The characters in ;*# all begin inline comments, although instruction
delimiter status overrides comment character status in the compile()
function.
"Local" labels (the only kind) start with a . and can be referenced by
relative jumps. Decompilation automatically generates labels for relative
jump destinations.
compile(block, opts)Parses a series of instructions and returns the equivalent machine code as a
byte string. Generates an error if an instruction does not match any
mnemonic, or if an invalid argument is given to an instruction. The optional
opts table can have the fields:
delims, a list (string) of characters that separate instructions in the
input (default '\n').defs, a table of string -> number mappings as if constructed by a series
of define commands. Additional defines in the input block will add to
the table.> lgbtasm = require 'lgbtasm'
> return lgbtasm.compile('cp b; ret', {delims = ';'}) == '\xb8\xc9'
true
> return lgbtasm.compile('ld (x),a', {defs = {x = 0xc6c5}}) == '\xea\xc5\xc6'
true
decompile(block, opts)Converts a string of machine code into an asm string. Generates an error if
an opcode is invalid, or if not enough bytes remain in the string to satisfy
an instruction's argument. The optional opts table can have the fields:
delim, a sequence of characters that separates instructions in the
output (default '\n').defs, a table of string -> number mappings as if constructed by a series
of define commands. 16-bit values that unambiguously match an entry will
use the corresponding symbol.> lgbtasm = require 'lgbtasm'
> return lgbtasm.decompile('\xb8\xc9', {delim = '; '})
cp b; ret
> return lgbtasm.decompile('\xfa\xc5\xc6', {defs = {x = 0xc6c5}})
ld a,(x)
db d8{,d8}Creates a sequence of literal bytes.
> lgbtasm = require 'lgbtasm'
> return lgbtasm.compile('db 01,02,03') == '\x01\x02\x03'
true
dw d16{,d16}Creates a sequence of little-endian words.
> lgbtasm = require 'lgbtasm'
> return lgbtasm.compile('dw 0201,0403') == '\x01\x02\x03\x04'
true
define symbol,valueAssociates a symbol with a constant numeric value. Redefining a symbol is not an error.
> lgbtasm = require 'lgbtasm'
> return lgbtasm.compile('define x,01; ld a,x', {delims = ';'}) == '\x3e\x01'
true