Web site to learn assembly language.
Find a file
2026-06-25 10:09:44 +02:00
dist fix: deleting unused files 2026-06-25 01:14:39 +02:00
examples Split frontend into standalone repository 2026-06-25 00:48:52 +02:00
lessons Split frontend into standalone repository 2026-06-25 00:48:52 +02:00
resources Split frontend into standalone repository 2026-06-25 00:48:52 +02:00
scenarios Split frontend into standalone repository 2026-06-25 00:48:52 +02:00
scripts fix: changing version file to follow auto-building process 2026-06-25 10:03:19 +02:00
src feat: refactoring code to separate git repo version 2026-06-25 01:25:57 +02:00
test fix: changing version file to follow auto-building process 2026-06-25 10:03:19 +02:00
.dockerignore feat: refactoring code to separate git repo version 2026-06-25 01:25:57 +02:00
.gitignore test: triggering build 2026-06-25 10:09:44 +02:00
Dockerfile Split frontend into standalone repository 2026-06-25 00:48:52 +02:00
favicon.ico Split frontend into standalone repository 2026-06-25 00:48:52 +02:00
index.html feat: refactoring code to separate git repo version 2026-06-25 01:25:57 +02:00
Makefile fix: changing version file to follow auto-building process 2026-06-25 10:03:19 +02:00
package-lock.json Split frontend into standalone repository 2026-06-25 00:48:52 +02:00
package.json Split frontend into standalone repository 2026-06-25 00:48:52 +02:00
README.md Split frontend into standalone repository 2026-06-25 00:48:52 +02:00
tsconfig.json Split frontend into standalone repository 2026-06-25 00:48:52 +02:00
VERSION fix: changing version file to follow auto-building process 2026-06-25 10:03:19 +02:00

IA64.CC

IA64.CC is a web x86 assembly learning environment with an MS-DOS style interface.

It includes an assembler, a debugger, scenario-based lessons, register and flag views, memory explorers, breakpoints, stack display, and a VGA text screen. The emulator uses Unicorn, Keystone, and Capstone in the browser.

Requirements

  • Node.js with npm
  • Python 3 for the local static server
  • Chrome or Chromium for smoke tests

Install

make install

Build And Check

make check
make test
make smoke

make check builds the generated browser files and runs TypeScript and syntax checks.

Run Locally

make serve

Open:

http://localhost:8000/index.html

make serve stops any existing process on the selected port before starting the server. Use PORT=8080 make serve to choose another port. The development server disables HTTP caching so rebuilt files are visible after a browser reload.

Scenarios

Scenario files live in scenarios/ as .scenario.json files. A scenario contains:

  • codemap data
  • title, description, icon, difficulty, and victory message
  • initial register state
  • tutorial steps and goals

The build creates a generated dist/scenarios.js manifest from the files in scenarios/.

CodeMap Runtime Contract

The browser keeps an authoring CodeMap for editing and debugging. In that file:

  • src at the top level is optional source metadata used to reopen the full assembler document.
  • zones[n].src is optional per-zone source metadata used by the debugger, labels and symbol views.
  • zones[n].kind is authoring/UI metadata: code zones appear in the debugger Code menu, while data and noinit zones appear in the Data menu for Memory1 and Memory2.
  • zones[n].asm, zones[n].address, zones[n].code and entry are the executable runtime data.

For a remote runtime, source fields are not authoritative. Before hashing or sending a program to a VM server, use the runtime projection from CodemapCore.toRuntimeCodemap() or CodemapCore.runtimeCodemapJson(). That projection strips src, zones[n].src, names and UI-only fields, then keeps only the stable executable payload:

  • format/version
  • target architecture
  • entrypoint
  • zones with address, code mode and base64 machine bytes

IA64.CC directives split that intent in source too: .code 16/32/64 marks an executable zone, .data 16/32/64 marks a loaded data zone, .noinit 16/32/64 marks a work/result zone, and offset @title resolves any loaded zone by title.

Hybrid Runtime Server

The browser still defaults to full-client execution. Hybrid mode is opt-in and uses IA64RuntimeClient to talk to a separately deployed IA64 runtime server. The mode, server address, log level, and text-screen transport can be selected from the debugger menu with Runtime > Configuration; the choice is stored in browser local storage.

