Inspired by Gynvael Coldwind's 125 bytes version

Assemble with Yasm
non-compliant (dialect) version, non-commands are not ignored

[bits 16]
[org 0x100]
; assume bp=091e used
; assume di=fffe
; assume si=0100
; assume dx=cs (see here)
; assume cx=00ff
; assume bx=0000
; assume ax=0000 used (ah)
; assume sp=fffe
start:moval, code_left - start
code_start:movch, 0x7f ; allow bigger programs
movbx, cx
movdi, cx
repstosb
movbp, find_right + start - code_start ;cache loop head for smaller compiled programs
jmpcode_start_end
find_right:popsi
decsi
decsi ;point to loop head
cmp[bx], cl
jneloop_right_end
loop_right:lodsb
cmpal, 0xD5 ; the "bp" part of "call bp" (because 0xFF is not unique, watch for additional '[')
jneloop_left
inccx
loop_left:cmpal, 0xC3 ; ret (watch for ']')
jneloop_right
looploop_right ;all brackets matched when cx==0
db0x3c ;cmp al, xx (mask push)
loop_right_end:pushsi
lodsw; skip "call" or dummy "dec" instruction, depending on context
pushsi
code_sqright:ret
code_dec:decbyte [bx]
code_start_end:db'$' ;end DOS string, also "and al, xx"
code_inc:incbyte [bx]
db'$'
code_right:incbx ;al -> 2
db'$'
code_left:decbx
db'$'
code_sqleft:callbp
db'$'
; create lookup table
real_start:subbyte [bx+'>'], al ;point to code_right
addbyte [bx+'['], al ;point to code_sqleft
movbyte [bx+']'], code_sqright - start
leasp, [bx+45+2] ;'+' + 4 (2b='+', 2c=',', 2d='-', 2e='.')
push(code_dec - start) + (code_dot - start) * 256
push(code_inc - start) + (code_comma - start) * 256
pre_write:movah, code_start >> 8
xchgdx, ax
; write
movah, 9
int0x21
; read
code_comma:movdl, 0xff
db0x3d ; cmp ax, xxxx (mask mov)
code_dot:movdl, [bx]
movah, 6
int0x21
mov[bx], al
db'$'
db0xff ; parameter for '$', doubles as test for zero
; switch
xlatb
jnepre_write
; next two lines can also be removed
; if the program ends with extra ']'
; and then we are at 96 bytes... :-)
the_end:movdl, 0xC3
int0x21
int0x20

compliant version, non-commands are ignored, but 104 bytes long

[bits 16]
[org 0x100]
; assume bp=091e used
; assume di=fffe
; assume si=0100
; assume dx=cs (see here)
; assume cx=00ff
; assume bx=0000
; assume ax=0000 used (ah)
; assume sp=fffe
start:moval, code_nothing - start
code_start:movch, 0x7f ; allow bigger programs
movbx, cx
movdi, cx
repstosb
movbp, find_right + start - code_start ;cache loop head for smaller compiled programs
jmpcode_start_end
find_right:popsi
decsi
decsi ;point to loop head
cmp[bx], cl
jneloop_right_end
loop_right:lodsb
cmpal, 0xD5 ; the "bp" part of "call bp" (because 0xFF is not unique, watch for additional '[')
jneloop_left
inccx
loop_left:cmpal, 0xC3 ; ret (watch for ']')
jneloop_right
looploop_right ;all brackets matched when cx==0
db0x3c ;cmp al, xx (mask push)
loop_right_end:pushsi
lodsw; skip "call" or dummy "dec" instruction, depending on context
pushsi
code_sqright:ret
code_dec:decbyte [bx]
code_start_end:db'$' ;end DOS string, also "and al, xx"
code_inc:incbyte [bx]
db'$'
code_right:incbx ;al -> 2
code_nothing:db'$'
code_left:decbx
db'$'
code_sqleft:callbp
db'$'
; create lookup table
real_start:incbyte [bx+'<'] ;point to code_left
decbyte [bx+'>'] ;point to code_right
movbyte [bx+'['], code_sqleft - start
movbyte [bx+']'], code_sqright - start
leasp, [bx+45+2] ;'+' + 4 (2b='+', 2c=',', 2d='-', 2e='.')
push(code_dec - start) + (code_dot - start) * 256
push(code_inc - start) + (code_comma - start) * 256
pre_write:movah, code_start >> 8
xchgdx, ax
; write
movah, 9
int0x21
; read
code_comma:movdl, 0xff
db0x3d ; cmp ax, xxxx (mask mov)
code_dot:movdl, [bx]
movah, 6
int0x21
mov[bx], al
db'$'
db0xff ; parameter for '$', doubles as test for zero
; switch
xlatb
jnepre_write
; next two lines can also be removed
; if the program ends with extra ']'
; and then we are at 100 bytes... :-)
the_end:movdl, 0xC3
int0x21
int0x20

Copyright (c) 2013 Peter Ferrie
All rights reserved

This site is hosted by 000webhost.com



Free web hostingWeb hosting