Parte IParte IIParte IIINeste artigo, escreveremos um compilador Brainfuck no TurboAssembler
Aqui você pode depurar os programas bf em um modo passo a passo.
Primeiro, escreveremos o intérprete em alguma linguagem de alto nível, por exemplo, em Pascal.
A matriz 
data_arr representará a memória de dados, a string 
str_arr conterá os comandos.
Escreveremos um programa que exibe um caractere cujo código ascii corresponde ao número 
+ (portanto, precisamos apenas dos comandos 
+ e 
. )
var data_arr:array[1..10] of integer; //   str_arr: string; //  i, j: integer; //     begin j:=1; //       readln(str_arr); //  for i:=1 to length(str_arr) do begin //     if (str_arr[i]='+') then data_arr[j]:= data_arr[j]+1; if (str_arr[i]='.') then write(chr(data_arr[j])); end; end. 
código bf +++++++++++++++++++++++++++++++++++. vai desistir 
! (o código ascii do personagem 
! é 33).
O programa pode ser verificado no site ide 
ideone.comEm seguida, substitua o loop 
for por 
goto e adicione os comandos 
No final, produziremos a matriz 
data_arr LABEL prev,next; var data_arr:array[1..10] of integer; //   str_arr: string; //  i,j,k: integer; //     begin i:=1; j:=1; readln(str_arr); //  prev: if i>length(str_arr) then goto next; if (str_arr[i]='+') then data_arr[j]:= data_arr[j]+1; if (str_arr[i]='-') then data_arr[j]:= data_arr[j]-1; if (str_arr[i]='>') then j:=j+1; if (str_arr[i]='<') then j:=j-1; if (str_arr[i]='.') then write(chr(data_arr[j])); i:=i+1; goto prev; next: for k:=1 to 10 do begin write(data_arr[k]); write(' '); end; end. 
Código 
dará 1 2 3 0 0 0 0 0 0 0
Código 
dará 1 2 2 0 0 0 0 0 0 0
ideone.comEm seguida, adicione 
[ e 
]Adicione outra variável 
i_stor .
Se o elemento atual passou no teste em 
[ , então verificamos o elemento atual da matriz 
data_arr como zero e, se o elemento for maior que zero, carregue o valor da variável 
i no 
i_stor .
Ao processar o colchete de fechamento 
] , se 
data_arr não 
for zero, carregaremos o endereço do colchete de abertura na variável 
i da variável 
i_stor [Em seguida, vá para o comando 
i: = i + 1;Se antes disso um valor de 
i_stor foi carregado em 
i (durante a verificação 
) ), depois do despejo estaremos em 
[ (caso contrário estaremos em 
] )
 LABEL prev,next; var data_arr:array[1..10] of integer; //   str_arr: string; //  i,j,k: integer; //     i_stor: integer; begin j:=1; i:=1; readln(str_arr); //  prev: if i>length(str_arr) then goto next; if (str_arr[i]='+') then data_arr[j]:= data_arr[j]+1; if (str_arr[i]='-') then data_arr[j]:= data_arr[j]-1; if (str_arr[i]='>') then j:=j+1; if (str_arr[i]='<') then j:=j-1; if (str_arr[i]='.') then write(chr(data_arr[j])); if (str_arr[i]='[') then begin if data_arr[j]>0 then i_stor:=i; end; if (str_arr[i]=']') then begin if data_arr[j]>0 then begin i:=i_stor; end; end; i:=i+1; goto prev; next: for k:=1 to 10 do begin write(data_arr[k]); write(' '); end; end. 
Código 
transfere o número 5 para a próxima célula 0 5 0 0 0 0 0 0 0 0 0
ideone.comO código HelloWorld se parece com 
ideone.comVamos para o assembler
Para organizar um loop (loop), é necessário colocar o número de ciclos de clock no registro CX e colocar um rótulo para o qual a transição será feita no final do ciclo (pelo comando loop).
 mov CX, 28h ; -   prev: ;   ;  ;  ;   loop prev ;    prev 
