malbolge编程语言笔记
简述
Malbolge 由 Ben Olmstead 于 1998 年发明。这种晦涩语言被认为是最复杂的编程语言。
据说 Malbolge 编程语言的作者从未使用该语言编写任何程序。Olmstead 发明该语言近两年后,Malbolge 中的 hello world 代码才出现。
这门编程语言使用反直觉的疯狂运算 (crazy operation),三基运算 (base-three arithmetic) 和自修改代码 (self-altering code) 来运行程序。
它的难度在早期的深奥语言 (esoteric languages) 之上,例如 Brainfuck 和 Befunge。
设计
Malbolge 的实现基于三元虚拟机。
在实现上,编译器停止执行 33-126 范围之外的数据 (即仅对可见字符有效)
寄存器
- a → 累加器 (accumulator),用于写操作和标准 I/O
- c → 代码指针 (code pointer),指向当前指令
- d → 数据指针 (data pointer),自动递增,指向数据操作指令
指针符号
- 寄存器 d 可以保存一个内存地址
- [d] 是寄存器间接寻址 (register indirect)
- [c] 是类似的
内存
数据是以三进制形式保存的(包括内存地址)。
不同的实现有不同的内存限制,存在无内存限制的版本 (Malbolge Unshackled)。
指令
Malbolge 有八个指令,通过取值 [c] 来确定要执行的指令,与 c 的值相加,得到的结果模 94,得到虚拟机对应的操作指令:
([c] + c) % 94 | 操作指令 | 用途 |
---|---|---|
4 | jmp [d] | 将 [d] 值赋值给 c。需要注意的是 c 还是会自增,因此执行的下一条指令是 [d] + 1 (mod 59049)。 |
5 | out a | 以 ASCII 码的形式输出 a 的值到屏幕 |
23 | in a | 将输入字符以 ASCII 码的形式赋值给 a。换行符为 10;EOF 标识符是 59048。 |
39 | rotr [d] mov a, [d] | 将 [d] 值旋转 (例如 0002111112 变为 2000211111),并将结果保存在 [d] 和 a。 |
40 | mov d, [d] | 将 [d] 值赋值给 d。 |
62 | crz [d], a mov a, [d] | 将[d]的值和a的值进行疯狂操作 (crazy operation),并将结果保存在 [d] 和 a。 |
68 | nop | 不做任何事。 |
81 | end | 结束程序。 |
default | nop | 不做任何事。但需要注意的是有部分 Malbolge 实现不会接受这样的操作数。 |
在执行每条指令后,有罪的指令 (guilty instruction) 会被加密,以便下一次执行该指令的时候不会做相同的事,除非刚刚发生了一次跳转。然后,c 和 d 的值都加 1 并执行下一条指令。
疯狂操作 (crazy operation)
对于两个输入的三进制数,使用下表来获取结果。
例如 crz 0001112220, 0120120120 得到结果 1001022211
加密
执行指令后,[c] 处的值(不添加任何内容)将替换为自身的值模 94。然后,使用下表找到结果值对应加密值,将加密值赋值给 [c]。
Result | Encrypted | Result | Encrypted | Result | Encrypted | Result | Encrypted | Result | Encrypted |
---|---|---|---|---|---|---|---|---|---|
0 | 57 | 19 | 108 | 38 | 113 | 57 | 91 | 76 | 79 |
1 | 109 | 20 | 125 | 39 | 116 | 58 | 37 | 77 | 65 |
2 | 60 | 21 | 82 | 40 | 121 | 59 | 92 | 78 | 49 |
3 | 46 | 22 | 69 | 41 | 102 | 60 | 51 | 79 | 67 |
4 | 84 | 23 | 111 | 42 | 114 | 61 | 100 | 80 | 66 |
5 | 86 | 24 | 107 | 43 | 36 | 62 | 76 | 81 | 54 |
6 | 97 | 25 | 78 | 44 | 40 | 63 | 43 | 82 | 118 |
7 | 99 | 26 | 58 | 45 | 119 | 64 | 81 | 83 | 94 |
8 | 96 | 27 | 35 | 46 | 101 | 65 | 59 | 84 | 61 |
9 | 117 | 28 | 63 | 47 | 52 | 66 | 62 | 85 | 73 |
10 | 89 | 29 | 71 | 48 | 123 | 67 | 85 | 86 | 95 |
11 | 42 | 30 | 34 | 49 | 87 | 68 | 33 | 87 | 48 |
12 | 77 | 31 | 105 | 50 | 80 | 69 | 112 | 88 | 47 |
13 | 75 | 32 | 64 | 51 | 41 | 70 | 74 | 89 | 56 |
14 | 39 | 33 | 53 | 52 | 72 | 71 | 83 | 90 | 124 |
15 | 88 | 34 | 122 | 53 | 45 | 72 | 55 | 91 | 106 |
16 | 126 | 35 | 93 | 54 | 90 | 73 | 50 | 92 | 115 |
17 | 120 | 36 | 38 | 55 | 110 | 74 | 70 | 93 | 98 |
18 | 68 | 37 | 103 | 56 | 44 | 75 | 104 |
Lou Scheffer 对 Malbolge 的密码分析提到了排列中的六个不同的循环。它们在这里列出:
- 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 ...
这些循环可用于创建每次执行不同操作并最终变得重复的循环。
示例代码
Hello, World!
1 | (=<`#9]~6ZY327Uv4-QsqpMn&+Ij"'E%e{Ab~w=_:]Kw%o44Uqp0/Q?xNvL:`H%c#DD2^WV>gY;dts76qKJImZkj |
编辑与运行
我们可以使用在线网站来编辑和运行我们的 malbolge 程序: