2018-06-14 Brainfuck程序手动解释执行

2018-06-14  本文已影响34人  四火流年

2018 Mossad Challenge 这篇文章里,我们遇到了手动解释一段brainfuck程序的问题,这里给出详细解释。

原代码:

+++++++++++[>++++
+++++++<-]>+[<+>-
]-[>+<-------]>--
-[<+>-][<+>-]>++>
+[>++[-<++++++>]<
<]>[<+>-]>+>++[++
>++[-<+++++>]<<]>
[<+>-]>+>+[>++++[
-<++++>]<<]>[<+>-
]++++++++[>++++++
+++++<-]>+[<+>-]+
++>>+>+[->+++[-<+
++++>]<<]>[<+>-]+
+++++++[>++++++++
<-]>+[<+>-]+++>++
++++>+>+-++<>-+--

第一步

+++++++++++
[>+++++++++++<-]

这是一个乘法器,11*11,得121。此时第一个位置为0,第二个位置为121,指针位于第一个位置。用 加粗加斜 表示指针的位置,那么此时的数据记为:

Position 1 Position 2 Position 3 Position 4
0 121

第二步

>+

再加一个1,得122,也就是 z

Position 1 Position 2 Position 3 Position 4
0 122

第三步

[<+>-]

这是一个swap函数,把当前位置的数交换到左边,后面会多次使用。

Position 1 Position 2 Position 3 Position 4
122 0

第四步

-

这里很关键,明明已经是0了,再减一是多少呢?
验证办法很简单,-.-.-.-. 不断地打印字符,直到发现一个可显示的字符

image.png
推断出,第一次-的结果是255(也可以理解为溢出了)。
Position 1 Position 2 Position 3 Position 4
122 255

第五步

[>+<-------]

这个就相当于一个除法器(除以7),但是比较特别,因为[]这个循环退出的唯一条件是 [ 左边这个位置的值为0。那么如果被除数不能被7整除,就要加上256,继续除,最终结果是 (255+256)/ 7 = 73

Position 1 Position 2 Position 3 Position 4
122 0 73

第六步

>---
Position 1 Position 2 Position 3 Position 4
122 0 70

第七步

[<+>-],再进行一次swap,

Position 1 Position 2 Position 3 Position 4
122 70 0

再进行一次swap,[<+>-],没有变化,因为当前位置就是0,所以是一个空循环。

第八步

>++>+
Position 1 Position 2 Position 3 Position 4 Position 5
122 70 0 2 1

第九步

[>++[-<++++++>]<<]

这个双重循环的作用是:把指针向右移动一位,把移动后的位置的值加上2,乘以6,再加到指针左边的位置上(也就是原指针位置),然后指针向左移动两位。

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 0 2 1 2
P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 0 2 13 0

内层循环到这里结束了。

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 0 2 13 0

外层循环到这里,没有结束。

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 0 2 15 0

外层循环,先指针右移,加2。

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 0 92 0 0

然后乘以6,加到左边去。 15*6+2 = 92。内层循环结束

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 0 92 0 0

再左移两个位置,外层循环结束。
92 即为 \

第十步

>[<+>-]

swap

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 0 0 0

第十一步

>+>++[++>++[-<+++++>]<<]
P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 0 1 2

再来一个二重循环:
先右移加1,再右移加2,

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 0 1 2

然后进入外层循环,还没有进入内层循环:

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 0 1 4 2
P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 0 1 14 0

走完第一次内层循环,即2*5+4=14

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 0 1 14 0
P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 0 1 14 0

然后左移两个位置,继续外层循环

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 0 1 14 0
P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 0 83 0 0

1+2+(14+2)*5 = 83

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 0 83 0 0

循环结束

第十二步

>[<+>-]

swap

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 83 0 0 0

第十三步

>+>+[>++++[-<++++>]<<]>[<+>-]

又是一个双重循环加swap,结果是:

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 83 85 0 0 0

第十四步

++++++++[>+++++++++++<-]>+[<+>-]

加上一个 8*11,再加1,然后swap,结果是:

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 83 85 89 0 0

第十五步

+++
P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 83 85 89 3 0

第十六步

>>+>+[->+++[-<+++++>]<<]>[<+>-]

双重循环,swap,结果是:

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 83 85 89 3 90 0 0 0

第十七步

++++++++[>++++++++<-]>+[<+>-]

8*8 + 1 = 65,再swap,结果是

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 83 85 89 3 90 65 0 0

第十八步

+++
P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 83 85 89 3 90 65 3 0

加3

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 83 85 89 3 90 65 3 0

第十九步

>++++++
P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 83 85 89 3 90 65 3 6 0

右移加6

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12
122 70 92 83 85 89 3 90 65 3 6 0

第二十步

>+>+-++<>-+--

只有 >+ 是有效的,即右移加1,剩下的就是0。

P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13
122 70 92 83 85 89 3 90 65 3 6 1 0

好,至此已经手动执行完成,最终的输出为:
122, 70, 92, 83, 85, 89, 3, 90, 65, 3, 6, 1

上一篇下一篇

猜你喜欢

热点阅读