BOX-256 是一款 8 位的虚拟汇编器,它一共有 256 字节内存,16x16的方格显示(16色)。它也是一个编程挑战,玩家可以通过编写和优化代码使其通过图形测试。 玩家的最终目标是通过采用多线程和其他优化技巧,使用尽可能少的 CPU 周期或代码行来实现给定的图案。
玩家通过编写源代码,执行代码并尝试让自己的输出(顶部屏幕)与目标图形(底部屏幕)匹配,并尽可能使用最少的 CPU 周期。
当计算机未执行时,编译器会主动尝试将源代码编译为机器代码。这可以看作是内存在改变,而用户正在编写代码。可以使用 PLAY 按钮从底部开始执行。它会一直持续下去,除非 a) 玩家用STOP或STEP停止它或 b) 输出屏幕与目标匹配并且关卡通过。
如果您想要更多挑战,请使用PREV和NEXT按钮选择其他目标图形。
保存和加载您的代码不幸的是,WebGL不直接支持剪贴板,但游戏使用弹出窗口让您能够间接导入和导出代码。
单击SAVE按钮将打开一个弹出窗口,其中包含您的整个源代码,以便您可以将其复制到剪贴板中。
加载源代码的方式类似。单击LOAD按钮您会看到一个弹出窗口,您可以在其中粘贴代码并单击加载按钮将其移动到游戏中。
编辑SHIFT+箭头键让你选择代码和CTRL-C & CTRL-V 进行复制粘贴。CTRL-Z 和 CTRL-Y 用于撤消和重做。也可以使用插入/删除/退格/回车来移动内容。对于专业玩家和键盘布局怪异的人,'@' 和 '*' 字符也可以用逗号 (,) 和句点 (.) 热键键入。
将鼠标悬停在内存或输出屏幕上可为您提供当前悬停插槽的地址。
固定宽度指令集源代码被编译为 4 字节块的机器代码。换句话说,机器码是基于固定宽度的指令集。然而,有些指令并不使用所有的 4 个字节。 聪明的玩家可以利用这一点。请注意,即使设置了固定宽度,也可以在内存中的任何位置强制程序计数器,而不管机器代码对齐如何。
程序计数器执行开始时,最后一个内存槽(FF)用作程序计数器(PC)。如果启动第二个线程,额外的 PC 将在 FE 中,第三个将在 FD 中,依此类推。由于没有内存保护,可以直接写入PC,导致执行跳转。该行为与使用JMP指令相同。
多线程可以使用THR指令启动多个线程。这些线程并不是真正同时执行的,它们是一个接一个地执行的。出于记分目的,它被视为单个周期。每个线程的内存读取是相同的,并且基于循环开始时缓存的内存状态。对于对同一内存地址的冲突写入,最后写入的线程是赢家。
由于缓存读取,一个线程通常不可能同时与另一个线程通信。然而,仍然存在两个例外:较早的线程可以写入稍后由较晚线程执行的内存地址。所以自修改代码是可能的。较早的线程也可以写入较晚线程拥有的程序计数器 (PC) 以导致立即跳转。 内存地址
源代码中有三个不同的前缀:
0 = 常量值
@ = 在内存中的地址
* = 指向另一个地址的地址 (又被称为指针)
例子:
没有任何内存保护。所有可执行的机器代码、您自己的变量和程序计数器愉快地共存于同一个 00-FF 内存空间中。你可以随时随地阅读和写作,只要你忍受后果:)。
该语言由 11 条可能的指令组成。这些被编译器编译成 120 个不同的操作码。大多数不同的操作码只是同一条指令的不同排列。
MOVMOV A B C
将内存地址 B的值设为A。
当一次移动多个值时,参数 C 可用作数组的长度。
JMP A
将执行跳转到 A。
如果 A 是常量,则它是当前执行地址的偏移量,否则视为绝对地址。通常跳入 4 的乘数是一个好主意,因为指令集是固定宽度的,而下一条指令(通常)位于接下来的 4 个字节中。
请注意,您可以在 A 前面加上减号“-”以获得负值。它们在机器代码中不会被编译为负数,但 JMP -1 会编译为 JMP FF。这是有效的,因为内存正好是 256 字节长,跳转 FF 意味着跳过整个内存并登陆到前一个内存地址。
PIX A B
将像素输出到索引 A 中,颜色为 B。
屏幕为 16x16,由 256 个像素组成。索引从左到右,从上到下增长。左上角的索引是 0,右下角是 255。可用的颜色是从 0 到 F,但是输出大于这个值的值是可以的,因为调色板会不断循环。
JEQ A B C
如果 A 等于 B,则执行跳转到 C。
如果 C 是一个常数,它是当前执行地址的一个偏移量,否则它被认为是一个绝对地址。通常跳入 4 的乘数是一个好主意,因为指令集是固定宽度的,而下一条指令(通常)位于接下来的 4 个字节中。
请注意,您可以在 C 前面加上减号“-”以获得负值。它们在机器代码中不会被编译为负数,但 JMP -1 会编译为 JMP FF。这是有效的,因为内存正好是 256 字节长,跳转 FF 意味着跳过整个内存并登陆到前一个内存地址。
JNE A B C
如果 A 不等于 B,则执行跳转到 C。
如果 C 是一个常数,它是当前执行地址的一个偏移量,否则它被认为是一个绝对地址。通常跳入 4 的乘数是一个好主意,因为指令集是固定宽度的,而下一条指令(通常)位于接下来的 4 个字节中。
请注意,您可以在 C 前面加上减号“-”以获得负值。它们在机器代码中不会被编译为负数,但 JMP -1 会编译为 JMP FF。这是有效的,因为内存正好是 256 字节长,跳转 FF 意味着跳过整个内存并登陆到前一个内存地址。
JGR A B C
如果 A 大于 B,则执行跳转到 C。
如果 C 是一个常数,它是当前执行地址的一个偏移量,否则它被认为是一个绝对地址。通常跳入 4 的乘数是一个好主意,因为指令集是固定宽度的,而下一条指令(通常)位于接下来的 4 个字节中。
请注意,您可以在 C 前面加上减号“-”以获得负值。它们在机器代码中不会被编译为负数,但 JMP -1 会编译为 JMP FF。这是有效的,因为内存正好是 256 字节长,跳转 FF 意味着跳过整个内存并登陆到前一个内存地址。
FLP A B C
翻转内存地址 A 和内存地址 B 之间的值。
当一次翻转多个值时,参数 C 可用作数组的长度。
THR A
从内存地址 A 开始一个新线程
这意味着您希望新线程开始执行的可执行机器代码指令位于内存地址 A 中。
ADD A B C
将值 A 和 B 相加并将结果存储在 C 中
SUB A B C
从 A 中减去 B 并将结果存储在 C
MUL A B C
将值 A 和 B 相乘并将结果存储在 C
DIV A B C
将 A 与 B 相除并将结果存储在 C 中
除零始终计算为 0。
MOD A B C
取A和B的模并将结果放在C中
零 (0) 的模数始终计算为 0。
源代码中的指令在内存中被编译成机器码操作码。这些操作码是计算机执行的实际命令。专家级玩家可以通过将这些值写入编辑器来直接编写程序。也可以在运行时更改已执行的内存,因此如果您知道不同操作码的作用,一切皆有可能。
大多数操作码是相同指令的排列。例如,ADD 指令有 8 个不同的操作码,具体取决于参数的“内存深度”。
存在三种不同的参数“深度”。常量 (0)、地址 (@) 和指针 (*)。
操作码 | 操作说明 | P1 | P2 | P3 | 例子 |
00 | 000 (NOP) | 0 | 1 | 0 | 000 000 000 000 |
01 | MOV | 0 | @ | 0 | MOV 001 @02 003 |
02 | MOV | 0 | * | 0 | MOV 001 *02 003 |
03 | MOV | @ | @ | 0 | MOV @01 @02 003 |
04 | MOV | @ | * | 0 | MOV @01 *02 003 |
05 | MOV | * | @ | 0 | MOV *01 @02 003 |
06 | MOV | * | * | 0 | MOV *01 *02 003 |
07 | MOV | 0 | @ | @ | MOV 001 @02 @03 |
08 | MOV | 0 | * | @ | MOV 001 *02 @03 |
09 | MOV | @ | @ | @ | MOV @01 @02 @03 |
0A | MOV | @ | * | @ | MOV @01 *02 @03 |
0B | MOV | * | @ | @ | MOV *01 @02 @03 |
0C | MOV | * | * | @ | MOV *01 *02 @03 |
0D | MOV | 0 | @ | * | MOV 001 @02 *03 |
0E | MOV | 0 | * | * | MOV 001 *02 *03 |
0F | MOV | @ | @ | * | MOV @01 @02 *03 |
10 | MOV | @ | * | * | MOV @01 *02 *03 |
11 | MOV | * | @ | * | MOV *01 @02 *03 |
12 | MOV | * | * | * | MOV *01 *02 *03 |
13 | ADD | @ | 0 | @ | ADD @01 002 @03 |
14 | ADD | * | 0 | @ | ADD *01 002 @03 |
15 | ADD | @ | @ | @ | ADD @01 @02 @03 |
16 | ADD | * | @ | @ | ADD *01 @02 @03 |
17 | ADD | @ | * | @ | ADD @01 *02 @03 |
18 | ADD | * | 0 | * | ADD *01 002 *03 |
19 | ADD | @ | 0 | * | ADD @01 002 *03 |
1A | ADD | * | @ | * | ADD *01 @02 *03 |
1B | ADD | @ | @ | * | ADD @01 @02 *03 |
1C | ADD | * | * | * | ADD *01 *02 *03 |
1D | SUB | @ | 0 | @ | SUB @01 002 @03 |
1E | SUB | 0 | @ | @ | SUB 001 @02 @03 |
1F | SUB | @ | @ | @ | SUB @01 @02 @03 |
20 | SUB | * | 0 | @ | SUB *01 002 @03 |
21 | SUB | 0 | * | @ | SUB 001 *02 @03 |
22 | SUB | * | @ | @ | SUB *01 @02 @03 |
23 | SUB | @ | * | @ | SUB @01 *02 @03 |
24 | SUB | * | * | @ | SUB *01 *02 @03 |
25 | SUB | @ | 0 | * | SUB @01 002 *03 |
26 | SUB | 0 | @ | * | SUB 001 @02 *03 |
27 | SUB | @ | @ | * | SUB @01 @02 *03 |
28 | SUB | * | 0 | * | SUB *01 002 *03 |
29 | SUB | 0 | * | * | SUB 001 *02 *03 |
2A | SUB | * | @ | * | SUB *01 @02 *03 |
2B | SUB | @ | * | * | SUB @01 *02 *03 |
2C | SUB | * | * | * | SUB *01 *02 *03 |
2D | JEQ | @ | 0 | 0 | JEQ @01 002 003 |
2E | JEQ | @ | @ | 0 | JEQ @01 @02 003 |
2F | JEQ | * | 0 | 0 | JEQ *01 002 003 |
30 | JEQ | * | @ | 0 | JEQ *01 @02 003 |
31 | JEQ | * | * | 0 | JEQ *01 *02 003 |
32 | JEQ | @ | 0 | @ | JEQ @01 002 @03 |
33 | JEQ | @ | @ | @ | JEQ @01 @02 @03 |
34 | JEQ | * | 0 | @ | JEQ *01 002 @03 |
35 | JEQ | * | @ | @ | JEQ *01 @02 @03 |
36 | JEQ | * | * | @ | JEQ *01 *02 @03 |
37 | JEQ | @ | 0 | * | JEQ @01 002 *03 |
38 | JEQ | @ | @ | * | JEQ @01 @02 *03 |
39 | JEQ | * | 0 | * | JEQ *01 002 *03 |
3A | JEQ | * | @ | * | JEQ *01 @02 *03 |
3B | JEQ | * | * | * | JEQ *01 *02 *03 |
3C | MUL | @ | 0 | @ | MUL @01 002 @03 |
3D | MUL | @ | @ | @ | MUL @01 @02 @03 |
3E | MUL | * | 0 | @ | MUL *01 002 @03 |
3F | MUL | * | @ | @ | MUL *01 @02 @03 |
40 | MUL | * | * | @ | MUL *01 *02 @03 |
41 | MUL | @ | 0 | * | MUL @01 002 *03 |
42 | MUL | @ | @ | * | MUL @01 @02 *03 |
43 | MUL | * | 0 | * | MUL *01 002 *03 |
44 | MUL | * | @ | * | MUL *01 @02 *03 |
45 | MUL | * | * | * | MUL *01 *02 *03 |
46 | DIV | @ | 0 | @ | DIV @01 002 @03 |
47 | DIV | 0 | @ | @ | DIV 001 @02 @03 |
48 | DIV | @ | @ | @ | DIV @01 @02 @03 |
49 | DIV | * | 0 | @ | DIV *01 002 @03 |
4A | DIV | * | @ | @ | DIV *01 @02 @03 |
4B | DIV | @ | * | @ | DIV @01 *02 @03 |
4C | DIV | * | * | @ | DIV *01 *02 @03 |
4D | DIV | @ | 0 | * | DIV @01 002 *03 |
4E | DIV | 0 | @ | * | DIV 001 @02 *03 |
4F | DIV | @ | @ | * | DIV @01 @02 *03 |
50 | DIV | * | 0 | * | DIV *01 002 *03 |
51 | DIV | * | @ | * | DIV *01 @02 *03 |
52 | DIV | @ | * | * | DIV @01 *02 *03 |
53 | DIV | * | * | * | DIV *01 *02 *03 |
54 | JMP | 0 | JMP 001 000 000 | ||
55 | JMP | @ | JMP @01 000 000 | ||
56 | JMP | * | JMP *01 000 000 | ||
57 | JGR | 0 | @ | 0 | JGR 001 @02 003 |
58 | JGR | @ | 0 | 0 | JGR @01 002 003 |
59 | JGR | @ | @ | 0 | JGR @01 @02 003 |
5A | JGR | @ | * | 0 | JGR @01 *02 003 |
5B | JGR | * | 0 | 0 | JGR *01 002 003 |
5C | JGR | * | @ | 0 | JGR *01 @02 003 |
5D | JGR | * | * | 0 | JGR *01 *02 003 |
5E | JGR | 0 | @ | @ | JGR 001 @02 @03 |
5F | JGR | @ | 0 | @ | JGR @01 002 @03 |
60 | JGR | @ | @ | @ | JGR @01 @02 @03 |
61 | JGR | @ | * | @ | JGR @01 *02 @03 |
62 | JGR | * | 0 | @ | JGR *01 002 @03 |
63 | JGR | * | @ | @ | JGR *01 @02 @03 |
64 | JGR | * | * | @ | JGR *01 *02 @03 |
65 | JGR | 0 | @ | * | JGR 001 @02 *03 |
66 | JGR | @ | 0 | * | JGR @01 002 *03 |
67 | JGR | @ | @ | * | JGR @01 @02 *03 |
68 | JGR | @ | * | * | JGR @01 *02 *03 |
69 | JGR | * | 0 | * | JGR *01 002 *03 |
6A | JGR | * | @ | * | JGR *01 @02 *03 |
6B | JGR | * | * | * | JGR *01 *02 *03 |
6C | PIX | 0 | 0 | PIX 001 002 000 | |
6D | PIX | 0 | @ | PIX 001 @02 000 | |
6E | PIX | 0 | * | PIX 001 *02 000 | |
6F | PIX | @ | 0 | PIX @01 002 000 | |
70 | PIX | @ | @ | PIX @01 @02 000 | |
71 | PIX | @ | * | PIX @01 *02 000 | |
72 | PIX | * | 0 | PIX *01 002 000 | |
73 | PIX | * | @ | PIX *01 @02 000 | |
74 | PIX | * | * | PIX *01 *02 000 | |
75 | FLP | @ | @ | 0 | FLP @01 @02 003 |
76 | FLP | * | @ | 0 | FLP *01 @02 003 |
77 | FLP | * | * | 0 | FLP *01 *02 003 |
78 | FLP | @ | @ | @ | FLP @01 @02 @03 |
79 | FLP | * | @ | @ | FLP *01 @02 @03 |
7A | FLP | * | * | @ | FLP *01 *02 @03 |
7B | FLP | @ | @ | * | FLP @01 @02 *03 |
7C | FLP | * | @ | * | FLP *01 @02 *03 |
7D | FLP | * | * | * | FLP *01 *02 *03 |
7E | THR | 0 | THR 001 000 000 | ||
7F | THR | @ | THR @01 000 000 | ||
80 | THR | * | THR *01 000 000 | ||
81 | MOD | @ | 0 | @ | MOD @01 002 @03 |
82 | MOD | 0 | @ | @ | MOD 001 @02 @03 |
83 | MOD | @ | @ | @ | MOD @01 @02 @03 |
84 | MOD | * | 0 | @ | MOD *01 002 @03 |
85 | MOD | 0 | * | @ | MOD 001 *02 @03 |
86 | MOD | * | @ | @ | MOD *01 @02 @03 |
87 | MOD | @ | * | @ | MOD @01 *02 @03 |
88 | MOD | * | * | @ | MOD *01 *02 @03 |
89 | MOD | @ | 0 | * | MOD @01 002 *03 |
8A | MOD | 0 | @ | * | MOD 001 @02 *03 |
8B | MOD | @ | @ | * | MOD @01 @02 *03 |
8C | MOD | * | 0 | * | MOD *01 002 *03 |
8D | MOD | 0 | * | * | MOD 001 *02 *03 |
8E | MOD | * | @ | * | MOD *01 @02 *03 |
8D | MOD | @ | * | * | MOD @01 *02 *03 |
90 | MOD | * | * | * | MOD *01 *02 *03 |
91 | JNE | @ | 0 | 0 | JNE @01 002 003 |
92 | JNE | @ | @ | 0 | JNE @01 @02 003 |
93 | JNE | * | 0 | 0 | JNE *01 002 003 |
94 | JNE | * | @ | 0 | JNE *01 @02 003 |
95 | JNE | * | * | 0 | JNE *01 *02 003 |
96 | JNE | @ | 0 | @ | JNE @01 002 @03 |
97 | JNE | @ | @ | @ | JNE @01 @02 @03 |
98 | JNE | * | 0 | @ | JNE *01 002 @03 |
99 | JNE | * | @ | @ | JNE *01 @02 @03 |
9A | JNE | * | * | @ | JNE *01 *02 @03 |
9B | JNE | @ | 0 | * | JNE @01 002 *03 |
9C | JNE | @ | @ | * | JNE @01 @02 *03 |
9D | JNE | * | 0 | * | JNE *01 002 *03 |
9E | JNE | * | @ | * | JNE *01 @02 *03 |
9F | JNE | * | * | * | JNE *01 *02 *03 |
A0 | DIV | 0 | * | @ | DIV 001 *02 @03 |
A1 | DIV | 0 | * | * | DIV 001 *02 *03 |