docs: add the Plan 9 assembly case and real-use note to the README
Test / test (push) Successful in 2m6s
Test / test (push) Successful in 2m6s
This commit is contained in:
@@ -40,6 +40,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
states the commit trailer form, the one-logical-change rule and the
|
states the commit trailer form, the one-logical-change rule and the
|
||||||
licence header rule. The repository's own assembly (the `verify`
|
licence header rule. The repository's own assembly (the `verify`
|
||||||
trampolines and the test kernels) is in `gasm fmt` canonical form.
|
trampolines and the test kernels) is in `gasm fmt` canonical form.
|
||||||
|
- **The README states the project's purpose and status.** It opens with
|
||||||
|
a warning that the tool is an experiment under active development,
|
||||||
|
version 0.x.x, free to change without warning, with 1.0.0 far off,
|
||||||
|
and already in active use on real assembly work. It describes both
|
||||||
|
goals (tooling for Plan 9 assembly, and Plan 9 assembly outside the
|
||||||
|
Go toolchain), argues the case for the syntax in a new Why Plan 9
|
||||||
|
assembly section, and carries a Direction section: extended
|
||||||
|
instruction support, full GOOBJ and ELF compilation, Linux and
|
||||||
|
FreeBSD, and the four architectures.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,63 @@
|
|||||||
# gasm-devkit
|
# Plan 9 assembly tooling, inside and outside Go
|
||||||
|
|
||||||
Developer tooling for **GAsm**, Go's built-in Plan 9 assembler.
|
> **Warning: this is an experiment.** gasm-devkit is under active
|
||||||
|
> development and is not stable. The version is 0.x.x: commands, flags,
|
||||||
|
> output formats and behaviour can change without warning at any time.
|
||||||
|
> A 1.0.0 release is light years away. Nothing in this document is a
|
||||||
|
> stability promise. For all of that, this is not a paper project: gasm
|
||||||
|
> is already in active use and is tested on real assembly work.
|
||||||
|
|
||||||
Go ships an assembler but no tooling for it: there is no syntax highlighting,
|
**GAsm** is Go's Plan 9 assembler, and Go ships it without tooling:
|
||||||
no autocomplete, no linter, no static analyser, no formatter, no standalone
|
there is no formatter, no linter, no static analyser, no standalone
|
||||||
assembler and no debugger for `.s` files. Developers write assembly blind,
|
assembler and no debugger for `.s` files. Developers write assembly
|
||||||
validate it by benchmark, and debug it by print statement. gasm-devkit is the
|
blind, validate it by benchmark, and debug it by print statement.
|
||||||
missing toolkit: a single, self-contained binary, `gasm`, that brings proper
|
gasm-devkit is the missing toolkit: a single, self-contained binary,
|
||||||
developer tooling to Plan 9 assembly on amd64, arm64, riscv64 and loong64.
|
`gasm`, that serves both purposes.
|
||||||
|
|
||||||
|
- **Help develop Plan 9 assembly.** Formatting, linting, disassembly,
|
||||||
|
dynamic verification, a source-level debugger and a language server,
|
||||||
|
for `.s` files in Go programs.
|
||||||
|
- **Use Plan 9 assembly outside the Go toolchain.** `gasm asm` encodes
|
||||||
|
on its own, with no Go installation in the loop, and writes raw
|
||||||
|
images, linkable ELF objects with DWARF5 debug sections, or the Go
|
||||||
|
toolchain's own GOOBJ format, which `go build` consumes in place of
|
||||||
|
the toolchain's output.
|
||||||
|
|
||||||
|
## Why Plan 9 assembly
|
||||||
|
|
||||||
|
Plan 9 assembly is the quiet triumph of the field. One syntax across
|
||||||
|
every architecture Go builds for: the same source-first operand order,
|
||||||
|
the same four pseudo-registers, the same frame convention, whether the
|
||||||
|
target is x86, ARM, RISC-V or LoongArch. Learn it once and you can
|
||||||
|
read a kernel on any of them.
|
||||||
|
|
||||||
|
Compare the alternatives. Intel syntax and AT&T syntax disagree on the
|
||||||
|
one question every instruction answers, which operand is the source
|
||||||
|
and which is the destination, so half the world writes it one way,
|
||||||
|
half the other, and every assembly programmer carries both in their
|
||||||
|
head forever. GNU as settles the argument with directives that switch
|
||||||
|
dialects mid-file (`.intel_syntax noprefix`), a percent sign on every
|
||||||
|
register and a dollar on every immediate: punctuation that carries
|
||||||
|
nothing the operand order did not already say. And the x86 family
|
||||||
|
fragments again underneath: NASM is not MASM is not GAS, each with its
|
||||||
|
own directive zoo and macro language, so every project picks a dialect
|
||||||
|
and every reader learns a different one by accident.
|
||||||
|
|
||||||
|
Plan 9 assembly has none of it. Registers are bare names. Memory is
|
||||||
|
one notation, `offset(base)`, extended by an index and a scale when
|
||||||
|
the instruction needs it. Arguments arrive named and offset-checked:
|
||||||
|
`x+0(FP)` is the argument x, on every architecture, and `go vet`
|
||||||
|
polices the offsets against the Go prototype.
|
||||||
|
|
||||||
|
```text
|
||||||
|
AT&T (GNU as): movq %rax, -16(%rbp)
|
||||||
|
Plan 9 (Go): MOVQ AX, total-16(SP)
|
||||||
|
```
|
||||||
|
|
||||||
|
The same lines, but only one of them tells you what the number is for.
|
||||||
|
The syntax is uppercase, regular and boring, which is the highest
|
||||||
|
compliment a language for machine code can earn. gasm-devkit exists
|
||||||
|
to give that syntax the tooling it deserves.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -47,12 +97,11 @@ developer tooling to Plan 9 assembly on amd64, arm64, riscv64 and loong64.
|
|||||||
assembly files byte-for-byte, `gasm profile` shows basic-block structure,
|
assembly files byte-for-byte, `gasm profile` shows basic-block structure,
|
||||||
`gasm audit-instructions` diffs the encoder against the installed toolchain,
|
`gasm audit-instructions` diffs the encoder against the installed toolchain,
|
||||||
and `gasm scaffold` generates a differential test skeleton for a kernel.
|
and `gasm scaffold` generates 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 gen` refreshes them.
|
|
||||||
|
|
||||||
### Architecture support
|
### Architecture support
|
||||||
|
|
||||||
|
Four architectures, the four that matter in practice:
|
||||||
|
|
||||||
| Architecture | GOARCH | File suffix | Instructions recognised |
|
| Architecture | GOARCH | File suffix | Instructions recognised |
|
||||||
|--------------|-------------|--------------|---------------------------------------------|
|
|--------------|-------------|--------------|---------------------------------------------|
|
||||||
| AMD64 | `amd64` | `_amd64.s` | 1600 + common opcodes + traditional aliases |
|
| AMD64 | `amd64` | `_amd64.s` | 1600 + common opcodes + traditional aliases |
|
||||||
@@ -63,9 +112,38 @@ developer tooling to Plan 9 assembly on amd64, arm64, riscv64 and loong64.
|
|||||||
"Common opcodes" are the instructions shared by every architecture (`RET`,
|
"Common opcodes" are the instructions shared by every architecture (`RET`,
|
||||||
`JMP`, `NOP`, `CALL`, `TEXT`, `FUNCDATA`, `PCDATA`, ...). AMD64 additionally
|
`JMP`, `NOP`, `CALL`, `TEXT`, `FUNCDATA`, `PCDATA`, ...). AMD64 additionally
|
||||||
carries the traditional conditional-jump spellings (`JZ`, `JNZ`, `JA`, `JC`,
|
carries the traditional conditional-jump spellings (`JZ`, `JNZ`, `JA`, `JC`,
|
||||||
...) that the assembler accepts as aliases. Regenerating the tables is one
|
...) that the assembler accepts as aliases. The tables are generated from
|
||||||
command (`just gen`) and requires only a Go installation; the committed output
|
the Go toolchain's own assembler source (`just gen` refreshes them), so
|
||||||
has no runtime dependency on the toolchain.
|
every mnemonic the real assembler accepts is recognised; what the encoder
|
||||||
|
can emit today is narrower, and a recognised but unencodable instruction is
|
||||||
|
reported as an explicit error, never as a wrong byte.
|
||||||
|
|
||||||
|
## Direction
|
||||||
|
|
||||||
|
The plan, in the order it is being worked:
|
||||||
|
|
||||||
|
- **Extended instruction support.** Two layers. First, encoding
|
||||||
|
coverage for every mnemonic the Go toolchain itself accepts, closed in
|
||||||
|
order of how often real code needs each instruction;
|
||||||
|
`gasm audit-instructions` measures the gap. Second, the larger work:
|
||||||
|
an extended instruction set the toolchain does not know at all. The
|
||||||
|
toolchain-derived tables stay generated and untouched; only the
|
||||||
|
extended instructions are hand-maintained, with their own spellings
|
||||||
|
and encoders, verified by execution on real hardware because the
|
||||||
|
toolchain offers no ground truth to compare against. The gaps exist
|
||||||
|
on every architecture, amd64 included.
|
||||||
|
- **Full GOOBJ and ELF compilation.** The destination is a complete,
|
||||||
|
standalone compilation path: linkable ELF objects for consumers outside
|
||||||
|
Go, and GOOBJ objects that `go build` links directly. Through GOOBJ, a
|
||||||
|
Go program will be able to use machine instructions that the Go
|
||||||
|
toolchain itself does not support; through ELF, Plan 9 assembly becomes
|
||||||
|
usable outside Go entirely.
|
||||||
|
- **Platforms: Linux and FreeBSD.** Linux is supported today on all four
|
||||||
|
architectures and is where the binary builds. FreeBSD follows: the
|
||||||
|
JIT's executable-memory mapping and the ptrace debugger layer are the
|
||||||
|
two pieces of porting work. Other unix systems may follow those two.
|
||||||
|
- **Four architectures, no more.** amd64, arm64, riscv64 and loong64.
|
||||||
|
No others are planned.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user