Интерпретатор Brainfuck размером 160 байт

Прочитав про IP-стэк twIP, который помещается в размер твита и отвечает на пинги, корейский программист Канг Сеонгхун (Kang Seonghoon) решил создать нечто такое же миниатюрное и при этом работоспособное. И он создал самый маленький интерпретатор Brainfuck на C размером всего 160 байт.

s[99],*r=s,*d,c;main(a,b){char*v=1[d=b];for(;c=*v++%93;)for(b=c&2,b=c%7?a&&(c&17?c&1?(*r+=b-1):(r+=b-1):syscall(4-!b,b,r,1),0):v;b&&c|a**r;v=d)main(!c,&a);d=v;}

Интерпретатор способен выполнять любые программы на Brainfuck.

$ cc bf.c -o bf
$ ./bf '++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.'
Hello World!


Конечно, из-за стремления втиснуться в 160 байт пришлось многие вещи переложить на окружение. Более портативная и независимая от окружения версия интерпретатора занимает 170 байт.

s[999],*r=s,*d,c;main(a,b){char*v=1[d=b];for(;c=*v++%93;)for(b=c%7?a&&(c&17?c&1?(*r-=c-44):(r+=c-61):c&2?putchar(*r):(*r=getchar()),0):v;b&&c|a**r;v=d)main(!c,&b-1);d=v;}

Если добавить нормальную табуляцию, то код будет выглядеть так:

  // с пробелами

  s[999], *r=s, *d, c;
  
  main(a, b)
  {
      char *v=1[d=b];
      for(;c = *v++ % 93;)
          for(b = c%7 ? 
                  a &&
                      (c & 17 ? 
                            c & 1 ? 
                                (*r -= c - 44)
                                :(r += c - 61)
                             :c & 2 ?
                                putchar(*r)
                                :(*r = getchar())
                      ,0)
                  :v;
              b&&c | a * *r;
              v=d)
                  main(!c,&b-1);
      d = v;
  }
+75
27 сентября 2010, 15:58
26
alizar 2275,0 G+

комментарии (32)

+1
Coyod #
1 твит == 140 байт…
+1
lolmaus #
А twIP 1.1 — 139 байт.
+8
Murkt #
1 твит == 140 символов. Так как юникод, то 1 символ не равен 1 байту.
0
selitskas #
Весь ASCII, емнип, всунули в однобайтовую зону. Ну а твиттер считает любые символы, а не байты, если на то пошло.
+30
mazy #
Молодец.
Вот бы кто jre в 140 байт обкорнал…
мечты…
+2
ruX #
не 140 конечно, но ОЧЕНЬ мало
www.harbaum.org/till/nanovm/index.shtml
джава машина для контроллера atmega8, даже работает :)
+1
Stepuk #
Код с табуляцией соответствует 170-байтной программе, а не 160-байтной.
+1
xtender #
Codegoooooooolf :)
Я еще вот такую задачку гольфил на с :)
0
tyomitch #
На www.muppetlabs.com/~breadbox/bf/ есть 166-байтный компилятор брейнфака.
0
yelbota #
Президент одобряет.
0
stampoon #
[al@localhost ~]$ cat bf.c
s[999],*r=s,*d,c;main(a,b){char*v=1[d=b];for(;c=*v++%93;)for(b=c%7?a&&(c&17?c&1?(*r-=c-44):(r+=c-61):c&2?putchar(*r):(*r=getchar()),0):v;b&&c|a**r;v=d)main(!c,&b-1);d=v;}
[al@localhost ~]$ cc bf.c -o bf
bf.c:1: предупреждение: data definition has no type or storage class
bf.c: В функции ‘main’:
bf.c:1: предупреждение: в присваивании целое преобразуется в указатель без приведения типа
bf.c:1: предупреждение: при инициализации целое преобразуется в указатель без приведения типа
bf.c:1: предупреждение: несоответствие типов указатель/целое в условном выражении
bf.c:1: предупреждение: несоответствие типов указатель/целое в условном выражении
bf.c:1: предупреждение: несоответствие типов указатель/целое в условном выражении
bf.c:1: предупреждение: в присваивании указатель преобразуется в целое без приведения типа
bf.c:1: предупреждение: несовместимый тип указателя в присваивании
bf.c:1: предупреждение: несовместимый тип указателя в присваивании
[al@localhost ~]$ ./bf '++++++++++[>+++++++>++++++++++>+++>+.'
Ошибка сегментирования
0
Zubchick #
zubchick~ % cc test.c -o bf 17:59
test.c:1: warning: data definition has no type or storage class
test.c: In function ‘main’:
test.c:1: warning: assignment makes pointer from integer without a cast
test.c:1: warning: initialization makes pointer from integer without a cast
test.c:1: warning: pointer/integer type mismatch in conditional expression
test.c:1: warning: pointer/integer type mismatch in conditional expression
test.c:1: warning: pointer/integer type mismatch in conditional expression
test.c:1: warning: assignment makes integer from pointer without a cast
test.c:1: warning: assignment from incompatible pointer type
test.c:1: warning: assignment from incompatible pointer type
zubchick~ % ./bf '++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.'
Hello World!
+1
Nebulosa #
Видимо это не для x64…
+2
squint #
что означает число 93?
+22
kurumpa #
То есть назначение остальных чисел вам понятно?
+5
track13 #
почти то же, что и 42.

