; bf.asm - Tiny BrainFuck compiler (135 bytes) ; ; Robert Oestling ; http://www.robos.org/ ; ; nasm -f bin bf.asm -o bf.com ; bf file.com ; ; Here are some other more or less tiny brainfuck compilers: ; ; Name Size Comments ; ========================================================================== ; Jeffry Johnston 123 '@' is EOF. Cheater. ; INT-E 136 16-bit words. ; Ben Olmstead 331 286 compatible. ; ========================================================================== [section .text] org 0x100 main: mov di,code_buffer+8 ; Where the compiled code goes. .read_byte: xor bx,bx ; stdin. mov ah,0x3f ; Read from file. mov cl,1 ; One byte. mov dx,di ; Right after the last compiled data int 0x21 inc bx ; stdout. dec ax ; Not EOF? (i.e. one byte read?) jz .not_eof mov al,0xc3 ; "ret" stosb ; Compile it. mov ah,0x40 ; Write to file. mov dl,0x7f ; dx = code_buffer. lea cx,[di+0xfe81] ; -code_buffer ; Note, if anything doesn't work after you modified the file, check ; these numbers first! int 0x21 ; Write and quit. ret .not_eof: cmp byte[di],'[' jz .loop_start cmp byte[di],']' jz .loop_end mov si,list ; Load instruction table into si. .next_try: lodsw xchg ax,cx ; cl = size, ch = instruction. lodsb ; al = address (low 8 bits). mov ah,1 ; High 8 bits of address always 1. or ch,ch ; Last entry? jz .read_byte ; Yes, unknown instruction (comment). cmp ch,[di] ; Is it the one we're looking for? jnz .next_try ; Nope, try again. .found: xchg ax,si ; Yes, address of code into si, mov ch,0 ; cx = cl (length of code). rep movsb ; Copy code. jmp short .read_byte .loop_start: mov al,0xe9 stosb ; Compile near jump, address filled push di ; Save current address. stosw ; in later. jmp short .read_byte .loop_end: pop ax ; Get address to patch+maybe jump to. push ax ; Save it again. mov si,code_loop ; Conditional jump code. movsw ; Copy first word of it. movsw ; Copy last word. sub ax,di ; Calculate relative jump back. stosw ; Copy relative jump address. not ax sub ax,5 ; Relative jump _forward_ (for patch) pop si ; si = address of jump to patch. mov [si],ax ; Patch! jmp short .read_byte code_inc: inc byte[bx] code_dec: dec byte[bx] code_dot: mov al,[bx] int 0x29 list: db 1,'>' db 0x0d db 1,'<' db 0x84 db 2,'+' db 0x5b db 2,'-' db 0x5d db 4,'.' db 0x5f db 8,',' db 0x75 code_comma: mov ah,0x00 ; 00 shows that the list is over. int 0x16 mov [bx],al code_loop: cmp [bx],ch ; ch is always 0 at run-time. db 0x0f,0x85 ; jnz ... code_buffer: ; Runtime initialization code: mov bh,0xa0 ; bx = 0xa000. mov di,bx ; di = 0xa000. mov ch,0x4b ; 0x4b = dec bx. rep stosb ; Zero memory area.