Est. 2005 Advanced

HackVM

A minimal stack-based virtual machine and single-character instruction language, published as Hack VM at hacker.org, whose 28 single-character opcodes exist mainly so that puzzle solvers can hand-write tiny programs for the site's programming challenges.

Created by Adam Miller, credited as the author of Hack VM by both the Esolang wiki and Progopedia. The language and its two reference interpreters are published at hacker.org, the puzzle and challenge site the VM was built to serve

Paradigm Imperative, stack-oriented assembly. A program is a flat string of single-character opcodes executed against an operand stack, a 16,384-cell memory buffer and a separate call stack; there are no names, labels, declarations or structured statements of any kind
Typing Untyped. Every operand stack slot and every memory cell holds one signed integer, and the same value is a number, a character code, a memory address or a jump offset depending only on which instruction consumes it
First Appeared Commonly catalogued as 2005, a date this page could not independently corroborate from any primary source. The earliest archived copy of the Hack VM documentation page located while researching this article dates from 21 November 2008
Latest Version Unversioned. The Python reference interpreter and the in-browser JavaScript interpreter at hacker.org carry no version number or release date, and the language has no changelog

HackVM - published as Hack VM, and subtitled by its author A Virtual Machine for Hackers - is a deliberately tiny stack machine whose programs are strings of single-character instructions. Its own documentation makes no larger claim for it than the truth: it is “a tiny, trivial, virtual machine” whose “purpose is to be used as a simple execution engine that can run very simple programs.” It exists because the puzzle site hacker.org needed a target for challenges that ask you to write a program that produces this output, and a language small enough to specify in one page and implement in a hundred lines is the right size for that job.

That modesty is what makes it interesting. Most esoteric languages are built to be admired, argued about, or laughed at, and are then never used. HackVM was built to be used, by strangers, under adversarial conditions, to solve problems set by someone else. Progopedia makes exactly this point when it calls Hack VM “one of the few really used esoteric languages.”

Disambiguation

The name collides badly, and three unrelated things are routinely confused with it:

NameWhat it actually is
HackVM / Hack VM (this page)Adam Miller’s stack machine at hacker.org, used for the site’s challenges
The Hack VM languageThe intermediate stack language of the Hack computer from The Elements of Computing Systems (nand2tetris), an entirely separate educational platform
HHVM / HackMeta’s PHP-derived language and its virtual machine, a large production system with no connection to either of the above

Repositories named hackvm on GitHub belong to both of the first two projects, so the name alone never identifies which machine is meant.

The Machine

The execution model fits in a paragraph. A program is a string; the index into that string is the program counter. The machine starts at index 0, executes the character it finds, advances, and repeats. It stops when the program counter reaches the end of the code, when an ! instruction executes, or when an exception is thrown.

The state is three pieces:

  • An operand stack, where almost all work happens.
  • A memory buffer of 16,384 cells, addressed 0 through 16383, all zero at startup unless the challenge specifies an initial state. Pre-initialised memory is how a challenge feeds input to a program - there is no read instruction.
  • A call stack, used only to hold return addresses.

Every cell, on the stack or in memory, holds one signed integer. The documentation says these are “currently limited to 32 bits, but do not count on it, they could be large in future implementations” - and the Python interpreter published at hacker.org in fact bounds values at the signed 64-bit range, raising an integer overflow exception outside it. Programs that depend on wraparound, or on a specific overflow point, are depending on an implementation detail the author explicitly warned about.

The Instruction Set

The documentation gives no total; counting the ten digit pushes and the no-op space, the instruction table holds twenty-eight distinct opcode characters. S0 is the top of the stack, S1 the next, and most instructions consume the operands they read.

OpcodeEffect
(space)Do nothing - the only formatting tool the language has
0-9Push that digit
+ - * /Push S1+S0, S1-S0, S1*S0, S1/S0
:Push -1 if S1<S0, 0 if equal, 1 if S1>S0
<Push the contents of memory cell S0
>Store S1 into memory cell S0
^Push a copy of S<S0+1> - so 0^ duplicates the top
vRemove S<S0+1> and push it on top - so 1v swaps the top two
dDrop S0
gAdd S0 to the program counter (relative jump)
?Add S0 to the program counter if S1 is zero
cPush the program counter to the call stack, jump to S0
$Pop the call stack into the program counter (return)
pPrint S0 as an integer
PPrint S0 as an ASCII character, using the low 7 bits
!Terminate