Это десятичное представление команд BF в ASCII. 93 это ]
+2
r1der #
Прошу прощения за оффтоп, что значит реализация ip-стека, как его вообще можно реализовать, это ведь просто иерархия протоколов, логическая. Не удивляйтесь глупому вопросу — гуглил, не помогло… Не могли бы вы объснить что тут к чему?
–4
xnike #
Из контекста статьи получается, что IP = Instruction Pointer, соответственно IP-стек = стек вызова.
–2
r1der #
то есть если я правильно вас понимаю то IP в данном случае аналог EIP в асме? и его каким то образом можно изменять?
+2
r1der #
а какже
>> и отвечает на пинги
0
AlexanderYastrebov #
Ну код-то посмотрите там 3 строчки. Конечно никакого стека там нет. Читает пакет из stdin, если ICMP — меняет адреса местами, ставит тип эхо и пишет в stdout.
0
xn__p2a #
Прошу прощения за оффтоп, что значит реализация ip-стека, как его вообще можно реализовать, это ведь просто иерархия протоколов, логическая.
Это вы автора топика спрашиваете?
Нашли кого спросить.
По моим наблюдениям, alizar не является IT-специалистом и, к сожалению, часто постит то, что сам даже не до конца понимает. Увы.

Если вы посмотрите в оригинал статьи, на которую он сослался, то вам станет понятно, что программа twIP (с кодом на C в 139 символов):
— вешается на обработку входящих/исходящих потоков сетевого интерфейса;
— может только отвечать на ping (получать пакеты ICMP echo request и отдавать в ответ пакеты ICMP echo reply);
— не использует сокеты и оперирует голыми пакетами, извлекаемыми из потока;
— написана just for fun;
— в предложенном варианте работает только под FreeBSD, а для работы в Linux нужно делать некоторые добавления в код, которые делают код уже длиннее 140 символов.
+1
entze #
Если не путаю, то самый маленький вирус был 47 байт, и 32 байта который портил файл (заражаемый корд затирался).
–2
Wyrd #
Самый маленький вирус вот (вешает 9х намертво):

cli
jmp $

(это 2 байта в .com)
+9
tyomitch #
Вирус — это самовоспроизводящийся код, а не любая пакость.
–1
Gorthauer87 #
while(fork()) fork()
вешает намертво любой юникс
+3
jerom #
Только в том случае, если не включен лимит на кол-во процессов для пользователя. На машинах «для студентов» обычно включают.
0
pentarh #
Отзыв благодарного пользователя: «С тех пор как я начал использовать f*ckf*ck, мне уже не нужно изливать мою агрессию на техсаппорт!»
+1
diamant #
160 или 170 байт — это исходный код, а не сам интерпретатор!
Скомпилированный файл у меня получился 9053 байта — есть, над чем работать. Например, переписать на ассемблере под ДОС :)
+2
Vladson #
Зачем DOS, лучше под спектрум =)
(вечерком попробую)
0
Adamax #
*Компилятор* bf, написанный на ассемблере. В откомпилированном виде занимает 170 байт.
www.muppetlabs.com/~breadbox/software/tiny/bf.asm.txt

~/tmp$ nasm -f bin -o bf bf.asm
~/tmp$ chmod +x bf
~/tmp$ ./bf < hello.b > hello
~/tmp$ chmod +x hello
~/tmp$ ./hello
Hello World!
0
tyomitch #
уже упомянут выше

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.