劲爆的语言应该用劲爆的音乐来衬托!

前言

在以往的CTF比赛中,遇见过BF(可不是BoyFriend….我倒是缺个GirlFriend/(ㄒoㄒ)/~),第一次见这种语言的时候完全蒙了,因为完全不知道知识什么,还以为是某种神奇的编码。。。后来一搜才知道这竟然是一种神奇的语言。。。。还好网上又很多关于Brainfuck的解释器,或者是自己写一一个也可以,解释一下就OK了

简介

Brainfuck是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainf$$ck或brainf$$k,甚至被简称为BF。Müller的目标是建立一种简单的、可以用最小的编译器来实现的、符合图灵完全思想的编程语言。这种语言由八种状态构成,为Amiga机器编写的编译器(第二版)只有240个字节大小!就象它的名字所暗示的,brainfuck程序很难读懂。尽管如此,brainfuck图灵机一样可以完成任何计算任务。虽然brainfuck的计算方式如此与众不同,但它确实能够正确运行。
这种语言基于一个简单的机器模型,除了指令,这个机器还包括:一个以字节为单位、被初始化为零的数组、一个指向该数组的指针(初始时指向数组的第一个字节)、以及用于输入输出的两个字节流。
这种语言,是一种按照“Turing complete(完整图灵机)”思想设计的语言,它的主要设计思路是:用最小的概念实现一种“简单”的语言,BrainF$$k 语言只有八种符号,所有的操作都由这八种符号的组合来完成。

操作符

下面是这八种状态的描述,其中每个状态由一个字符标识:

1
2
3
4
5
6
7
8
9
10
11

字符 含义
> 指针加一
< 指针减一
+ 指针指向的字节的值加一
- 指针指向的字节的值减一
. 输出指针指向的单元内容(ASCⅡ码)
, 输入内容到指针指向的单元(ASCⅡ码)
[ 如果指针指向的单元值为零,向后跳转到对应的]指令的次一指令处
] 如果指针指向的单元值不为零,向前跳转到对应的[指令的次一指令处

小例子

这里转一个别人写的小例子,感觉很有趣,跟着例子过一遍,应该就是理解的差不多了。。

将八个操作符 < > + - [ ] . , 分别转写为:

1
2
3
4
5
6
7
8
> 右
< 左
+ 上
- 下
[ 始
] 终
. 写
, 读

然后找一张方格纸,对就是小学作文本那种,一支铅笔(不,钢笔不行,Lamy 的也不行),一块橡皮,一张从你的旧 C 语言书上撕下来的 ASCII 码表。

现在来看 +++[>+<-] 这行程序。按照我们的转写,它变成:上上上始右上左下终。

接下来在你的方格纸上的第一个格子里写下 0

[0]

很好。现在我们一边读转写好的程序,一边按照以下规则行事:
遇到什么都没写的格子就当里面写了 0

1
2
3
4
5
6
7
8
右:向右移动一个格子。嗯你盯着它看就行了,什么都不用做 
左:向左移动一个格子
上:给格子里的数字加上 1,擦掉原来的数字再写回去。现在你知道为什么要用铅笔了吧,少年!
下:给格子里的数字减去 1
始:开始重复「始……终」之间的指令,直到你读到「始」之前盯着的那个格子里的数字变成 0 为止。(什么?那个格子里已经是负数了?……不要这么没有下限好不好)
终:如果当前格子里的数字为 0,就跳过,否则回头到「始」那里
写:查当前格子里的数字在 ASCII 表上对应的字母,把它写下来(不,别写在格子里,就写在你买来一直立志想用但是没有用的日记本上吧)
读:随便想一个英文字母,查表找到它对应的数字,写到当前格子里

我们开始吧。方括号代表当前你盯着看的格子。首先是上,上,上:
[3]
接下来,始:
[3]
嗯,你要重复做它到「终」之间的事情。首先是「右」:

3[0]
上:
3[1]
左:
[3]1
下:
[2]1
终:
碰到「始」之前你盯着的那个格子,你还记得吗?碰巧就是当前这个。目前里面是 2 ,不是 0,所以我们回去「始」。
右:
2[1]
上:
2[2]
左:
[2]2
下:
[1]2
终:
回去「始」
右:
1[2]
上:
1[3]
左:
[1]3
下:
[0]3
终:
格子里是 0 了,你可以跳过「终」读下去了。 这段程序就此完结,但如果你读懂了这些,其实就已经看懂了我那个程序最开始的部分:

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

无非就是,先把最左边的格子加到 10,然后向右移动,移动到第二个格子里加 3,第三个加 4,第四个加 7,第五个加 10,第六个加 11,然后向左移动五次,回到第一格,减 1。如此重复十次之后,最左边的格子变成 0,循环终止,而我有了如下格子:

[0] 30 40 70 100 110

接下来的部分,就是挪到某个格子,加上或者减去若干次 1,直到获得想要字母的 ASCII 代码,然后用 . 把它打印出来。比如紧接着的 >>>++. 就是右移三次,到写了 70 的格子上,加两次 1,得到 ASCII 72 ,大写字母 H,再用 . 把它显示出来。

很简单吧?学会了?恭喜你……

参考

Brainfuck
brainfuck 语言入门
BrainFuck 解释器(C语言实现)
brainfuck 在线解释器


声明:
文章标题:Brainfuck语言入门
文章作者:h3h3da
文章链接:https://www.liucunzhan.com/p/ed7cf337-8629-4ff1-abd3-6d3f854a80ee
文章版权属本博主所有,有问题或者建议欢迎在下方评论。欢迎转载、引用,但请标明作者和原文地址,谢谢。


喜欢,就支持我一下吧~