Two things follow immediately from that table, and they shape everything about writing the language.

There are no literals above 9. To print a capital H, ASCII 72, you must build 72 from single digits and arithmetic - 89* gives 72 in two characters, and the official Hello World opens with exactly that. Every string constant in a HackVM program is really a sequence of small arithmetic puzzles, and shorter programs win by finding better factorisations. This is the language’s defining activity.

Jumps are relative and computed. g and ? add a stack value to the program counter, so a loop is written by pushing a negative offset, and every edit to the body of a loop changes the offset that closes it. There are no labels. Subroutine calls via c take an absolute target, again computed on the stack. In practice this means a HackVM program of any length is written, and then rewritten, around its own character offsets.

Two Official Examples

From the documentation itself:

1
78*p

Pushes 7, pushes 8, multiplies, prints the integer: output 56.

1
123451^2v5:4?9p2g8pppppp

Output 945321. The program uses ^ to copy a value from deep in the stack, v to rotate one to the top, : to compare, and ? to jump conditionally - roughly the whole machine exercised in twenty-four characters. Programs at this density are normal for the language rather than exceptional, because challenge answers are scored by producing the right output at all, and terse programs are easier to reason about than long ones when every jump is a hand-counted offset.

For a sense of what real work looks like, Progopedia’s documented Fibonacci program keeps its loop counter in memory cell 0, the ASCII codes for comma and space in cells 1 and 2, and the two most recent Fibonacci values in cells 3 and 4, driving the whole loop with a single ? and a single g. Its factorial program is structured the same way and is reported to terminate with an integer overflow exception at 13! - a value that exceeds the documented 32-bit range but not the 64-bit bound the Python interpreter actually enforces, so where the ceiling falls depends on which interpreter you run. Either way the machine’s limits are close enough to the surface that ordinary programs hit them.

Implementations

There are two implementations by the author and very few by anyone else.

The Python interpreter (hackvm.py) is the reference. It is a single file, and reading it is the fastest way to resolve ambiguities in the prose specification. Several details are visible only there: execution is capped at 10,000 cycles and aborts with a too many cycles exception beyond that, so unbounded search programs cannot simply be left to run; memory reads and writes outside 0-16383 raise access-violation exceptions rather than wrapping; ^ and v bounds-check against the current stack depth; and errors are reported on standard error in a fixed !ERROR: format that includes the failing instruction, the program counter and the stack depth. It also accepts --trace, which dumps the operand stack after every instruction - the only debugger the language has - and --init, which loads a comma-separated memory image, the mechanism challenges use to supply input.

The published script is Python 2 code: it uses print as a statement and the built-in cmp, both removed in Python 3. Running it today therefore requires a Python 2 interpreter or a small port. Division is Python 2 integer division on integer operands, so / truncates toward negative infinity rather than toward zero - a difference that matters for programs doing arithmetic on negative values.

The JavaScript interpreter is embedded in the documentation page, with fields for the program, for initial memory contents, and a trace option. Progopedia notes that it is stated to differ from the Python one, which is a warning worth taking seriously: on a puzzle site, a program that behaves differently in the two interpreters is a solver’s problem, not the site’s.

Third-party, a C implementation was published on GitHub in December 2013. Rewriting the VM in a compiled language is a plausible response to challenges that require searching a large space of candidate programs, though no published benchmark compares the C, Python and JavaScript interpreters.

Why It Is Dormant

Nothing about the language was ever deprecated or replaced; it simply reached its final form early and had no reason to change. The specification is one page and complete. The instruction set is the minimum needed for a Turing-equivalent machine plus two output instructions. There is no committee, no versioning, no roadmap, and no user base separate from the challenge site.

