use16 org 100h macro print_string s { push dx push ax mov dx, s mov ah, 9 int 21h pop ax pop dx } macro print_char chr { mov dl, chr mov ah, 02h int 21h } macro cmpje reg, tmpl, trgt { cmp reg, tmpl je trgt } macro cmpjne reg, tmpl, trgt { cmp reg, tmpl jne trgt } macro failwith cond, reason { mov dx, reason j#cond error } macro zero reg {xor reg, reg} ; entry point mov ax, cs cmp ax, 0A000h - 03000h failwith nc, er_no_memory add ax, 1000h mov ds, ax add ax, 1000h mov es, ax zero bx erase: mov byte ptr ds:bx, 0 inc bx jnz erase mov si, prg ; si - instruction pointer zero di ; di - data pointer zero bx ; bx - stack pointer start: mov al, [cs:si] and al, al jz terminate call proc inc si jmp start error: mov ah, 9 int 21h terminate: mov ah, 4ch int 21h proc: cmpje al, '>', right cmpje al, '<', left cmpje al, '+', incr cmpje al, '-', decr cmpje al, ',', read cmpje al, '.', print cmpje al, '[', open cmpje al, ']', close ret right: inc di ret left: dec di ret incr: inc byte ptr ds:di ret decr: dec byte ptr ds:di ret read: mov ah, 01h int 21h mov [ds:di], al ret print: mov dl, [ds:di] mov ah, 02h int 21h ret open: cmpje byte ptr ds:di, 0, find_close cmp bx, 0FFFEh failwith e, er_full mov [es:bx], si add bx, 2 ret find_close: zero cx l: mov al, [cs:si] inc si cmpjne al, '[', l2 inc cx jmp l l2: cmpjne al, ']', l3 dec cx jnz l dec si ret l3: and al, al jnz l failwith mp, er_end close: and bx, bx failwith e, er_empty sub bx, 2 cmpje byte ptr ds:di, 0, close1 mov si, [es:bx] dec si close1: ret er_end: db 'End reached unexpectedly$' er_empty: db 'Stack underflow$' er_full: db 'Stack overflow$' er_no_memory: db 'Out of memory$' msg_debug: db ' debug $' prg: db '-[.>-[>-[>-[-]<-]<-]<-]', 0