Интерпретатор Brainfuck на Ассемблере
Интерпретатор Brainfuck на Ассемблере
Если вы увлекаетесь программированием, то скорее всего слышали об эзотерическом языке программирования Brainfuck. Дословно его название переводится на русский язык как "мозгоёбка", но в приличном обществе его обычно сглаживают до "вынос мозга". Язык имеет всего восемь команд, каждая из которых записывается одним символом. В полном соответствии с названием, программы на Brainfuck трудно не только читать, но и писать, поскольку они представляют собой последовательность символов-команд без какого-либо дополнительного синтаксиса. Несмотря на это, Brainfuck является полноценной машиной Тьюринга, и поэтому может выполнять любые вычислительные задачи. Ветераны реверса наверняка помнят KeygenMe от легендарного Ms-Rem, в котором алгоритм проверки ключа был спрятан внутри виртуальной машины на Brainfuck.
Дело было вечером,
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------------
- ; Интерпретатор языка Brainfuck
- ; Автор: ManHunter / PCL (www.manhunter.ru)
- ;------------------------------------------------------------------
- ; Параметры:
- ; lpSource - текст программы на Brainfuck
- ; lpInput - строка для посимвольной передачи ее программе
- ; lpOutput - буфер для записи результатов работы программы
- ;------------------------------------------------------------------
- ; На выходе:
- ; EAX = 0 - программа выполнена успешно
- ; EAX = -1 - ошибка синтаксиса,
- ; EDX -> позиция ошибочной команды в строке
- ; EAX = -2 - ошибка выполнения,
- ; EDX -> позиция ошибочной команды в строке
- ;------------------------------------------------------------------
- proc Brainfuck lpSource:DWORD, lpInput:DWORD, lpOutput:DWORD
- BRAINFUCK_MEM_LENGTH=30000
- locals
- hHeap dd ?
- mem dd ?
- endl
- ; Выделить память
- invoke GetProcessHeap
- mov [hHeap],eax
- invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,BRAINFUCK_MEM_LENGTH
- mov [mem],eax
- ; Проверить правильность расстановки циклов
- mov esi,[lpSource]
- cld
- xor ecx,ecx
- .scan_loop:
- lodsb
- or al,al
- jz .scan_loop_done
- cmp al,'['
- jne @f
- inc ecx
- jmp .scan_loop
- @@:
- cmp al,']'
- jne .scan_loop
- or ecx,ecx
- je .loc_syntax_error
- dec ecx
- jmp .scan_loop
- .scan_loop_done:
- or ecx,ecx
- jnz .loc_syntax_error
- ; Выполнить код
- mov esi,[lpInput]
- mov edi,[lpOutput]
- ; Указатель на текущую команду
- mov edx,[lpSource]
- ; Указатель на текущую ячейку памяти
- xor ebx,ebx
- .loc_loop:
- mov al,[edx]
- or al,al
- jz .loc_success
- ; Перейти к следующей ячейке
- cmp al,'>'
- jne .loc_1
- inc ebx
- ; Выход за пределы памяти
- cmp ebx,BRAINFUCK_MEM_LENGTH
- je .loc_runtime_error
- inc edx
- jmp .loc_loop
- .loc_1:
- ; Перейти к предыдущей ячейке
- cmp al,'<'
- jne .loc_2
- ; Выход за пределы памяти
- cmp ebx,0
- je .loc_runtime_error
- dec ebx
- inc edx
- jmp .loc_loop
- .loc_2:
- ; Увеличить значение в текущей ячейке на 1
- cmp al,'+'
- jne .loc_3
- mov eax,[mem]
- inc byte [eax+ebx]
- inc edx
- jmp .loc_loop
- .loc_3:
- ; Уменьшить значение в текущей ячейке на 1
- cmp al,'-'
- jne .loc_4
- mov eax,[mem]
- dec byte [eax+ebx]
- inc edx
- jmp .loc_loop
- .loc_4:
- ; Напечатать значение из текущей ячейки
- cmp al,'.'
- jne .loc_5
- mov eax,[mem]
- mov al,[eax+ebx]
- stosb
- inc edx
- jmp .loc_loop
- .loc_5:
- ; Ввести извне значение и сохранить в текущей ячейке
- cmp al,','
- jne .loc_6
- mov al,byte [esi]
- or al,al
- jz @f
- inc esi
- @@:
- mov ecx,[mem]
- mov [ecx+ebx],al
- inc edx
- jmp .loc_loop
- .loc_6:
- ; Если значение текущей ячейки ноль, перейти вперед по тексту
- ; программы на ячейку, следующую за соответствующей ] (с учетом
- ; вложенности)
- cmp al,'['
- jne .loc_7
- xor ecx,ecx
- inc ecx
- mov eax,[mem]
- cmp byte [eax+ebx],0
- je .loc_6_1
- inc edx
- jmp .loc_loop
- .loc_6_1:
- inc edx
- mov al,[edx]
- cmp al,'['
- jne @f
- inc ecx
- @@:
- cmp al,']'
- jne .loc_6_1
- dec ecx
- or ecx,ecx
- jnz .loc_6_1
- inc edx
- jmp .loc_loop
- .loc_7:
- ; Если значение текущей ячейки не нуль, перейти назад по тексту
- ; программы на символ [ (с учетом вложенности)
- cmp al,']'
- jne .loc_8
- xor ecx,ecx
- inc ecx
- mov eax,[mem]
- cmp byte [eax+ebx],0
- jne .loc_7_1
- inc edx
- jmp .loc_loop
- .loc_7_1:
- dec edx
- mov al,[edx]
- cmp al,']'
- jne @f
- inc ecx
- @@:
- cmp al,'['
- jne .loc_7_1
- dec ecx
- or ecx,ecx
- jnz .loc_7_1
- jmp .loc_loop
- .loc_8:
- ; Команда не опознана, пропустить
- inc edx
- jmp .loc_loop
- .loc_syntax_error:
- sub esi,[lpSource]
- mov edx,esi
- mov eax,-2
- jmp .loc_ret
- .loc_runtime_error:
- sub edx,[lpSource]
- inc edx
- mov eax,-1
- jmp .loc_ret
- .loc_success:
- xor eax,eax
- .loc_ret:
- ; Очистить выделенную память
- push eax edx
- invoke HeapFree,[hHeap],NULL,[mem]
- pop edx eax
- ret
- endp
Параметры вызова: lpSource - указатель на строку, содержащую текст программы на Brainfuck. В программе кроме команд Brainfuck могут быть любые символы, при обработке они просто будут игнорироваться. lpInput - указатель на строку, которая будет посимвольно передаваться программе по команде ",". При достижении конца строки на запрос программы будет передаваться нулевой символ. lpOutput - указатель на буфер, в который будут записываться все символы, выводимые командой "." из программы. Размеры буфера в интерпретаторе не проверяются, об этом вы должны позаботиться сами.
В приложении пример программы-оболочки с исходным текстом, использующей интерпретатор Brainfuck.
Просмотров: 3198 | Комментариев: 4
Метки: Assembler
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Vnv
(25.07.2017 в 18:45):
Dimka, есть отладчик онлайн, там все видно: https://fatiherikli.github.io/...-visualizer/
ManHunter
(25.07.2017 в 14:16):
Не Syntax error, а Runtime error at: 46
Выход указателя за границы памяти [0..30000]
Выход указателя за границы памяти [0..30000]
Dimka
(25.07.2017 в 14:08):
Привет ) Вот это некропост с краклаба ты откопал ))
Пишу вот так:
>--[+++++++<---->>-->+>+>+<<<<]
<.>++++[-<++++<++>>>->--<<]>>-.> ;--..>+.<<<.<<-.>>+>->>.+++[.<]< ;<++.
Выдаёт Syntax error at: 46 - что не так ?
Пишу вот так:
>--[+++++++<---->>-->+>+>+<<<<]
<.>++++[-<++++<++>>>->--<<]>>-.> ;--..>+.<<<.<<-.>>+>->>.+++[.<]< ;<++.
Выдаёт Syntax error at: 46 - что не так ?
Добавить комментарий
Заполните форму для добавления комментария
Походу гитхаб убил сайт. Альтернативная ссылка: https://copy.sh/brainfuck/