By default, the runtime address uses the same-domain prefix /runtime. It can be configured in two ways:

  • Full URL: http://localhost:8080, useful during local development.
  • Same-domain prefix: /runtime, resolved as window.location.origin + "/runtime", useful when the Rust runtime is exposed behind the same site or reverse proxy.

If you keep the split workspace layout, start the backend from the sibling runtime project:

cd ../runtime
make up

Select the runtime implementation:

make up
make up RUNTIME_ENGINE=unicorn
make up RUNTIME_ENGINE=mock

unicorn is the default server runtime. It creates one Unicorn x86 VM instance per session, so multiple sessions can execute independently with isolated CPU and memory state. mock only advances the current address and exists to test the HTTP/WebSocket protocol. If a runtime queue itself becomes unavailable, the server returns 503 RUNTIME_UNAVAILABLE.

Run the backend unit tests without installing Rust locally:

cd ../runtime
make test

Useful client-side calls from the browser console:

IA64RuntimeClient.setRuntimeConfig({ mode: 'hybrid' })
IA64RuntimeClient.setRuntimeConfig({ endpointMode: 'prefix', endpointPrefix: '/runtime' })
IA64RuntimeClient.health()

The server accepts a standard ia64.codemap, validates it, strips authoring metadata into ia64.runtime-codemap, computes a stable hash, stores the runtime payload by hash, and creates lightweight sessions. The current execution engine is Unicorn by default; the mock runtime remains available for protocol tests.

The backend runtime is now hidden behind a small VmRuntime interface. The server can select UnicornRuntime or MockRuntime with IA64_RUNTIME_ENGINE, while the HTTP routes already depend on the interface rather than on one specific implementation.

In hybrid mode the debugger can store CodeMaps on the Rust runtime, create sessions, and exchange bounded step/run commands with the server runtime. Status logs show the remote hash, session id, snapshot current address, snapshot version, and execution delta so the protocol can be verified. After session creation, the debugger prefers the runtime WebSocket for step/run mirroring and falls back to HTTP if the socket is unavailable. Remote snapshots are mirrored in the debugger Status window and the remote instruction pointer is highlighted in the Code window when it is visible. Snapshots include mode-specific general registers, the instruction pointer, stack pointer, flags, segment registers, VGA text rows, small memory windows, and register deltas. The debugger Runtime menu can stay in Mirror mode or switch to Follow, which makes the local instruction pointer follow the remote snapshot current address as an explicit preview mode.

Hybrid execution is intentionally sliced. The browser sends bounded step or run commands instead of asking the backend to run forever. This keeps the UI responsive, gives the runtime a chance to accept keyboard/timer events between slices, and avoids long blocking Unicorn executions. The debugger sends the current breakpoint list with every remote step, run, and key command; the Unicorn runtime stops before executing a breakpoint address, while ignoring the breakpoint already under the instruction pointer at the start of the command so single-step remains usable.

The remote screen snapshot supports text rows plus attributes, 320x200 indexed graphics bytes, and compact WebP images. The debugger can render remote text mode either as DOM cells or as a WebP image. Graphics snapshots are sent as WebP when available. Keyboard IRQ1 is only injected when an explicit keyboard event is sent to the runtime; in the browser UI, physical keyboard events are forwarded only while the virtual keyboard overlay is open, which avoids accidental IRQs while using menus or shortcuts.

The server also exposes GET /api/sessions/{id}/vga.html?refresh=1000, which can be embedded in an iframe to display a VGA snapshot with periodic refresh. For streaming control, the server exposes GET /api/sessions/{id}/ws. The socket sends an initial hello snapshot, then accepts JSON commands such as {"command":"snapshot"}, {"command":"step","count":1}, {"command":"run","count":1000}, {"command":"key","key":"a"}, and {"command":"ping"}. Responses use the same snapshot/delta payload as HTTP.

Repository Layout

  • src/: TypeScript source
  • test/: unit and browser smoke tests
  • scenarios/: scenario JSON files
  • resources/: app images
  • dist/: vendored browser libraries and generated build outputs
  • scripts/build.mjs: build script

Generated files in dist/ are ignored where they are produced by this project. Vendored runtime libraries and assets remain versioned because the app is served as a static web application.