Assisted-by: GLM 5.3 Flash
gasm-devkit
Developer tooling for GAsm, Go's built-in Plan 9 assembler.
Go ships an assembler but no tooling for it: there is no syntax highlighting,
no autocomplete, no linter, no static analyser, no formatter, no standalone
assembler and no debugger for .s files. Developers write assembly blind,
validate it by benchmark, and debug it by print statement. gasm-devkit is the
missing toolkit: a single, self-contained binary, gasm, that brings proper
developer tooling to Plan 9 assembly on amd64, arm64, riscv64 and loong64.
Features
- Front end. A hand-written lexer and an error-tolerant parser produce a
typed AST with source positions;
gasm tokensandgasm parseexpose them directly. - Formatter.
gasm fmtcanonicalises indentation, operand spacing, per-function mnemonic alignment and blank-line layout:gofmtfor assembly, operating recursively on directories the waygo fmtdoes. - Linter.
gasm lintruns 17 conservative static checks, among themundefined-label,abi-argsize(declared frame vs the// funcsignature),register-clobber(Go ABI register liveness over the control-flow graph),stack-imbalance,abi0-register-argsandunencodable-instruction. - Standalone assembler.
gasm asmencodes all four architectures without the Go toolchain and writes raw images, linkable ELF objects (with DWARF5 debug sections) or the Go toolchain's own GOOBJ format, whichgo buildconsumes in place of the toolchain's output. - Dynamic verification.
gasm verifyJIT-loads assembled functions into executable memory: smoke calls, ABI checks (sentinel registers, red-zone canary), differential fuzzing against thego tool asmbuild, and byte-for-byte ground-truth comparison of the machine code. - Debugger.
gasm debugis a source-level ptrace debugger with breakpoints (optionally conditional), hardware watchpoints, register and memory inspection, and headless script runs with label-level coverage. - Language server.
gasm lspserves completion, hover, document symbols, diagnostics, semantic-token highlighting, go-to-definition, find references, rename, formatting, inlay hints, code actions, signature help, document highlights and workspace symbol search over stdio. - Comparators and audits.
gasm diffcompares the machine code of two assembly files byte-for-byte,gasm profileshows basic-block structure,gasm audit-instructionsdiffs the encoder against the installed toolchain, andgasm scaffoldgenerates a differential test skeleton for a kernel. - Complete instruction coverage. The instruction tables are generated
from the Go toolchain's own assembler source, so the toolkit recognises
every mnemonic the real assembler accepts;
just genrefreshes them.
Architecture support
| Architecture | GOARCH | File suffix | Instructions recognised |
|---|---|---|---|
| AMD64 | amd64 |
_amd64.s |
1600 + common opcodes + traditional aliases |
| ARM64 | arm64 |
_arm64.s |
538 + common opcodes |
| RISC-V | riscv64 |
_riscv64.s |
961 + common opcodes |
| LoongArch | loong64 |
_loong64.s |
799 + common opcodes |
"Common opcodes" are the instructions shared by every architecture (RET,
JMP, NOP, CALL, TEXT, FUNCDATA, PCDATA, ...). AMD64 additionally
carries the traditional conditional-jump spellings (JZ, JNZ, JA, JC,
...) that the assembler accepts as aliases. Regenerating the tables is one
command (just gen) and requires only a Go installation; the committed output
has no runtime dependency on the toolchain.
Install
Prebuilt binaries for linux/amd64, linux/arm64, linux/riscv64 and linux/loong64 are on the releases page. From source (Go 1.27 or later):
go install sourcedock.dev/petrbalvin/gasm-devkit/cmd/gasm@latest
Or from a repository checkout, with the development version stamped:
just install-bin
Quick start
cat > hello_amd64.s <<'EOF'
#include "textflag.h"
// func add(a, b int) int
TEXT ·add(SB), NOSPLIT, $0-24
MOVQ a+0(FP), AX
ADDQ b+8(FP), AX
MOVQ AX, ret+16(FP)
RET
EOF
gasm lint hello_amd64.s # static checks
gasm asm -o hello.bin hello_amd64.s # assemble to a raw image
gasm verify --call add --args a=2,b=3 hello_amd64.s # JIT-call it with arguments
Usage
gasm fmt # reformat every .s below here, like go fmt
gasm fmt -w kernel_amd64.s # canonicalise one file in place
gasm lint *.s # static checks
gasm asm --format elf -o k.o k.s # assemble to a linkable ELF object
gasm asm --format goobj -p pkg/path -o k.o k.s # Go object, consumed by go build
gasm verify --ground-truth k.s # byte-for-byte vs go tool asm
gasm verify --fuzz k.s # differential fuzz vs the go tool asm build
gasm debug --func name k.s # interactive debugger
gasm debug --func name --script cmds.txt --timeout 30s k.s # headless run
gasm debug --func name --cover k.s # which labels did execution reach?
gasm diff a.s b.s # compare machine code byte-for-byte
gasm diff --map wideCopyAVX2=wideCopyAVX512 avx2.s avx512.s
gasm profile k.s # show basic-block structure
gasm audit-instructions # encoder vs go tool asm name diff
gasm scaffold differential k.s # generate a differential test skeleton
Run gasm --help for the command overview and gasm <command> -h for a
command's flags. docs/CLI.md is the full reference.
Editor integration
gasm lsp speaks the Language Server Protocol over standard input/output, so
any LSP-capable editor can use it: point your editor's LSP client at the
binary and associate it with .s files. Syntax highlighting is delivered as
LSP semantic tokens, so no editor-specific grammar is required. The server
infers the target architecture from the file-name suffix
(_amd64.s / _arm64.s / _riscv64.s / _loong64.s).
Development
just install # download module dependencies
just build # go vet + gofmt check, zero errors and zero warnings
just test # full suite, race detector, 80 % coverage gate
just fmt # gofmt the tree
just gen # regenerate the instruction tables from the Go toolchain
See CONTRIBUTING.md for the development workflow and docs/DEVELOPMENT.md for setup details and every recipe.
Documentation
- docs/ARCHITECTURE.md: components and data flow
- docs/CLI.md: full command reference
- docs/DEVELOPMENT.md: development setup and recipes
- docs/DECISIONS.md: deferred design decisions
- CHANGELOG.md: release history
Licence
BSD-3-Clause — see LICENSE.
Copyright © 2026 Petr Balvín