An Open Experiment in 1998

Ben Olmstead designed Malbolge around a goal contrary to that of conventional languages: making programs difficult to write. At the opening of the specification, he compared experimental languages such as INTERCAL, arguing that some appeared strange but still made their operations too easy to infer. His new obstacles were built into the rules of execution.

The original page offered MS-DOS and Unix downloads containing interpreter source code and binaries for different processors. The surviving page marks the Malbolge download as updated on April 15, 1998. Olmstead placed the language, description and interpreter in the public domain. The specification then offered no working examples. The open experiment drew online programming enthusiasts into the search for runnable programs and ways to compose them.

References: [1] [2]

A Ternary Machine with Shared Memory

Malbolge specifies a small ternary virtual machine. Each word has ten trits and can represent values from 0 to 59,048. Its 59,049 memory cells are shared by program and data. Accumulator A, code pointer C and data pointer D all start at zero.

Loading ignores whitespace and places program characters in successive memory cells. The remaining space is generated from existing contents through a special operation. C identifies the current instruction, while D participates in data operations; both normally increment after an execution step. The programmer must arrange future instructions while tracking where the data pointer will move next.

References: [2]

Character Meaning Changes with Its Address

The same character can mean different operations at different addresses. The interpreter combines the character’s numerical value with its position, takes the result modulo 94 and consults a table to determine the instruction. After execution, another table rewrites a code cell. Copying apparently usable code may change its meaning, and running it a second time may produce a different action.

Data operations likewise avoid familiar addition, subtraction and assignment. Core operations include a cyclic right rotation of trits and a special combination performed through a per-trit lookup table. There are no direct general-purpose load and store instructions. Preserving a value or repeatedly reading the same data often requires a chain of auxiliary operations. Difficulty arises from interacting rules as well as unfamiliar-looking characters.

References: [2] [4]

How an Output Program Reaches Its First Character

A greeting program later written by Andrew Cooke illustrates the mechanism. In his 2010 technical presentation, Masahiko Sakai walks through its opening: the first effective operation changes D, two special operations construct a value in A, and only then does an output instruction emit a character. A now contains the ternary value 2200, or decimal 72, producing the ASCII character H.

The sequence gives no literal command saying “output H.” Registers first pass through constrained state changes. Reading it also requires distinguishing written characters from decoded operations; the presentation places both sequences side by side. This later example shows how the original specification’s rules could be organized into actual output.

References: [4]

Using Rewrite Cycles to Build Loops

Lou Scheffer treated Malbolge as an analyzable transformation system. He found short cycles in its code-permutation table, allowing certain instructions to return to their original forms after a finite number of rewrites. A jump changes C before the rewrite acts at the new position, so the original jump instruction itself can survive.

These observations made repeatable structures possible. Scheffer built an input-to-output copying program in 2004, though it did not terminate correctly at end of input. By 2010, Sakai’s presentation showed low- and high-level assembly layers, packaging constrained instruction combinations into more manageable operations and listing programs such as rot13. These tools reduced the burden of composition while retaining the original language’s complex rules.

References: [3] [4]

Specification, Interpreter and Computational Limits

The original text and reference implementation differ in places. The specification’s two input/output symbols are reversed relative to the corresponding reading and writing behavior of the C interpreter. Scheffer and later technical presentations follow the interpreter, making the chosen authority consequential when reconstructing early programs.

Olmstead conjectured in the original specification that the language might be Turing-complete. The original machine has fixed memory. Scheffer later proposed the Malbolge-T variant, adding an external tape movable in both directions to address formal Turing completeness. Programs have demonstrated loops and character transformations in the original language within its finite memory.

References: [2] [3]