An extensible tracing disassembler for classic CPUs, version 4.1.0.
From Ancient Greek δασμός (dasmós, "division"), from δαίω (daíō, "to divide, share").
Dasmos helps turn binary images, such as ROM dumps, cartridge contents, or captured snapshots of memory, into readable, annotated assembly source. Starting from one or more entry points, the tracing core follows reachable code paths to classify which bytes are instructions and which are data, then renders the result via a chosen assembler-syntax back-end (such as beebasm or 64tass) or as structured JSON for downstream tooling.
You drive Dasmos either as a one-shot CLI command or more usually via a Python driver script that accretes labels, comments, data classifications, subroutine banners, and cross-references as you grow your understanding of the code; re-running the script regenerates the listing. CPUs, assembler-syntax back-ends, and target environments all ship as composable plug-ins, so adding support for an instruction set architecture or a new assembler dialect is a self-contained extension, without needing to modify the core code.
Install
The
uvanduvxcommands shown below come from Astral's uv. If you don't have it yet, see the uv installation guide — one-line installers are available for macOS, Linux, and Windows.
For one-shot CLI use, no install needed — uvx fetches and runs in
a transient environment:
uvx dasmos disassemble myrom.bin --load-addr '&8000'
To add dasmos to a project (required for driver scripts that
import dasmos):
uv add dasmos
Or with pip:
pip install dasmos
Programmatic API
Every CLI capability is also reachable through the package. The typical driver-script flow is: pick a CPU plug-in, load a binary, register entry points / labels / classifications / annotations, disassemble, then render via a renderer plug-in.
from dasmos import Disassembler, Align
d = Disassembler.create(cpu="6502")
d.load("rom.bin", 0x8000)
d.entry(0x8000, name="start")
d.label(0x8006, "show", description="Display routine")
d.comment(0x8000, "Entry point.")
d.comment(0x8000, "magic", align=Align.INLINE)
ir = d.disassemble()
print(str(ir.render("beebasm")))
That produces beebasm-assemblable source. Re-assembling it via the
beebasm binary yields a binary byte-identical to the input.
CLI
$ dasmos --help
Usage: dasmos [OPTIONS] COMMAND [ARGS]...
An extensible tracing disassembler.
Options:
--version Show the version and exit.
--help Show this message and exit.
Commands:
describe-cpu Describe a specific CPU plug-in.
describe-environment Describe a specific environment plug-in.
describe-renderer Describe a specific renderer plug-in.
disassemble Disassemble ROM and write the rendered output.
init Scaffold a starter dasmos driver at DRIVER_PATH.
list-cpus List the available CPU plug-ins.
list-environments List the available environment plug-ins.
list-renderers List the available renderer plug-ins.
The CLI commands inherit a uniform --as display | tsv | json story
(plus --report, --header, --detailed) from
asyoulikeit, so any
command's structured output drives downstream tooling cleanly.
Discovering plug-ins
Two namespaces are populated by the bundled extensions; third-party packages register additional entries the same way.
$ dasmos list-cpus
CPUs registered under 'dasmos.cpu'
┏━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Name ┃ Description ┃
┡━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 6502 │ The classic NMOS 6502. │
│ 65C02 │ The CMOS 65C02 — 8 extra mnemonics on top of the 6502. │
└───────┴────────────────────────────────────────────────────────┘
$ dasmos list-renderers
Renderers registered under 'dasmos.renderer'
┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Name ┃ Description ┃
┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 64tass │ 64tass-syntax renderer. │
│ beebasm │ Beebasm-syntax renderer. │
│ json │ JSON structured-output renderer. │
└─────────┴──────────────────────────────────┘
$ dasmos list-environments
Environments registered under 'dasmos.environment'
┏━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Name ┃ Description ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ acorn_fdc_1770 │ Acorn WD1770 floppy-disc-controller Environment. │
│ acorn_fdc_8271 │ Acorn 8271 floppy-disc-controller Environment. │
│ acorn_master_hardware │ Acorn BBC Master hardware-register Environment. │
│ acorn_model_b_hardware │ Acorn BBC Model B / B+ hardware-register │
│ │ Environment. │
│ acorn_mos │ Acorn MOS environment. │
│ acorn_sideways_rom │ Acorn sideways ROM environment. │
│ bbc_basic_6502 │ Registers BBC BASIC (6502) language-specific data │
│ │ types. │
└────────────────────────┴─────────────────────────────────────────────────────┘
Environments layer onto a disassembler additively — a driver can
activate any number of them, in either the constructor's
environments=[…] kwarg or via repeated
d.use_environment(…) calls.
describe-cpu (and the matching describe-renderer) shows the full
docstring of a single plug-in:
$ dasmos describe-cpu 6502
6502: The classic NMOS 6502.
16-bit address space; the 56 documented mnemonics across 13
addressing modes; 151 documented opcodes (undocumented opcodes
deliberately omitted).
$ dasmos list-cpus --help
Usage: dasmos list-cpus [OPTIONS]
List the available CPU plug-ins.
Produces reports:
cpus Registered CPU (processor) plug-ins with one-line descriptions.
Options:
Report Output Options:
--no-reports Suppress all report output. The handler still runs
(useful for action commands whose reports are
incidental); only rendering is skipped. Mutually
exclusive with --report and --all-reports.
--all-reports Render every report the handler returns,
regardless of the command's default_reports.
Useful for commands whose default is a subset (or
silent) but where you want the full picture this
time. Mutually exclusive with --report and --no-
reports.
--report [cpus] Report name(s) to display (can be specified
multiple times). Shows all if omitted. Valid
values: cpus.
--header / --no-header Include column headers in output. Overrides each
report's default. Format-specific: TSV prefixes
first cell with '#', display omits
headers/title/caption, JSON ignores this flag.
--detailed / --essential Include detailed columns or only essential
columns. Auto-detects based on output format if
not specified.
--as [display|json|tsv] Output format for tabular data. Defaults to
'display' for terminals, 'tsv' for pipes.
--help Show this message and exit.
Testing
pytest -v runs the suite. Tests marked @pytest.mark.beebasm
auto-skip when beebasm isn't on PATH; the rest run anywhere
Python and uv are installed. CI exercises the full matrix
(ubuntu/macos/windows × earliest+latest declared Python) against
the installed wheel, not the source tree, so packaging regressions
(missing entry points, omitted py.typed markers, unshipped
sub-packages) fail loud.
Layout
src/dasmos/ the package
src/dasmos/cli.py Click entry point + asyoulikeit reports
src/dasmos/disassembler.py Disassembler (driver-script API)
src/dasmos/core/ Memory / labels / moves / classifications
src/dasmos/cpu.py Cpu base + Opcode shape
src/dasmos/renderer.py Renderer base
src/dasmos/ext/cpus/ Bundled CPU plug-ins (cpu6502, cpu65c02)
src/dasmos/ext/renderers/ Bundled renderer plug-ins (beebasm, 64tass)
src/dasmos/hooks.py Subroutine hooks (stringhi_hook, …)
scripts/py8dis2dasmos.py py8dis → dasmos AST porter
scripts/generate_readme.py This README's generator
docs/design/ Architecture decisions & sweep memos
tests/ Unit + round-trip + py8dis-parity tests
tests/fixtures/ Vendored ROM + driver + reference output
Related projects
- py8dis (fork) — the predecessor Dasmos is replacing.
Driver scripts written against this fork port via
scripts/py8dis2dasmos.py. - The four sibling Acorn ROM disassembly repositories under the
acornaeology umbrella that drive Dasmos's
round-trip / parity validation:
acorn-econet-bridge,acorn-6502-tube-client,acorn-nfs,acorn-adfs. - beebasm — the BBC-Micro-style assembler used as the round-trip oracle.
- asyoulikeit — the CLI-output framework Dasmos's reports are built on.
Lineage, Credit and Acknowledgements
Dasmos is a ground-up rewrite and reimagining of a heavily modified fork of py8dis — Steven Flintham's original programmable tracing disassembler for the 6502 family. Dasmos owes the core idea of a scriptable disassembler to Steven and to the py8dis project. Unlike py8dis, Dasmos organises a tracing disassembler as a core algorithm customised through plug-in extensions which provide knowledge of CPUs, different assembly syntaxes, and target environments. The core of the essential design vocabulary — driver scripts, traced classification, label/comment/banner annotations — is all inspired by py8dis.
py8dis was itself heavily influenced by Phill Harvey-Smith's BeebDis, an earlier 6502 disassembler for the BBC Micro ecosystem; py8dis modelled its command surface on BeebDis where it could. Dasmos is therefore a link in a chain of work — BeebDis → py8dis → the acornaeology fork of py8dis → Dasmos — and gratefully acknowledges the contribution each step made to the next.
Driver scripts written for py8dis can be ported automatically to
Dasmos with the bundled scripts/py8dis2dasmos.py:
uv run python scripts/py8dis2dasmos.py path/to/disasm_<rom>.py > ported.py
This README is generated from scripts/readme_template.md.j2 by
scripts/generate_readme.py (the {{ version }} placeholder and
the captured CLI blocks are filled in at generation time). Do not edit
it directly — edit the template (or the generator, or the source files
whose output it captures). You rarely need to run the generator by hand:
the pre-commit hook regenerates README.md and re-stages it on every
relevant commit, and bump-my-version regenerates it as part of a
version bump (via its pre_commit_hooks), so a bump lands the new
version and the refreshed README in one commit. The readme-check CI
job (in ci.yml and release.yml) runs the generator's --check mode
and fails if a committed README is stale.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dasmos-4.1.0.tar.gz.
File metadata
- Download URL: dasmos-4.1.0.tar.gz
- Upload date:
- Size: 345.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b3e3531b710545173c33dd9c4ce5c0ef8a7ec3429fd752ea16e1436cd1bed07
|
|
| MD5 |
bce06d4dbd407a579c694dfd6bb42150
|
|
| BLAKE2b-256 |
3fdccbd17baf456cc8488e242f018c6c17683e54e6934d4f3e5c1073cff78ec0
|
File details
Details for the file dasmos-4.1.0-py3-none-any.whl.
File metadata
- Download URL: dasmos-4.1.0-py3-none-any.whl
- Upload date:
- Size: 232.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
99d00a307dec5b326a100d8fe885a8eed3f6f56333d32ebdf03834414264c123
|
|
| MD5 |
50134a4424617818f9f004fbb5e86c78
|
|
| BLAKE2b-256 |
0ce1fd033483d3f24d7512c173781d7bb4a7b8d7c1c178d541d0085eb738315c
|