Crie uma matriz de comandos 
str_arr , coloque lá 
Crie um array de dados 
data_arr , (para maior clareza) coloque lá 1,1,1,1,1,1,1,1,1,1,1,1
Em um loop, compare o caractere atual com o caractere 
e, se os caracteres forem iguais, aumente o valor na célula atual em 1.
 text segment ; bf1.asm assume cs:text, ds:data, ss:stk begin: ;   mov AX,data ;    mov DS,AX mov DL, str_arr ;   DL 1  mov CX, 0Ah ; 10  prev: cmp DL, 2Bh ;   + jne next ; ,    next mov BL, 00h ;   BL  inc data_arr[BX] ; ,      1 next: inc i ;       mov BL, i mov DL, str_arr [BX] loop prev mov AX, 4c00h ;   int 21h text ends data segment str_arr DB 2Bh,2Bh,2Bh,'$' ;  +++ data_arr DB 1,1,1,1,1,1,1,1,1,1,'$' ;  i DB 0 ;    data ends stk segment stack db 100h dup (0) ;  256  stk ends end begin 
A montagem (tradução) é realizada pelo 
comando tasm.exe bf1.asmA vinculação é feita pelo 
tlink.exe bf1.objDepois de executar o programa no depurador TurboDebagger, você pode ver que a partir do endereço 0130, os comandos estão localizados 
A seguir, é a matriz de dados na qual alteramos o primeiro elemento, depois a variável 
i , que após a execução do loop se torna igual a 0Ah.

Adicionar comandos 
Para gerar um único caractere usando a função de interrupção 
02h int 21h , é necessário (antes de chamar a interrupção) colocar o código do caractere no registro 
DL .
  mov AH,2 mov DL,   int 21h 
Vamos escrever o programa inteiro
 text segment ; bf2.asm assume cs:text,ds:data, ss:stk begin: ;   mov AX,data ;    mov DS,AX mov DL, str_arr ;   DL 1  mov CX, 0Ah ; 10  prev: cmp DL, 2Bh ;   + jne next ; ,    next mov BL, j ;   BL   inc data_arr[BX] ; ,      1 next: cmp DL, 2Dh ;   - jne next1 ; ,    next1 mov BL, j dec data_arr[BX] next1: cmp DL, 3Eh ;   > jne next2 ; ,    next2 inc j ; ,      data_arr next2: cmp DL, 3Ch ;   < jne next3 ; ,    next3 dec j ; ,      data_arr next3: cmp DL, 2Eh ;   . jne next4 ; ,    next4 mov AH,2 ; ,    mov BL, j mov DL, data_arr[BX] int 21h next4: inc i ;       mov BL, i mov DL, str_arr [BX] loop prev mov AX, 4c00h ;   int 21h text ends data segment str_arr DB 2Bh,3Eh,2Bh,2Bh,'$' ;  +>++ data_arr DB 0,0,0,0,0,0,0,0,0,0,'$' ;  i DB 0, '$' ;    j DB 0, '$' ;    data ends stk segment stack db 100h dup (0) ;  256  stk ends end begin 

