在TurboAssembler中编写Brainfuck解释器(编译器)。首先,让我们以高级语言(例如Pascal)构建解释器。
首先,编写一个程序,该程序将使用
+的和作为自己的ascii代码输出一个字符。
因此,我们只需要bf命令
+和
。var data_mem: array[1..10] of integer; // data array command_mem: string; // command array i: integer; // index of command array j: integer; // index of data array begin j:=1; readln(command_mem); for i:=1 to length(command_mem) do begin // in the cycle we process the string if (command_mem[i]='+') then data_mem[j]:= data_mem[j]+1; if (command_mem[i]='.') then write(chr(data_mem[j])); end; end.
bf代码
+++++++++++++++++++++++++++++++++++++++。 会发出
!(符号!的ascii码为33 )。您可以通过
链接确保程序正确。
接下来,用
goto运算符替换operator并添加bf-commands
-<> 。
LABEL prev,next; var data_mem: array[1..10] of integer; command_mem: string; i,j,k: integer; begin j:=1; i:=1; readln(command_mem); prev: if i>length(command_mem) then goto next; if (command_mem[i]='+') then data_mem[j]:= data_mem[j]+1; if (command_mem[i]='-') then data_mem[j]:= data_mem[j]-1; if (command_mem[i]='>') then j:=j+1; if (command_mem[i]='<') then j:=j-1; if (command_mem[i]='.') then write(chr(data_mem[j])); i:=i+1; goto prev; next: for k:=1 to 10 do begin write(data_mem[k]); write(' '); end; end.
ideone.com接下来,让我们添加
[和
]为方括号
[]循环添加另一个变量
i_stor 。
如果当前项目已成功通过
[的检查,
则将 i加载到
i_stor (如果当前项目
大于零)。
通过
右括号的处理(如果
data_mem不
等于零 ),将
右括号的地址从
i_stor加载到
i中 LABEL prev,next; var data_mem: array[1..10] of integer; command_mem: string; i,j,k: integer; i_stor: integer; begin j:=1; i:=1; readln(command_mem); prev: if i>length(command_mem) then goto next; if (command_mem[i]='+') then data_mem[j]:= data_mem[j]+1; if (command_mem[i]='-') then data_mem[j]:= data_mem[j]-1; if (command_mem[i]='>') then j:=j+1; if (command_mem[i]='<') then j:=j-1; if (command_mem[i]='.') then write(chr(data_mem[j])); if (command_mem[i]='[') then begin if data_mem[j]>0 then i_stor:=i; end; if (command_mem[i]=']') then begin if data_mem[j]>0 then begin i:=i_stor; end; end; i:=i+1; goto prev; next: for k:=1 to 10 do begin write(data_mem[k]); write(' '); end; end.
bf代码
+++++ [> + <-]将数字
5传输到相邻的单元格
0 5 0 0 0 0 0 0 0 0ideone.com“ Hello World!” 程序看起来像
ideone.com转到TASM要组织
循环 ,请将循环阶段的数量放入CX寄存器中,然后将
prev标签(将在其上进行转换)放在阶段的末尾-通过命令
循环 mov CX, 28h ; count of the stages of the loop prev: ; label ; do stuff loop prev ; go back to label prev
让我们创建数据数组
data_mem 。
让我们创建命令数组
command_mem 。
数据数组的内容以
1到元素的形式来说明。
在
循环中,将当前符号与符号
+进行比较,如果字符相等,则将当前单元格的值递增
text segment ; bf1.asm assume cs:text, ds:data, ss:stk begin: mov AX,data ; set the data segment mov DS,AX mov DL, command_mem ; load the 1st command in the DL mov CX, 0Ah ; 10 stages prev: cmp DL, '+' ; the cell contains + jne next ; no, go to the label next: mov BL, 00h ; load into BL the index of data_mem inc data_mem[BX] ; yes, we increase the value in the cell by 1 (inc means increment) next: inc i ; go to the next character in the array of commands mov BL, i mov DL, command_mem [BX] loop prev mov AX, 4c00h ; terminate the program int 21h text ends data segment command_mem DB '+', '+', '+', '$' data_mem DB 1,1,1,1,1,1,1,1,1,1,'$' i DB 0 ; command_mem index data ends stk segment stack db 100h dup (0) ; reserve 256 cells stk ends end begin
汇编 (翻译)由命令
tasm.exe bf1.asm执行 。
链接是通过命令
tlink.exe bf1.obj完成的 。
完成执行后,从地址0130开始有
+++命令,然后是数据数组
data_mem ,然后是
TurboDebugger中的变量
i等于
0Ah 。

接下来,添加bf命令
-<>。使用中断
int 21h的功能
02h输出单个字符。
在调用中断之前,将字符代码放入寄存器DL中。
mov AH,2 mov DL, character_code int 21h
让我们完整地编写程序
text segment ; bf2.asm assume cs:text, ds:data, ss:stk begin: mov AX,data ; set the data segment mov DS,AX mov DL, command_mem mov CX, 0Ah prev: cmp DL, '+' jne next mov BL, j inc data_mem[BX] next: cmp DL, '-' jne next1 mov BL, j dec data_mem[BX] next1: cmp DL, '>' jne next2 inc j next2: cmp DL, '<' jne next3 dec j next3: cmp DL, '.' jne next4 mov AH,2 mov BL, j mov DL, data_mem[BX] int 21h next4: inc i mov BL, i mov DL, command_mem [BX] loop prev mov AX, 4c00h ; terminate the program int 21h text ends data segment command_mem DB '+', '>', '+', '+', '$' ; data_mem DB 0,0,0,0,0,0,0,0,0,0,'$' i DB 0 ; command_mem index j DB 0 ; data_mem index data ends stk segment stack db 100h dup (0) ; reserve 256 cells stk ends end begin

该循环如下所示:
如果
command-mem的当前元素不等于
+,则跳至下一个标签
:(否则,执行
+ )
如果
command-mem的当前元素不相等
-则跳转到标签
next1:如果
command-mem的当前元素不等于
>,则跳转到标签
next2:如果
command-mem的当前元素不等于
<,则跳转到标签
next3:如果
command-mem的当前元素不相等
。 然后跳转到标签
next4:在标签
next4:之后
:增加
command_mem的索引并跳转到标签
prev:(循环的开始)
接下来,添加
[和
]添加变量
i_stor如果当前项已成功通过
[的检查,请检查当前
data_mem元素是否为零,如果当前项等于零,则进一步跳转(在下一个标签上);否则,返回0。 否则将
我加载到
i_stor next4: cmp DL, '[' ; the cell contains [ jne next5 ; no, go to the label next5 mov BL, j mov DL, data_mem[BX] cmp DL, 00h ; yes, check current data_mem element for zero jz next5 ; if zero, jump further mov DL, i ; otherwise load i to i_stor mov i_stor, DL next5:
通过
右括号的处理(如果
data_mem不
等于零 ),将
右括号的地址从
i_stor加载到
i中 next5: cmp DL, ']' ; the cell contains ] jne next6 ; no, go to the label next6 mov BL, j mov DL, data_arr[BX] cmp DL, 00h ; yes, check current data_mem element for zero jz next6 ; if zero, jump further mov DL, i_stor ; otherwise load i_stor to i mov i, DL next6:
检查bf代码
++++ [> + <-] text segment ; bf3.asm assume cs:text, ds:data, ss:stk begin: mov AX,data ; set the data segment mov DS,AX mov DL, command_mem mov CX, 50h prev: cmp DL, '+' jne next mov BL, j inc data_mem[BX] next: cmp DL, '-' jne next1 mov BL, j dec data_mem[BX] next1: cmp DL, '>' jne next2 inc j next2: cmp DL, '<' jne next3 dec j next3: cmp DL, '.' jne next4 mov AH,2 mov BL, j mov DL, data_mem[BX] int 21h next4: cmp DL, '[' ; the cell contains [ jne next5 ; no, go to the label next5 mov BL, j mov DL, data_mem[BX] cmp DL, 00 ; yes, check the current data_mem element for zero jz next5 ; if zero, jump further mov DL, i ; otherwise load i to i_stor mov i_stor, DL next5: cmp DL, ']' ; the cell contains ] jne next6 ; no, go to the label next6 mov BL, j mov DL, data_mem[BX] cmp DL, 00 ; yes, check current data_mem element for zero jz next6 ; if zero, jump further mov DL, i_stor ; otherwise load i_stor to i mov i, DL next6: inc i mov BL, i mov DL, command_mem[BX] loop prev mov AX, 4c00h ; terminate the program int 21h text ends data segment command_mem DB '+','+','+','+','[','>','+','<','-',']', '$' data_mem DB 0,0,0,0,0,0,0,0,0,0,'$' i DB 0 ; command_mem index j DB 0 ; data_mem index i_stor DB 0 data ends stk segment stack db 100h dup (0) ; reserve 256 cells stk ends end begin

添加输入功能
3fh中断
21h mov ah, 3fh ; input function mov cx, 100h ; the number of bytes you want to read from the input mov dx,OFFSET command_mem int 21h
当前字符/命令为“ $”时,
循环结束
cmp DL, '$' je exit_loop
将
循环更改为
jmp mov ah, 3fh ; input function mov cx, 100h ; the number of bytes you want to read from input mov dx,OFFSET command_mem int 21h mov DL, command_mem ; load the 1st command in the DL ;mov CX, 100h prev: cmp DL, '$' ; check the current command for '$' je exit_loop ; jump if the check has successfully passed
添加
JUMPS指令。
JUMPS指令启用TASM中的自动条件跳转扩展。 如果条件跳转的目标超出范围,则TASM会将跳转转换为本地跳转/ JMP对。 例如:
JE EQUAL_PLACE becomes: JNE @@A JMP EQUAL_PLACE @@A:
毕竟
JUMPS ; bf4.asm text segment assume cs:text,ds:data, ss: stk begin: mov AX,data mov DS,AX ;;; mov ah, 3fh mov cx, 100h mov dx,OFFSET command_mem int 21h ;;; mov DL, command_mem ;mov CX, 100h prev: cmp DL, '$' je exit_loop cmp DL, '+' jne next mov BL, j inc data_mem[BX] next: cmp DL, '-' jne next1 mov BL, j dec data_mem[BX] next1: cmp DL, '>' jne next2 inc j next2: cmp DL, '<' jne next3 dec j next3: cmp DL, '.' jne next4 mov AH,2 mov BL, j mov DL, data_mem[BX] int 21h next4: cmp DL, '[' jne next5 mov BL, j mov DL, data_mem[BX] cmp DL, 00 jz next5 mov DL, i mov i_stor, DL next5: cmp DL, ']' jne next6 mov BL, j mov DL, data_mem[BX] cmp DL, 00 jz next6 mov DL, i_stor mov i, DL next6: inc i mov BL, i mov DL, command_mem[BX] jmp prev exit_loop: MOV AH,2 MOV DL,0Ah INT 21h mov AX, 4c00h int 21h text ends data segment command_mem DB 256h DUP('$') data_mem DB 0,0,0,0,0,0,0,0,0,0,'$' i DB 0,'$' j DB 0,'$' i_stor DB 0,'$' data ends stk segment para stack db 100h dup (0) stk ends end begin
github.com