Ham62

BFI86 v0.1

Jun 5th, 2021
641
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; -----------------------------------------------------
  2. ; Brainfuck Interpreter 86
  3. ;
  4. ; A simple Brainfuck interpreter written entirely in 8086
  5. ; assembler for MS-DOS 2.0+
  6. ;
  7. ; To execute a BF program, just type "BFI86 file.bf"
  8. ; and it will begin running immediately.
  9. ;
  10. ; Written by Graham Downey (2021)
  11.  
  12. CPU 8086
  13. ORG 100h
  14.  
  15. %define SRC_BUFF_SZ 32768
  16.  
  17. section .text
  18.  
  19. start:
  20.     XOR BX, BX    ; Make cmd line arguments NULL terminated
  21.     MOV BL, [80h] ; 80h is length of cmd line arguments in PSP
  22.     MOV BYTE [BX + 81h], 00h
  23.  
  24. openFile:
  25.     MOV AX, DS    ; DS=ES=CS=SS
  26.     MOV ES, AX
  27.  
  28.     MOV AL, ' '   ; Skip all spaces at start of cmd line
  29.     MOV DI, 81h
  30.     MOV CL, [80h] ; Max length of search loop
  31.     INC CL        ; since [80h] is length excluding CR
  32.     XOR CH, CH
  33.  
  34.     REPZ SCASB
  35.     JCXZ .noParameter ; No parameters passed
  36.  
  37.     MOV AX, 3D02h ; Open file read/write
  38.     DEC DI        ; DI is 1 past start of string
  39.     MOV DX, DI
  40.     INT 21h
  41.    
  42.     JC .openError
  43.  
  44.     MOV [hSrcFile], AX ; Store file handle
  45.  
  46.     JMP loadFile
  47.  
  48. .noParameter:
  49.     LEA DX, [sNoParameter] ; Show no parameters passed
  50.     MOV AH, 09h
  51.     INT 21h
  52.  
  53.     JMP end    
  54.  
  55. .openError:
  56.     LEA DX, [sOpenFailed] ; Show error
  57.     MOV AH, 09h
  58.     INT 21h
  59.  
  60.     MOV AH, 40h  ; print file name
  61.     MOV BX, 1    ; File handle 1 is STDOUT
  62.     MOV CX, DI   ; Calculate length of filename
  63.     DEC CX
  64.     SUB CX, 80h
  65.     SUB CL, [80h]
  66.     NEG CL
  67.     MOV DX, DI
  68.     INT 21h
  69.  
  70.     MOV AH, 02h  ; print closing quote
  71.     MOV DL, "'"
  72.     INT 21h    
  73.  
  74.     JMP end
  75.  
  76.  
  77.  
  78. loadFile:
  79.     MOV BX, AX           ; BX = file handle
  80.     LEA DX, [sourceBuff] ; DS:DX = dest buffer
  81.     MOV CX, SRC_BUFF_SZ  ; Read source into buffer
  82.     MOV AH, 3Fh
  83.     INT 21h              ; Read data from source file
  84.  
  85.     MOV [srcFileLen], AX ; Store length of source file
  86.  
  87.     MOV BX, AX           ; Put EOF at end of source
  88.     ADD BX, sourceBuff
  89.     MOV [BX], BYTE 26
  90.  
  91.     JNC runProgram       ; No error? Start running prog
  92.  
  93. .readError:
  94.     LEA DX, [sReadFailed] ; Show error
  95.     MOV AH, 09h
  96.     INT 21h
  97.  
  98.     JMP end    
  99.  
  100.  
  101. ; ======== Main program execution ========
  102.  
  103. runProgram:
  104.     MOV AH, 40h ; Echo source to screen
  105.     MOV BX, 1
  106.     MOV CX, [srcFileLen]
  107.     LEA DX, [sourceBuff]
  108.     INT 21h
  109.  
  110.     MOV AH, 02h ; Send \r\n
  111.     MOV DL, 13
  112.     INT 21h
  113.     MOV DL, 10
  114.     INT 21h
  115.     ;JMP end
  116.  
  117.     LEA DI, [bfMemory]     ; Initalize BF memory buffer
  118.     MOV CX, 30000/2
  119.     MOV AX, 0000h
  120.     CLD
  121.     REP STOSW
  122.  
  123.     LEA SI, [sourceBuff-1] ; Source code ptr
  124.     LEA DI, [bfMemory]     ; BF Memory ptr
  125.  
  126. nextCommand:
  127.     INC SI
  128.     MOV AL, [SI]
  129.  
  130.     CMP AL, '>'
  131.     JE incPtr
  132.  
  133.     CMP AL, '<'
  134.     JE decPtr
  135.  
  136.     CMP AL, '+'
  137.     JE incData
  138.  
  139.     CMP AL, '-'
  140.     JE decData
  141.  
  142.     CMP AL, '['
  143.     JE loopStart
  144.  
  145.     CMP AL, ']'
  146.     JE loopEnd
  147.  
  148.     CMP AL, ','
  149.     JE readChar
  150.  
  151.     CMP AL, '.'
  152.     JE writeChar
  153.  
  154.     CMP AL, 26 ; EOF
  155.     JE end
  156.  
  157.     JMP nextCommand
  158.  
  159. incPtr:
  160.     INC DI
  161.     CMP DI, bfMemEnd ; Check for buffer overrun
  162.     JGE errMemOver
  163.  
  164.     JMP nextCommand
  165.  
  166. decPtr:
  167.     DEC DI
  168.     CMP DI, bfMemory ; Check for buffer underrun
  169.     ;JL errMemUnder
  170.  
  171.     JMP nextCommand
  172.  
  173. incData:
  174.     INC BYTE [DI]
  175.     JMP nextCommand
  176.  
  177. decData:
  178.     DEC BYTE [DI]
  179.     JMP nextCommand
  180.  
  181. loopStart:
  182.     INC BYTE [stackDepth]
  183.     PUSH SI        ; Save location in source
  184.     PUSH DI        ; Save counter for loop
  185.     JMP nextCommand
  186.  
  187. loopEnd:
  188.     DEC BYTE [stackDepth]
  189.     JB errStackUnder      ; If we have more ']' than '['
  190.  
  191.     POP BX ; Get loop counter
  192.     POP AX ; Get return address for loop
  193.  
  194.     XOR DL, DL
  195.     CMP [BX], DL
  196.     JZ nextCommand ; if counter is zero, loop done
  197.  
  198.     MOV SI, AX ; Counter non-zero, loop again
  199.     PUSH SI    ; Save loop start again
  200.     PUSH BX    ; Save counter address again
  201.  
  202.     JMP nextCommand
  203.  
  204. readChar:
  205.     MOV AH, 01h
  206.     INT 21h
  207.  
  208.     MOV [DI], AL
  209.  
  210.     JMP nextCommand
  211.  
  212. writeChar:
  213.     MOV AH, 02h
  214.     MOV DL, [DI] ; Get character to echo to stdout
  215.     INT 21h
  216.  
  217.     JMP nextCommand
  218.  
  219. ; ======== Error handling ========
  220.  
  221. errMemUnder:
  222.     LEA DX, [sMemUnder] ; Show error and exit
  223.     MOV AH, 09h
  224.     INT 21h
  225.  
  226.     JMP end  
  227.  
  228. errMemOver:
  229.     LEA DX, [sMemOver] ; Show error and exit
  230.     MOV AH, 09h
  231.     INT 21h
  232.  
  233.     JMP end  
  234.  
  235. errStackUnder:
  236.     LEA DX, [sStackUnder] ; Show error and exit
  237.     MOV AH, 09h
  238.     INT 21h
  239.  
  240.     JMP end
  241.  
  242. end:
  243.     MOV AX, 4C00h ; DOS quit and clean up resources
  244.     INT 21h
  245.  
  246.  
  247. ; ======== Data Section ========
  248.  
  249. section .data
  250.  
  251. stackDepth: db 00h
  252.  
  253. psFileName: dw 0000h ; Address of filename
  254.  
  255. srcFileLen: dw 0000h ; Length of source file
  256. hSrcFile: dw 0000h
  257.  
  258. sReadFailed: db "Failed to read file!", '$'
  259. sOpenFailed: db "Failed to open file: '", '$'
  260. sNoParameter: db "No file passed to interpreter!", '$'
  261.  
  262. sMemUnder:   db "Error: BF buffer underrun!", '$'
  263. sMemOver:    db "Error: BF buffer overrun!", '$'
  264. sStackUnder: db "Error: Stack underrun in script!", '$'
  265.  
  266. section .bss
  267.  
  268. sourceBuff: resb SRC_BUFF_SZ ; source code buffer
  269. sourceBuffEnd:
  270.  
  271. bfMemory:   resb 30000       ; bf memory space
  272. bfMemEnd:
  273.  
  274.  
RAW Paste Data