O loop funciona assim:
se o elemento atual de 
str_arr não 
for depois pule para o 
próximo rótulo 
: (caso contrário, execute 
)
se o elemento atual de 
str_arr não 
for então pule para o rótulo 
next1:se o elemento atual de 
str_arr não 
for então pule para o rótulo 
next2:se o elemento atual de 
str_arr não 
for então pule para o rótulo 
next3:se o elemento atual de 
str_arr não 
for então pule para o rótulo 
next4:Após o rótulo 
next4: aumente o índice da string 
str_arr e pule para o início do loop - para o label 
anterior:Em seguida, adicione 
[ e 
]Adicione a variável 
i_stor .
Se o elemento atual passou no teste em 
[ , então verificamos o elemento atual da matriz 
data_arr para zero e, se o elemento é zero, saltamos mais (para o próximo rótulo); caso contrário, carregamos o valor da variável 
i no 
i_stor .
 next4: cmp DL, 5Bh ;   [ jne next5 ; ,    next5 mov BL, j mov DL, data_arr[BX] cmp DL, 00 ; ,    data_arr   jz next5 ;  ,   mov DL, i ;   mov i_stor, Dl ;  i_stor   i next5: 
Ao processar o colchete de fechamento 
] , se 
data_arr não 
for zero, carregue o endereço do colchete de abertura na variável 
i da variável 
i_stor [ next5: cmp DL, 5Dh ;   ] jne next6 ; ,    next6 mov BL, j mov DL, data_arr[BX] cmp DL, 00 ; ,    data_arr   jz next6 ;  ,   mov DL, i_stor ;   mov i, Dl ;  i_stor   i next6: 
Verifique o código 
 text segment ; bf4.asm assume cs:text, ds:data, ss:stk begin: ;   mov AX,data ;    mov DS,AX mov DL, str_arr ;   DL 1  mov CX, 50h ; 80  prev: cmp DL, 2Bh ;   + jne next ; ,    next mov BL, j ;   BL   inc data_arr[BX] ; ,      1 next: cmp DL, 2Dh ;   - jne next1 ; ,    next1 mov BL, j dec data_arr[BX] ;BX,   Bl next1: cmp DL, 3Eh ;   > jne next2 ; ,    next2 inc j ; ,      data_arr next2: cmp DL, 3Ch ;   < jne next3 ; ,    next3 dec j ; ,      data_arr next3: cmp DL, 2Eh ;   . jne next4 ; ,    next4 mov AH,2 ; ,    mov BL, j mov DL, data_arr[BX] int 21h next4: cmp DL, 5Bh ;   [ jne next5 ; ,    next5 mov BL, j mov DL, data_arr[BX] cmp DL, 00 ; ,    data_arr   jz next5 ;  ,   mov DL, i ;   mov i_stor, Dl ;  i_stor   i next5: cmp DL, 5Dh ;   ] jne next6 ; ,    next6 mov BL, j mov DL, data_arr[BX] cmp DL, 00 ; ,    data_arr   jz next6 ;  ,   mov DL, i_stor ;   mov i, Dl ;  i_stor   i next6: inc i ;     mov BL, i mov DL, str_arr[BX] loop prev ;    prev: mov AX, 4c00h ;   int 21h text ends data segment str_arr DB 2Bh,2Bh,2Bh,2Bh,5Bh, 3Eh,2Bh,3Ch,2Dh ,5Dh, '$' ;  ++++[>+<-] data_arr 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 stack db 100h dup (0) ;  256  stk ends end begin 

Adicionar função à linha de entrada 
3fh interromper 
21h  mov ah, 3fh ;   mov cx, 100h ; 256  mov dx,OFFSET str_arr int 21h 
Sairemos do loop após atingir o final da string 
'$' .
Para fazer isso, compararemos o caractere atual com o caractere 
'$' cmp DL, 24h ;  '$' je exit_loop 
Substitua o loop do loop pelo comando jmp.
 text segment assume cs:text,ds:data, ss: stk begin: ;   mov AX,data ;    mov DS,AX ;   mov ah, 3fh mov cx, 100h ; 256  mov dx,OFFSET str_arr int 21h ; mov DL, str_arr ;   DL 1  ;mov CX, 100h ; 256  prev: cmp DL, 24h ;    '$' je exit_loop cmp DL, 2Bh ;   + jne next ; ,    next mov BL, j ;   BL   inc data_arr[BX] ; ,      1 next: cmp DL, 2Dh ;   - jne next1 ; ,    next1 mov BL, j dec data_arr[BX] ;BX,   Bl next1: cmp DL, 3Eh ;   > jne next2 ; ,    next2 inc j ; ,      data_arr next2: cmp DL, 3Ch ;   < jne next3 ; ,    next3 dec j ; ,      data_arr next3: cmp DL, 2Eh ;   . jne next4 ; ,    next4 mov AH,2 ; ,    mov BL, j mov DL, data_arr[BX] int 21h next4: cmp DL, 5Bh ;   [ jne next5 ; ,    next5 mov BL, j mov DL, data_arr[BX] cmp DL, 00 ; ,    data_arr   jz next5 ;  ,   mov DL, i ;   mov i_stor, Dl ;  i_stor   i next5: cmp DL, 5Dh ;   ] jne next6 ; ,    next6 mov BL, j mov DL, data_arr[BX] cmp DL, 00 ; ,    data_arr   jz next6 ;  ,   mov DL, i_stor ;   mov i, Dl ;  i_stor   i ;       prev: next6: inc i ;     mov BL, i mov DL, str_arr[BX] ; loop prev ;    prev: jmp prev exit_loop: MOV AH,2 ;     MOV DL,0Ah INT 21h mov AX, 4c00h ;   int 21h text ends data segment str_arr DB 256h DUP('$') ;   256  data_arr 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) ;  256  stk ends end begin 
