Brainfuck de bajo nivel

Escribir un intérprete Brainfuck (compilador) en TurboAssembler.

Para empezar, construyamos el intérprete en un lenguaje de alto nivel, por ejemplo, en Pascal.

Para comenzar, escriba un programa que genere un carácter usando la suma de + como propio código ascii.

Entonces, solo necesitamos los comandos bf + y .

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. 

código bf +++++++++++++++++++++++++++++++++++. emitirá !
(¡el código ascii del símbolo ! es 33 ).

Puede asegurarse de que el programa sea correcto a través del enlace .

Luego, reemplace para operador con goto operator y agregue los comandos 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.com

A continuación, agreguemos [ y ]

Agregue otra variable i_stor para el bucle bracket [] .

Si el elemento actual ha pasado con éxito la comprobación de [ , cargue i en i_stor (si el elemento actual es mayor que cero).

Mediante el procesamiento del corchete de cierre ] (si data_mem no es igual a cero ) cargue la dirección del corchete de apertura [ en i desde 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. 

bf-code +++++ [> + <-] transfiere el número 5 a la celda vecina 0 5 0 0 0 0 0 0 0 0

ideone.com

Un "¡Hola Mundo!" el programa se parece a ideone.com

Pasando a TASM

Para organizar el bucle, coloque el número de etapas del bucle en el registro CX, luego coloque la etiqueta anterior: (en la que se realizará la transición) al final de la etapa - mediante el bucle de comando

 mov CX, 28h ; count of the stages of the loop prev: ; label ; do stuff loop prev ; go back to label prev 


Creemos la matriz de datos data_mem .
Creemos el comando array command_mem .
Contenido de la matriz de datos con 1 para ilustrar como se ven los elementos.

En el bucle, compare el símbolo actual con el símbolo + y, si los caracteres son iguales, incremente el valor de la celda actual

 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 

El ensamblaje (traducción) se realiza mediante el comando tasm.exe bf1.asm .

La vinculación se realiza con el comando tlink.exe bf1.obj .

A medida que se realiza la ejecución, hay comandos +++ a partir de la dirección 0130, luego viene la matriz de datos data_mem , luego viene la variable i igual 0Ah en el TurboDebugger .



A continuación, agregue los comandos bf - <>.
Use la función 02h de la interrupción int 21h para generar un solo carácter.
Ponga el código de caracteres en el registro DL antes de llamar a la interrupción.

  mov AH,2 mov DL, character_code int 21h 

Escribamos el programa completamente

 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 



El ciclo funciona así:

si el elemento actual de command-mem no es igual a + , salte a la etiqueta siguiente: (de lo contrario, realice + )
si el elemento actual de command-mem no es igual , salte a la etiqueta next1:
si el elemento actual de command-mem no es igual > salte a la etiqueta next2:
si el elemento actual de command-mem no es igual < entonces salte a la etiqueta next3:
si el elemento actual de command-mem no es igual . luego salta a la etiqueta next4:
Después de la etiqueta next4: incremente el índice de command_mem y salte a la etiqueta anterior: (el comienzo del ciclo)

A continuación, agregue [ y ]
Agregue la variable i_stor
Si el elemento actual ha pasado con éxito la verificación de [ , verifique el elemento data_mem actual para cero y, si el elemento actual es igual a cero, salte más lejos (en la siguiente etiqueta); de lo contrario, cargue i en 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: 

Mediante el procesamiento del corchete de cierre ] (si data_mem no es igual a cero ) cargue la dirección del corchete de apertura [ en i desde 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: 

Verifique el código 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 



Agregue la función de entrada 3fh interrupción 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 

el ciclo finaliza cuando el carácter / comando actual es '$'

 cmp DL, '$' je exit_loop 

Cambiar bucle a 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 

Agregue la directiva JUMPS .
La directiva JUMPS permite el salto condicional automático que se extiende en TASM. Si el objetivo de un salto condicional está fuera de rango, TASM convierte el salto en un par de salto local / JMP. Por ejemplo:

  JE EQUAL_PLACE becomes: JNE @@A JMP EQUAL_PLACE @@A: 


Despues de todo

 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

Source: https://habr.com/ru/post/es428644/


All Articles