Malbolge#Hello, World!

{{Short description|1998 esoteric programming language}}

{{pp|small=yes}}

{{about|the programming language|the eighth circle of hell in Dante's Inferno|Malebolge}}

{{Infobox programming language

| title = Malbolge

| screenshot = Malbolge cat program.png

| screenshot caption = A cat program in Malbolge

| paradigm = Esoteric, imperative, scalar, value-level

| designer = Ben Olmstead{{Cite web

|url=https://esolangs.org/wiki/Malbolge

|title=Malbolge - Esolang

|access-date=2022-08-27

|archive-date=2022-08-27

|archive-url=https://web.archive.org/web/20220827150419/https://esolangs.org/wiki/Malbolge

|url-status=live

}}

| developer = Ben Olmstead

| discontinued = yes

| released = 1998

| influenced by = Brainfuck, INTERCAL (Tri-INTERCAL), Befunge

| influenced = Dis, Malbolge Unshackled

| File extensions = .mal, .mb

| typing = Untyped

}}

Malbolge ({{IPAc-en|m|æ|l|ˈ|b|oʊ|l|dʒ}}) is a public domain esoteric programming language invented by Ben Olmstead in 1998, named after the eighth circle of hell in Dante's Inferno, the Malebolge. It was specifically designed to be almost impossible to use, via a counter-intuitive "crazy operation", base-three arithmetic, and self-altering code. It builds on the difficulty of earlier challenging esoteric languages (such as Brainfuck and Befunge) but exaggerates this aspect to an extreme degree, playing on the entangled histories of computer science and encryption. Despite this design, it is possible to write useful Malbolge programs.

Programming in Malbolge

Malbolge was very difficult to understand when it arrived, taking two years for the first Malbolge program to appear. The author himself has never written a Malbolge program. The first program was not written by a human being; it was generated by a beam search algorithm designed by Andrew Cooke and implemented in Lisp.{{cite web

|url=https://www.acooke.org/malbolge.html

|url-access=

|title= malbolge: hello world

|last=Cooke

|first=Andrew

|language=en

|access-date=2021-01-08

|url-status=dead

|archive-url=https://web.archive.org/web/20191206191704/https://www.acooke.org/malbolge.html

|archive-date=2019-12-06

}}

Later, Lou Scheffer posted a cryptanalysis of Malbolge and provided a program to copy its input to its output. He also saved the original interpreter and specification after the original site stopped functioning and offered a general strategy of writing programs in Malbolge as well as some thoughts on its Turing completeness.{{Cite web

| title = Malbolge - Programming language

| url = http://progopedia.com/language/malbolge/

| first = Mariya

| last = Mykhailova

| date = 2012-05-11

| publisher = Progopedia

| accessdate = 2017-06-09

| archive-date = 2023-06-09

| archive-url = https://web.archive.org/web/20230609041355/http://progopedia.com/language/malbolge/

| url-status = live

}}

Olmstead believed Malbolge to be a linear bounded automaton. There is a discussion about whether one can implement sensible loops in Malbolge—it took many years before the first non-terminating one was introduced. A correct 99 Bottles of Beer program, which deals with non-trivial loops and conditions, was not announced for seven years; the first correct one was by Hisashi Iizawa in 2005.{{cite web

| url=http://www.99-bottles-of-beer.net/language-malbolge-995.html

| title=Language Malbolge

| publisher=99 Bottles of Beer

| date=2005-12-29

| archive-url=https://web.archive.org/web/20200514153526/http://www.99-bottles-of-beer.net/language-malbolge-995.html

| archive-date=2020-05-14

| url-status=dead

| accessdate=2020-11-19}} Hisashi Iizawa et al. also proposed a guide for programming in Malbolge for the purpose of obfuscation for software protection.

In 2020, Kamila Szewczyk published a Lisp interpreter written in Malbolge Unshackled.{{Citation|last=Palaiologos|title=kspalaiologos/malbolge-lisp|date=2021-03-04|url=https://github.com/kspalaiologos/malbolge-lisp|access-date=2021-03-23}}{{Cite web |first=Gregory |last=Laughlin |date=2022-03-26 |title=Malbolge (a second look) |website=oklo |url=https://oklo.org/2022/03/26/malbolge-a-second-look/ |access-date=2023-10-24 |language=en-US}}

Example programs

= Hello, World! =

This program displays "Hello, World!".{{Citation|last=Palaiologos|title=kspalaiologos/hello.mb|date=2021-03-04|url=https://gist.github.com/kspalaiologos/a1fe6913aaff8edea515b4af385368fe|access-date=2021-03-23|archive-date=2021-08-05|archive-url=https://web.archive.org/web/20210805174318/https://gist.github.com/kspalaiologos/a1fe6913aaff8edea515b4af385368fe|url-status=live}}

(=<`#9]~6ZY327Uv4-QsqpMn&+Ij"'E%e{Ab~w=_:]Kw%o44Uqp0/Q?xNvL:`H%c#DD2^WV>gY;dts76qKJImZkj

=<code>cat</code> program =

This program reads a string from a user and prints that string, similar to the Unix command-line utility cat.{{Cite web |last=Lutter |first=Matthias |title=Malbolge cat |url=https://lutter.cc/malbolge/cat.html |access-date=2022-08-28 |website=lutter.cc |archive-date=2022-08-28 |archive-url=https://web.archive.org/web/20220828200812/https://lutter.cc/malbolge/cat.html |url-status=live }}

(=BA#9"=<;:3y7x54-21q/p-,+*)"!h%B0/.

~P<

<:(8&

66#"!~}|{zyxwvu

gJ%

Design

Malbolge is machine language for a ternary virtual machine, the Malbolge interpreter.

The standard interpreter and the official specification do not match perfectly.{{Cite web

| title = Malbolge

| url = http://www2.latech.edu/~acm/helloworld/malbolge.html

| first = Austin

| last = Green

| date = 2000-12-01

| website = Louisiana Tech University

| accessdate = 2017-06-09

| archive-date = 2017-07-09

| archive-url = https://web.archive.org/web/20170709110418/http://www2.latech.edu/~acm/helloworld/malbolge.html

| url-status = live

}} One difference is that the compiler stops execution with data outside the 33–126 range. Although this was initially considered a bug in the compiler, Ben Olmstead stated that it was intended and there was in fact "a bug in the specification".

= Registers =

Malbolge has three registers, a, c, and d. When a program starts, the value of all three registers is zero.

a stands for "accumulator", set to the value written by all write operations on memory and used for standard I/O. c, the code pointer, is special: it points to the current instruction.{{Cite web

| title = Malbolge Specification

| url = http://www.lscheffer.com/malbolge_spec.html

| last = Olmstead

| first = Ben

| date = 1998

| website = www.lscheffer.com

| accessdate = 2017-06-09

| archive-date = 2017-06-11

| archive-url = https://web.archive.org/web/20170611074817/http://www.lscheffer.com/malbolge_spec.html

| url-status = live

}} d is the data pointer. It is automatically incremented after each instruction, but the location it points to is used for the data manipulation commands.

= Pointer notation =

d can hold a memory address; [d] is register indirect; the value stored at that address. [c] is similar.

= Memory =

The virtual machine has 59,049 (310) memory locations that can each hold a ten-trit ternary number. Each memory location has an address from 0 to 59048 and can hold a value from 0 to 59048. Incrementing past this limit wraps back to zero.

The language uses the same memory space for both data and instructions. This was influenced by how hardware such as x86 architecture worked.

Before a Malbolge program starts, the first part of memory is filled with the program. All whitespace in the program is ignored and, to make programming more difficult, everything else in the program must start out as one of the instructions below.

The rest of memory is filled by using the crazy operation (see below) on the previous two addresses ([m] = crz [m - 2], [m - 1]). Memory filled this way will repeat every twelve addresses (the individual ternary digits will repeat every three or four addresses, so a group of ternary digits is guaranteed to repeat every twelve).

Note that the official specification does not cover the edge case of 1-instruction programs, where trying to fill the second memory position using the crazy operation, as indicated before, will result in [m - 2] pointing outside the program's memory region. The reference implementation does not explicitly consider this case either and incurs in undefined behavior.{{Cite web

| title = Malbolge reference interpreter

| url = https://www.lscheffer.com/malbolge_interp.html

| last = Olmstead

| first = Ben

| date = 1998

| website = www.lscheffer.com

| accessdate = 2024-09-27

| archive-date = 2024-08-08

| archive-url = https://web.archive.org/web/20240808044301/http://www.lscheffer.com/malbolge_interp.html

| url-status = live

}}

In 2007, Ørjan Johansen created Malbolge Unshackled, a version of Malbolge which does not have the arbitrary memory limit. The hope was to create a Turing-complete language while keeping as much in the spirit of Malbolge as possible. No other rules are changed, and all Malbolge programs that do not reach the memory limit are still completely functional.{{Cite web

| title = An interpreter for the Malbolge Unshackled dialect

| url = http://oerjan.nvg.org/esoteric/Unshackled.hs

| first = Ørjan

| last = Johansen

| format = Haskell

| date = 2013-10-25

| website = oerjan.nvg.org

| accessdate = 2017-06-09}}

= Instructions =

Malbolge has eight instructions. Malbolge figures out which instruction to execute by taking the value [c], adding the value of c to it, and taking the remainder when this is divided by 94. The final result tells the interpreter what to do:

style="margin:auto;" class="wikitable"

|+ Instructions

Value of
{{mono|([c] + c) % 94}}
Instruction
represented
Explanation
4

| {{mono|jmp [d]}} || style="text-align:left;"| Copies the value at [d] to c. Note that c will still be incremented after execution of this instruction, so the next instruction to be executed will be the one at [d] + 1 (modulo 59049).

5

| {{mono|out a}} || style="text-align:left;"| Prints the value of a, as an ASCII character, to the screen.

23

| {{mono|in a}} || style="text-align:left;"| Inputs a character, as an ASCII code, into a. Newlines or line feeds are both code 10. An end-of-file condition is code 59048.

39

| {{mono|rotr [d]
mov a, [d]}} || style="text-align:left;"| Rotates the value at [d] by one ternary digit to the right (0002111112 becomes 2000211111). Stores the result both at [d] and in a.

40

| {{mono|mov d, [d]}} || style="text-align:left;"| Copies the value at [d] to d.

62

| {{mono|crz [d], a
mov a, [d]}} || style="text-align:left;"| Does the crazy operation (see below) with the value at [d] and the value of a. Stores the result both at [d] and in a.

68

| {{mono|nop}} || style="text-align:left;"| Does nothing.

81

| {{mono|end}} || style="text-align:left;"| Ends the Malbolge program.

Any other value

| colspan="2" | does the same as 68: nothing. These other values are not allowed in a program while it is being loaded, but are allowed afterwards.

After each instruction is executed, it gets encrypted (see below) so that it will not do the same thing next time, unless a jump just happened. Right after a jump, Malbolge will encrypt the instruction just prior to the one it jumped to instead. Then, the values of both c and d are increased by one and the next instruction is executed.

= ''Crazy'' operation <!--Name Crazy isn't found in source material, see talk page--> =

For each ternary digit of both inputs, use the following table to get a ternary digit of the result. For example, crz 0001112220, 0120120120 gives 1120020211.

style="margin:auto;" class="wikitable"

|+ Crazy operation{{Cite web

| title = Interview with Ben Olmstead

| url = https://esoteric.codes/blog/interview-with-ben-olmstead

| last = Temkin

| first = Daniel

| date = 2014-11-03

| website = esoteric.codes

| accessdate = 2021-01-07

| archive-date = 2023-03-20

| archive-url = https://web.archive.org/web/20230320212242/https://esoteric.codes/blog/interview-with-ben-olmstead

| url-status = live

}}{{Cite web

| title = Programming Method in Obfuscated Language Malbolge

| url = http://www.sakabe.i.is.nagoya-u.ac.jp/~nishida/DB/pdf/iizawa05ss2005-22.pdf

| last = IIZAWA

| first = Hisashi

| publisher = Nagoya University

| language = Japanese

| accessdate = 2017-06-09

| archive-date = 2017-06-23

| archive-url = https://web.archive.org/web/20170623131043/http://www.sakabe.i.is.nagoya-u.ac.jp/~nishida/DB/pdf/iizawa05ss2005-22.pdf

| url-status = live

}}

style="text-align:center;"

! colspan="2" rowspan="2" | crz !! colspan="3" | Input 1

style="text-align:center;"

! 0 !! 1 !! 2

style="text-align:center;"

! rowspan="3" | Input 2 !! 0

| 1

00
style="text-align:center;"

! 1

| 1

02
style="text-align:center;"

! 2

| 2

21

=Encipherment=

After an instruction is executed, the value at [c] (without anything added to it) will be replaced with itself mod 94. Then, the result is enciphered with one of the following two equivalent methods.

; Method 1: Find the result below. Store the ASCII code of the character below it at [c].

0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999

0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123

----------------------------------------------------------------------------------------------

9m<.TVac`uY*MK'X~xDl}REokN:#?G"i@5z]&gqtyfr$(we4{WP)H-Zn,[%\3dL+Q;>U!pJS72FhOA1CB6v^=I_0/8|jsb

; Method 2: Find the result below. Store the encrypted version at [c].

style="margin:auto;" class="wikitable"

|+ Encryption table

style="text-align:center;"

! Result !! Encrypted !! Result !! Encrypted !! Result !! Encrypted !! Result !! Encrypted !! Result !! Encrypted

style="text-align:center;"

| 0

57191083811357917679
style="text-align:center;"

| 1

109201253911658377765
style="text-align:center;"

| 2

6021824012159927849
style="text-align:center;"

| 3

4622694110260517967
style="text-align:center;"

| 4

842311142114611008066
style="text-align:center;"

| 5

8624107433662768154
style="text-align:center;"

| 6

9725784440634382118
style="text-align:center;"

| 7

9926584511964818394
style="text-align:center;"

| 8

9627354610165598461
style="text-align:center;"

| 9

1172863475266628573
style="text-align:center;"

| 10

8929714812367858695
style="text-align:center;"

| 11

423034498768338748
style="text-align:center;"

| 12

77311055080691128847
style="text-align:center;"

| 13

753264514170748956
style="text-align:center;"

| 14

3933535272718390124
style="text-align:center;"

| 15

88341225345725591106
style="text-align:center;"

| 16

12635935490735092115
style="text-align:center;"

| 17

12036385511074709398
style="text-align:center;"

| 18

6837103564475104

Lou Scheffer's cryptanalysis of Malbolge mentions six different cycles in the permutation. They are listed here:

  • 33 ⇒ 53 ⇒ 45 ⇒ 119 ⇒ 78 ⇒ 49 ⇒ 87 ⇒ 48 ⇒ 123 ⇒ 71 ⇒ 83 ⇒ 94 ⇒ 57 ⇒ 91 ⇒ 106 ⇒ 77 ⇒ 65 ⇒ 59 ⇒ 92 ⇒ 115 ⇒ 82 ⇒ 118 ⇒ 107 ⇒ 75 ⇒ 104 ⇒ 89 ⇒ 56 ⇒ 44 ⇒ 40 ⇒ 121 ⇒ 35 ⇒ 93 ⇒ 98 ⇒ 84 ⇒ 61 ⇒ 100 ⇒ 97 ⇒ 46 ⇒ 101 ⇒ 99 ⇒ 86 ⇒ 95 ⇒ 109 ⇒ 88 ⇒ 47 ⇒ 52 ⇒ 72 ⇒ 55 ⇒ 110 ⇒ 126 ⇒ 64 ⇒ 81 ⇒ 54 ⇒ 90 ⇒ 124 ⇒ 34 ⇒ 122 ⇒ 63 ⇒ 43 ⇒ 36 ⇒ 38 ⇒ 113 ⇒ 108 ⇒ 39 ⇒ 116 ⇒ 69 ⇒ 112 ⇒ 68 ⇒ 33 ...
  • 37 ⇒ 103 ⇒ 117 ⇒ 111 ⇒ 120 ⇒ 58 ⇒ 37 ...
  • 41 ⇒ 102 ⇒ 96 ⇒ 60 ⇒ 51 ⇒ 41 ...
  • 42 ⇒ 114 ⇒ 125 ⇒ 105 ⇒ 42 ...
  • 50 ⇒ 80 ⇒ 66 ⇒ 62 ⇒ 76 ⇒ 79 ⇒ 67 ⇒ 85 ⇒ 73 ⇒ 50 ...
  • 70 ⇒ 74 ⇒ 70 ...

These cycles can be used to create loops that do different things each time and that eventually become repetitive. Lou Scheffer used this idea to create a Malbolge program (included in his cryptanalysis linked below) that repeats anything the user inputs.

Variants

Malbolge is not Turing-complete, due to its memory limits. However, it otherwise has sequential execution, repetition, and conditional-execution. Several attempts have been made to create Turing-complete versions of Malbolge:

  • Malbolge20 is a version of Malbolge with an expanded word-size of 20 trits, allowing one to write a program with a size of up to ~3.4 gigabytes.{{Cite web |title=Malbolge20 - Esolang |url=https://esolangs.org/wiki/Malbolge20 |access-date=2022-12-12 |website=esolangs.org |archive-date=2022-12-12 |archive-url=https://web.archive.org/web/20221212005023/https://esolangs.org/wiki/Malbolge20 |url-status=live }}
  • Malbolge-T is a theoretical version of Malbolge that resets the input/output stream upon reaching the end, allowing for unbounded programs. Malbolge-T would be backward compatible with Malbolge.{{Cite web

| title = Introduction to Malbolge

| url = http://www.lscheffer.com/malbolge.shtml

| last = Scheffer

| first = Lou

| date = 2015-04-17

| accessdate = 2017-06-09

| archive-date = 2023-06-11

| archive-url = https://web.archive.org/web/20230611003703/http://www.lscheffer.com/malbolge.shtml

| url-status = live

}}

  • Malbolge Unshackled is a Turing-complete variation, allowing for programs of any length. However, due to command variations to allow for values above 257, valid Malbolge programs will not necessarily run correctly in Malbolge Unshackled.{{cite web |date=2024-09-26 |title=Malbolge Unshackled |url=https://esolangs.org/wiki/Malbolge_Unshackled |accessdate=2024-12-03 |website=esolangs.org}}

See also

{{Portal|Free and open-source software}}

References

{{Reflist|30em}}