Durante a compilação, obtemos um erro
Salto relativo fora do intervalo em 0001h bytes
O fato é que os comandos 
je / jne podem saltar apenas após algumas linhas do programa (cada linha ocupa de 1 a 5 bytes na memória).

Saltos longos até o final do programa 
je / jne não podem ser feitos.
Portanto, substituímos a expressão
  cmp DL, 24h ;  '$' je exit_loop ... exit_loop: 
expressão
 cmp DL, 24h ;  '$' jne exit_ jmp exit_loop exit_ ... exit_loop: 
Portanto, se o caractere atual corresponder a 
$ , vá para o label 
exit_loop: com o comando 
jmp , caso contrário, 
pularemos o comando 
jmp .
O comando 
jmp pode fazer uma transição 
curta relativa intra-segmento (transição menor que 128 bytes, ou seja, IP: = IP + i8) ou uma 
transição longa relativa intra-segmento (transição menor que 327 bytes, ou seja, IP: = IP + i16).
Por padrão, o comando 
jmp faz um salto em distância relativo, que é o que precisamos (em geral, você pode simplesmente adicionar a diretiva jumps ao início do programa).
 ;jumps text segment assume cs:text,ds:data, ss: stk begin: ;   mov AX,data ;    mov DS,AX ;;; mov ah, 3fh ;   mov cx, 100h ; 256  mov dx,OFFSET str_arr int 21h ;;; mov DL, str_arr ;   DL 1  ;mov CX, 100h ; 256  prev: cmp DL, 24h ;  '$' ;je exit_loop jne l1 jmp SHORT exit_loop l1: cmp DL, 2Bh ;   + jne next ; ,    next mov BL, j ;   BL   inc data_arr[BX] ; ,      1 next: cmp DL, 2Dh ;   - jne next1 ; ,    next1 mov BL, j dec data_arr[BX] ;BX,   Bl next1: cmp DL, 3Eh ;   > jne next2 ; ,    next2 inc j ; ,      data_arr next2: cmp DL, 3Ch ;   < jne next3 ; ,    next3 dec j ; ,      data_arr next3: cmp DL, 2Eh ;   . jne next4 ; ,    next4 mov AH,2 ; ,    mov BL, j mov DL, data_arr[BX] int 21h next4: cmp DL, 5Bh ;   [ jne next5 ; ,    next5 mov BL, j mov DL, data_arr[BX] cmp DL, 00 ; ,    data_arr   jz next5 ;  ,   mov DL, i ;   mov i_stor, Dl ;  i_stor   i next5: cmp DL, 5Dh ;   ] jne next6 ; ,    next6 mov BL, j mov DL, data_arr[BX] cmp DL, 00 ; ,    data_arr   jz next6 ;  ,   mov DL, i_stor ;   mov i, Dl ;  i_stor   i ;       prev: next6: inc i ;     mov BL, i mov DL, str_arr[BX] ; loop prev ;    prev: jmp prev exit_loop: MOV AH,2 ;     MOV DL,0Ah INT 21h mov AX, 4c00h ;   int 21h text ends data segment str_arr DB 256h DUP('$') ;   256  data_arr 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) ;  256  stk ends end begin 
Link para o github com listas de programas.
PS Aqui está 
um artigo sobre a criação de uma calculadora de notação polonesa reversa x86 (RPN).