The signals of dormancy are all secondary: the Esolang article has been a one-line stub since 2015, the reference interpreter has not been ported off a Python version that reached end of life on 1 January 2020, and the documentation page carries no dates at all. hacker.org itself remains online and its challenge system still runs, so HackVM is better described as finished and static than as abandoned.

Why It Matters

HackVM is a useful specimen for two reasons.

First, it is an unusually clean example of a language as a puzzle substrate. The design decisions that look perverse in a general-purpose language - no literals above 9, relative jumps only, no input instruction, a hard cycle cap - are all correct for the actual requirement, which is that a challenge author must be able to state a problem precisely and verify an answer mechanically. Constraints that would be defects elsewhere are the product here.

Second, it shows what minimal Turing-equivalent design costs its users. The machine has a stack, addressable memory, arithmetic, comparison, conditional relative jumps and a call stack, which is genuinely everything needed to compute. What it lacks is every affordance that makes computation writable by humans: names, labels, structure, literals, types, and any error reporting richer than a program counter. Working in it teaches, faster than an argument could, that the difference between a language you can compute in and a language you can program in is almost entirely made of affordances rather than power.

For anyone who wants the same lesson with a curriculum attached, the nand2tetris Hack VM is the better-documented place to get it. For anyone who wants the lesson delivered as a puzzle with a scoreboard, this is the one that was built for it.

Timeline

2005
The year most commonly given in language catalogues for the first appearance of HackVM. No primary source confirming it was found for this page, and the date should be read as approximate
2008
The earliest archived snapshot of the Hack VM documentation page at hacker.org that could be located for this article dates from 21 November. By this point the page already carries the complete instruction table, the worked examples and the downloadable Python interpreter, so the language was finished and in use for challenges some time before this date rather than starting at it
2010
On 20 June an anonymous contributor creates the Esolang wiki entry for Hack VM as a stub, the earliest dated third-party record of the language in the wiki's revision history
2013
On 27 December an independent C implementation of the VM is published on GitHub by Juan Pablo Rinaldi, described by its author as a C implementation of the Hack VM from hacker.org. The repository was created on that date and last updated in January 2014. It is one of very few third-party implementations; the author does not state a motive, and no comparative measurement of it against the browser or Python interpreters has been published
2015
On 3 September the Esolang wiki article is reduced to a permanent stub. A contributor had pasted the hacker.org documentation into the wiki; editor Oerjan reverted it as a copyright violation, noting there was no evidence the web page was public domain. What remains is a single sentence naming Adam Miller as creator plus a link, which is why the language is so thinly documented in the usual esoteric-language references
2026
As of August the documentation, the in-browser interpreter and the downloadable interpreter remain online and unchanged at hacker.org/hvm/. The reference interpreter is still written in Python 2 syntax and will not run under Python 3 without modification, which is the clearest single indicator of the language's dormancy

Notable Uses & Legacy

hacker.org programming challenges

The only purpose the language was built for, and stated as such in its own documentation: some of the challenges on hacker.org require the solver to write a Hack VM program that produces a particular result. Progopedia singles this out as the reason Hack VM is unusual among esoteric languages, describing it as one of the few that is really used

Hand-golfed constant generation

Because digits 0 through 9 are the only literals, every other number has to be built arithmetically, so a Hack VM program that prints text is really an exercise in finding short expressions for ASCII codes. The official documentation's own example, 78*p, multiplies 7 by 8 and prints 56; Progopedia's Hello World writeup builds each character code in turn and, for the doubled letters in Hello, triples one computed value on the stack rather than recomputing it. This constant-golfing is the characteristic activity of writing the language

Third-party reimplementations

A small number of independent interpreters exist, notably a C implementation published on GitHub in December 2013. There is no ecosystem beyond this - no package manager, no compiler targeting the VM, no standard library

Esoteric-language catalogues

Hack VM has entries in the Esolang wiki and in Progopedia, which is how the language appears in encyclopedic language lists at all. The Esolang entry is a one-line stub; the Progopedia entry, which documents the full instruction set along with Hello World, Fibonacci and factorial programs, is the most complete secondary description in existence

Running Today

Run examples using the official Docker image:

docker pull
Last updated: