Écriture d'un interpréteur Brainfuck (compilateur) dans TurboAssembler.Pour commencer, construisons l'interpréteur dans un langage de haut niveau, par exemple en Pascal.
Pour commencer, écrivez un programme qui produira un caractère en utilisant la somme de
+ comme propre code ascii.
Nous n'avons donc besoin que des commandes bf
+ et
.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-code
++++++++++++++++++++++++++++++++++++. émettra
!(le code ascii du symbole ! est 33 ).Vous pouvez vous assurer que le programme est correct via
le lien .
Ensuite, remplacez l'opérateur par l'opérateur
goto et ajoutez les commandes bf
- <> .
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.comEnsuite, ajoutons
[ et
]Ajoutez une autre variable
i_stor pour la boucle crochet
[] .
Si l'élément actuel a réussi la vérification de
[ , chargez
i dans
i_stor (si l'élément actuel est
supérieur à zéro).
Par le traitement de la parenthèse fermante
] (si le
data_mem n'est pas égal à
zéro ) charger l'adresse de la parenthèse ouvrante
[ dans
i depuis
i_stor 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.
code bf
+++++ [> + <-] transfère le nombre
5 à la cellule voisine
0 5 0 0 0 0 0 0 0 0ideone.comUn «Bonjour tout le monde!» le programme ressemble à
ideone.comPasser à TASMPour organiser la
boucle, mettez le nombre d'étages de boucle dans le registre CX, puis mettez l'étiquette
prev: (sur laquelle la transition sera effectuée) à la fin de l'étape - par la
boucle de commande
mov CX, 28h ; count of the stages of the loop prev: ; label ; do stuff loop prev ; go back to label prev
Créons le tableau de données
data_mem .
Créons le tableau de commandes
command_mem .
Contenu du tableau de données avec
1 à illustratif à mesure que les éléments ressemblent.
Dans la
boucle, comparez le symbole actuel avec le symbole
+ et, si les caractères sont égaux, incrémentez la valeur de la cellule actuelle
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
L'assemblage (traduction) est effectué par la commande
tasm.exe bf1.asm .
La liaison est effectuée avec la commande
tlink.exe bf1.obj .
Au fur et à mesure de l'exécution, il y a des commandes
+++ à partir de l'adresse 0130, puis vient le tableau de données
data_mem , puis vient la variable
i égale à
0Ah dans le
TurboDebugger .

Ensuite, ajoutez les commandes bf
- <>.Utilisez la fonction
02h de l'interruption
int 21h pour sortir un seul caractère.
Mettez le code de caractère dans le registre DL avant d'appeler l'interruption.
mov AH,2 mov DL, character_code int 21h
Écrivons le programme entièrement
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

Le cycle fonctionne comme ceci:
si l'élément courant de la
commande-mem n'est pas égal à
+, passez à l'étiquette
suivante: (sinon, effectuez
+ )
si l'élément courant de la
commande-mem n'est pas égal
- alors
passez à l'étiquette
suivante1:si l'élément courant de la
commande-mem n'est pas égal
> alors
passez à l'étiquette
next2:si l'élément courant de la
commande-mem n'est pas égal à
< alors
passez à l'étiquette
suivante3:si l'élément actuel de
command-mem n'est pas égal
. puis
passez à l'étiquette
next4:Après le label
next4: incrémentez l'index du
command_mem et
passez au label
prev: (le début du cycle)
Ensuite, ajoutez
[ et
]Ajoutez la variable
i_storSi l'élément actuel a réussi la vérification
[ , vérifiez l'élément
data_mem actuel pour zéro, et, si l'élément actuel est égal à zéro, sautez plus loin (sur l'étiquette suivante); sinon chargez
i dans
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:
Par le traitement de la parenthèse fermante
] (si le
data_mem n'est pas égal à
zéro ) charger l'adresse de la parenthèse ouvrante
[ dans
i depuis
i_stor 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:
Vérifiez le code 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

Ajouter la fonction d'entrée
3fh interruption
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
la
boucle est terminée lorsque le caractère / la commande en cours est '$'
cmp DL, '$' je exit_loop
Changer la
boucle en
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
Ajoutez la directive
JUMPS .
La directive JUMPS permet l'extension automatique de saut conditionnel dans TASM. Si la cible d'un saut conditionnel est hors de portée, TASM convertit le saut en une paire saut local / JMP. Par exemple:
JE EQUAL_PLACE becomes: JNE @@A JMP EQUAL_PLACE @@A:
Après tout
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