From e601535399e3dc8616c0cd849c958c0ca854b5a2 Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Sun, 20 Oct 2019 01:05:26 -0400 Subject: [PATCH] First cut at x86 assembler & simplest program - add VM tracing - bootstrap defs from file - error messages --- asm.img | Bin 0 -> 10804 bytes asm.qf | 65 ++++++++++ boot.img | Bin 0 -> 10118 bytes boot.qf | 66 ++++++++++ build.bat | 2 + in.asm | 6 + messages.txt | 3 + out.com | 1 + qf.bas | 270 ++++++++++++++++++++++++++++++---------- trace.txt | 346 +++++++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 694 insertions(+), 65 deletions(-) create mode 100755 asm.img create mode 100755 asm.qf create mode 100755 boot.img create mode 100755 boot.qf create mode 100755 build.bat create mode 100755 in.asm create mode 100755 messages.txt create mode 100755 out.com create mode 100755 trace.txt diff --git a/asm.img b/asm.img new file mode 100755 index 0000000000000000000000000000000000000000..6124976f1d02afa73d962551104831142ace0298 GIT binary patch literal 10804 zcmeI2-)me&6vt=ordth!mPim4bc#aM8h_Gin^+4{MAX(F4}!nS-QAmX&F8unRCx1ZIY<2xR2IC6o#rCqL#tbhC>!=g4vP8tg#DVcCwa~S_HGn!(0WEPol6M zxxp)7iWT14WiatjJ;&KwAU)-BR4BU5{RyU!#B6+)z(fb4{1D^xB`~Ep9^{VWBADSg zDR4WR2U8g;=c2?NpEmVi{ zS87Zp+W@A*mpau6Cae_LNZ$x1X1!6W8_W(*Lid2_^Dy_49@ZPBwt}hE-F1$ZZv#_^ zsRFr`^%@2h$c?C7mWd89ao!E4SgA)zHF4fzFMxTGu|re+LW-9?%pmk^_b^p3y&k3x zTd1onH3B`|ETPmJ&{K$VLjw%=CiLu!67KaZOCIKXFrM2n*viQvR8qc zB_S?Ob)-N4AKI}=L7gtDpm%aLB_g|!IaqwrPSxdga;f}toTbXah0>A)Rw z9RrgeO4#3cjvGDqvHqMe%>68L63m{b_wL@adzX{@!7|V8dh8)5^W!RW-&Pm&lVzTR zA{U~5vCQL7J>^8yuVCWpCO3eYQ((ecEh^_qkt?TXz?27*i2E5}9t;Tg#$l^HFpPWS zU^>9mcvEU47*C3+>xkhlO4z!d7)PzdwE5fwCeNp{x`h~zty_ul*y;vT@Yvc+jK|hJ z#CU8y04C?L^&l}GTfM}1Y&`;|#$U_oQPSgK9wR-TBK`!Jf`{1yhAAuN+@AxJcb6W+ zJWu|3m>0<(53?7{tv219&pa5E@Ip_qTy-5uKbSII{|r!H)1 zu~bhFU6>A^zFA@7YCgsfu4^g#mKgVz%#!bno;8=Rs=NTE9PeKpuhp5cOm3~Y71kjeI>ZHi zL2KRA%cjkWtk8NAl1aUY=d^AU^tT>bH?+iaTCWo%8%MhY*}pTLqNzK@jiM9OdGxey z7w4h#obE>dUL&XfLEk18G20C-8F2{~Ch#R0X>LH{gppjtI3s$oa?bR2p?4PKJp3f9 zJ;saO@MA$QK~A!5;;QM%v^TG>=s~P&KsurOO>ag2yuOHaOR42Rj9_-&SRhTbb81On zr#NRu)6g+$VnH5{B2Kf2nzcA?=BCV=34KIR{6?YiU1O7Gn;6fcJ+dmXW3pp4)2!B) zF}?#9r%m)}BoIYAqWv`V24N#)M;#bx{kwS*dlvdf#ozjEw9VDXH1#Yf8#&Szh&jVi zbZAd)STTau?t}D@RvS0+c+#wupqlV&3UeJ|KCm8iNs7zO@@mRkjhR&A7CEl7m|aAq z&R`wsrOYB7c6}e#H}vD+0$8$k$r432E4JdCv+#^0<0cm+;z+(tf&BzC%V-<=w0Rze z-$x;%Ibujk?c{%$XJGF$FiS>u#t?siIs;CKDNX%`J_L#~hAfblqv$vE!F27)Dq8aq zJZ}>RNl1?4EXZ2{j(W;O_=?La>~`V@B1C9g;+=oy%222XTh+qN_(gEsg>txV-I9j{B(jO^ zm9I+>)Mw zhm_w-c+RA{SJqiC#{%m)&OV@1A4MikA@jb$h~D?p`rCkXUz6^k37M^ZlVB!siuTM; ziUm|evezZw4+3#*#r optypes r@ + ! ops r@ + ! 1 r> + currop ! ; +: assembled 0 currop ! ; + +: mkreg makedo , does> @ swap makedo , , does> dup @ swap 1 + @ op! ; +OP_REG8 mkreg reg8 +OP_REG16 mkreg reg16 +OP_SREG mkreg sreg +0 reg16 ax 0 reg8 al 4 reg8 ah +1 reg16 cx 1 reg8 cl 5 reg8 ch +2 reg16 dx 2 reg8 dl 6 reg8 dh +3 reg16 bx 3 reg8 bl 7 reg8 bh +4 reg16 sp 5 reg16 bp 6 reg16 si 7 reg16 di +0 sreg es 1 sreg cs 2 sreg ss 3 sreg ds + +: # OP_IMM op! ; + +: read-impl ( p -- next cp optypes ) + dup @ swap + dup 1 + @ swap + 2 + ; + +: match-impl ( optypes opcount -- b ) + begin dup > 0 while + 1 - 2dup + @ over optypes + @ != + if drop drop 0 ret then + repeat drop drop 1 ; + +: inst ( opcount -- ) makedo , 0 , does> + dup @ currop @ != if 0 message yelp ret then + 1 + @ begin dup while + read-impl currop @ match-impl + if execute drop assembled ret else drop then + repeat drop 1 message yelp ; + +: do.data ( cp -- data ) 2 + ; +: inst-nextimpl do.data 1 + ; +: inst-opcount do.data @ ; + +: impl ( [optype...] cp cpinst -- ) + here >r >r ( r: impl inst ) + r@ inst-nextimpl @ , , + r@ inst-opcount begin dup while 1 - swap , repeat drop + r> inst-nextimpl r> swap ! ; + +: int &hcd outb! outb! assembled ; +2 inst mov +2 inst movb + +: outw! dup &hff and outb! 256 / outb! ; +OP_IMM OP_REG16 :noname &hb8 op1 + outb! op2 outw! ; ' mov impl +OP_IMM OP_REG8 :noname &hb0 op1 + outb! op2 outb! ; ' movb impl + + diff --git a/boot.img b/boot.img new file mode 100755 index 0000000000000000000000000000000000000000..359ccf7d1185ef0715076b9fe68014aa7af29ff2 GIT binary patch literal 10118 zcmeI2J7^q77{_NNeHc$5MM$+c)c8|S1OBYN! zp@0a67)&aWBBTl!;dDurbm`KiNsO)NeM;oh!?JXz@&B7WJ1M;1^kEjXJCEP|zi<9C zJ1b+wDv{i!wGhR6l|$qSnA(ibLLD&Ual{7O05icxlJXeLc?)v{rVuMXQQ6=VFhR&i zI|LKelROviG3it)su*O4`wL7lj#z)%VAQNC)S09Yz?7q?#4X1@n3*Upax>cl6V@wv z6=(aiOR<9FlWaoD7MP11fWAjyhAhkunAa`LKVaUpFn@y?voPym-mx%iU_Skfox0p6 zrc!00RWRd>$CO4BOgzpfv_;GW&paf?vdNZ-vAn1cz+B=($xSd7Rjc_^*)Q0iU>d5- z?)eokN$eN0Riyj_%$Vie=oNTRZ*aR=${d)tEC*RXm9%m@x};nRM7}q`U&AmSmrEG<+CLF`^SFTWr)YIDxVe zc{OF!EaUSvFhQ88xEg1E#oh<=0TYM1CWR+HvM?p+j98c|m{ALpAQsM5mTEv}kR_!2 z96CjnuTL@D7tonjG531Og)YN=<8FaDZ`nV$!32{`GU&R4oReu4a?~OiRj#o)e+wqB zrUFjrE|{6=pv(y^fr(WWzbIs9bPtR_<+HJV0#gr@pqwoue*yC<(@$N$g89(G{07Ey z{K((27JeN24Myue7#wx%QNNNhjEa=&6sufjPrD|VFkn9ga)%f-#U3uZ6f0k2^Em`F z5=Nn4$zFL_C`N9wGP2k6#7)b~{4$se#fTL;gIL8#)!wN3Nn!fM=s7SIzob~Ht`2ub zUo!cqN$yKHMmjtqC&0uC)Qi(Kt?z-km_##vT+CdM>tH4=AFz*+bHK!*t}2+2{Sru- zfN2D(%zSp_9L+rnvo{7}&4U@WKwl!3^0QVGBDlWtJW+}Gv-fK-dHg%2L<2IeZ;($p z2uqnJW8C*(D(nd*{4mby#1I_{G zfOEh(;2dxcI0yb84*cvD#4BP$Z)mMM`ouhQA}6%oLd%vu#(i7&3HnpM#?QH zZkm>T)O*D!M(&!@Rg_jh?jcW#I%KlAhCCkYHrlCeSR9#>*DdYoC%S}jEwpaxNmF{J zzo+*xuHB8?BO2)4GZ9FMW=>Di8xU)zwhfI1;{|2B0H1c?S{iZH^fk?xO}!|{zXd4X zF)^vPgZd7hi_crqI>kwqsaNYm)L%oyZR0-G1YAsOG@q6}EmDWl+9}kuzHjctu0Vf5 zJkq!D>^yg-qjx~1&XHP=*fkuvLv!lGhz6eNJV=LBQ{O1#Ei={w)j?iO^wCPD8JzLR zmvi1xmroUYyNYjnt2&3?V>q>paimK-i!{>lV;JAk?}F<=q%_rbgQf^JKchPf#XG=dc_uI&O32oFz47Jj8>p#qO#JdNkZQ7O%@c`5^I3b#v$}K$) zigpY|AeAMQTY9cL_Sq;J^Bpqp6La3Yr}cpuJ%`zzVBgTHwV~8+X3>N9gLW#t6|@3r GO^BzP@#O*l literal 0 HcmV?d00001 diff --git a/boot.qf b/boot.qf new file mode 100755 index 0000000..0e3030c --- /dev/null +++ b/boot.qf @@ -0,0 +1,66 @@ +: debug word@ yelp ; +: here 0 @ ; +: here! 0 ! ; +: != not = ; + +: if ' jz_ , here 0 , ; immediate +: then here over - swap ! ; immediate +: else ' jmp_ , here >r 0 , [ ' then , ] r> ; immediate + +: begin here ; immediate +: while [ ' if , ] ; immediate +: repeat ' jmp_ , swap here - , [ ' then , ] ; immediate +: again ' jmp_ , here - , ; immediate +: until ' jz_ , here - , ; immediate + +: ( begin in@ [ in@ ) lit ] = until ; immediate +: \ begin in@ 0 < until ; immediate + +: const word@ create ' $const , , ; +: array word@ create ' $var , ; +: var, array , ; +: var 0 var, ; + +: allot here + here! ; + +: nip swap drop ; +: negate 0 swap - ; +: abs dup 0 < if negate then ; + +: :noname here ] ; +: :| here 4 + lit ' jmp_ , here 0 , ; immediate +: |; ' ret , [ ' then , ] ; immediate + +: $do r> dup 1 + swap @ >r ; +var does.patch +: makedo word@ create ' $do , here does.patch ! -1 , ; +: does> here 3 + lit :| does.patch @ ! rdrop |; , ; immediate + +: $defer r> @ >r ; +: defer word@ create ' $defer , :| |; , ; +: redef 1 + ! ; + +: +towards ( from to -- from+-1 ) + over > if 1 + else 1 - then ; + +: for ( from to -- ) + ' >r , [ ' begin , ] ( from r: to ) + ' dup , ' r@ , ' != , [ ' while , ] + ' >r , ; immediate ( r: to from ) +: i ' r@ , ; immediate +: next + ' r> , ' r@ , ' +towards , ( from+1 r: to ) + [ ' repeat , ] ' drop , ' rdrop , ; immediate + +: yield rswap ; +: done rdrop 0 >r rswap ; +: ;done ' done , [ ' [ , ] ; immediate +: each [ ' begin , ] ' r@ , [ ' while , ] ; immediate +: more ' yield , [ ' repeat , ] ' rdrop , ; immediate +: break rswap rdrop :| yield done |; execute rswap ; + +: links begin yield @ dup not until drop ;done + +: min ( x y -- x|y ) 2dup > if swap then drop ; +: max ( x y -- x|y ) 2dup < if swap then drop ; + diff --git a/build.bat b/build.bat new file mode 100755 index 0000000..24f7d92 --- /dev/null +++ b/build.bat @@ -0,0 +1,2 @@ +qbasic /run qf.bas + diff --git a/in.asm b/in.asm new file mode 100755 index 0000000..6d55dc0 --- /dev/null +++ b/in.asm @@ -0,0 +1,6 @@ +\ The simplest possible COM file: just return 1 + +\ 1 trace +\ mov \ should fail and yelp +ax &h4c01 # mov +&h21 int diff --git a/messages.txt b/messages.txt new file mode 100755 index 0000000..f7eca25 --- /dev/null +++ b/messages.txt @@ -0,0 +1,3 @@ +Operand count doesn't match +No matching instruction + diff --git a/out.com b/out.com new file mode 100755 index 0000000..f041664 --- /dev/null +++ b/out.com @@ -0,0 +1 @@ +¸LÍ! \ No newline at end of file diff --git a/qf.bas b/qf.bas index 66ca35a..c00bd52 100755 --- a/qf.bas +++ b/qf.bas @@ -1,3 +1,9 @@ +DECLARE FUNCTION lookupop$ (op%) +DECLARE FUNCTION guessdef$ (ptr%) +DECLARE FUNCTION loadimg! (filename$) +DECLARE SUB bootstrap () +DECLARE SUB saveimg (filename$) +DECLARE SUB loadfile (filename$) DECLARE SUB vm () DECLARE SUB interpret (st$) DECLARE SUB execute (op%) @@ -17,18 +23,29 @@ TYPE word df AS INTEGER i AS INTEGER END TYPE -DIM SHARED words(256) AS word +CONST WORDCOUNT = 256 +CONST memcount = 10000 +DIM SHARED words(WORDCOUNT) AS word DIM SHARED strings$(32) -DIM SHARED mem(10000) AS INTEGER +DIM SHARED messages$(32) +DIM SHARED mem(memcount) AS INTEGER DIM SHARED stack(64) AS INTEGER DIM SHARED rstack(64) AS INTEGER COMMON SHARED sp AS INTEGER, rsp AS INTEGER, w AS INTEGER, ip AS INTEGER -COMMON SHARED in$ +COMMON SHARED tracevm +COMMON SHARED in$, inline% COMMON SHARED interpretcp AS INTEGER COMMON SHARED trace% +inline% = -1 interpretcp = -1 -trace% = 0 +trace% = 10 ' 10 + +OPEN "messages.txt" FOR INPUT AS #1 +FOR i = 0 TO 31 + IF EOF(1) = 0 THEN LINE INPUT #1, messages$(i) +NEXT +CLOSE #1 OPEN "out.com" FOR OUTPUT AS #1 CLOSE #1 @@ -66,65 +83,29 @@ CONST O.EQ = -25 CONST O.JMP = -26 CONST O.YELP = -27 CONST O.IMMEDIATE = -28 +CONST O.RDROP = -29 +CONST O.RTOP = -30 +CONST O.RSWAP = -31 +CONST O.BITAND = -32 +CONST O.BITOR = -33 +CONST O.MESSAGE = -34 +CONST O.TRACE = -35 CONST P.HERE = 0 CONST P.LATEST = 1 CONST P.NEXTSTR = 2 -mem(P.LATEST) = -1 -mem(P.HERE) = 3 -CALL opcode("ret", O.RET) -CALL opcode("dup", O.DUP) -CALL opcode("swap", O.SWAP) -CALL opcode(">rot", O.ROT) -CALL opcode("@", O.GET) -CALL opcode("!", O.SET) -CALL opcode("create", O.CREATE) -CALL opcode("in@", O.IN) -CALL opcode("out!", O.OUT) -CALL opcode("immediate", O.IMMEDIATE) -CALL opcode("drop", O.DROP) -CALL opcode("execute", O.EXEC) -CALL opcode("lookup", O.LOOKUP) -CALL opcode("word@", O.WORD) -CALL opcode("number", O.NUMBER) -CALL opcode("lit_", O.LIT) -CALL opcode("+", O.ADD) -CALL opcode("-", O.SUB) -CALL opcode("*", O.MUL) -CALL opcode("/", O.DIV) -CALL opcode("<", O.LT) -CALL opcode("=", O.EQ) -CALL opcode("jz_", O.JZ) -CALL opcode("jmp_", O.JMP) -CALL opcode(">r", O.RPUSH) -CALL opcode("r>", O.RPOP) -CALL opcode(",", O.COMMA) -CALL opcode("yelp", O.YELP) +IF loadimg("asm.img") = 0 THEN + IF loadimg("boot.img") = 0 THEN + PRINT "Bootstrapping" + CALL bootstrap + CALL saveimg("boot.img") + END IF + CALL loadfile("asm.qf") + CALL saveimg("asm.img") +END IF -CALL assemble("rot >rot ret") -CALL assemble("over", "swap dup >rot ret") -CALL assemble("2dup", "over over ret") -CALL assemble("$var", "r> ret") -CALL assemble("$const", "r> @ ret") -CALL assemble("not", "jz_ 3 lit_ 0 ret lit_ 1 ret") -CALL assemble("and", "jz_ 4 jz_ 3 jmp_ 4 drop lit_ 0 ret lit_ 1 ret") -CALL assemble("or", "not swap not and not ret") -CALL assemble(">=", "< not ret") -CALL assemble("<=", "2dup < >rot = or ret") -CALL assemble(">", "<= not ret") -CALL assemble("state", "$var 0") - -CALL assemble("doword", "state @ not or jz_ 2 execute ret , ret") -CALL assemble("donum", "state @ jz_ 4 lit_ lit_ , , ret") -CALL assemble("donext", "lookup jz_ 2 doword ret number jz_ 2 donum ret yelp ret") -CALL assemble("interpret", "word@ dup lit_ 0 >= jz_ 3 donext jmp_ -10 drop ret") -CALL assemble("[", "lit_ 0 state ! ret"): CALL execute(O.IMMEDIATE) -CALL assemble("]", "lit_ 1 state ! ret") -CALL assemble(":", "word@ create ] ret") -CALL assemble(";", "lit_ ret , [ ret"): CALL execute(O.IMMEDIATE) - -CALL interpret("65 out! 66 out! 0 out! 67 out! 7 out! 254 out! 10 out! 13 out!") +CALL loadfile("in.asm") SUB assemble (name$, asm$) in$ = asm$ @@ -159,11 +140,75 @@ SUB assemble (name$, asm$) WEND END SUB +SUB bootstrap +mem(P.LATEST) = -1 +mem(P.HERE) = 3 + +CALL opcode("ret", O.RET) +CALL opcode("dup", O.DUP) +CALL opcode("swap", O.SWAP) +CALL opcode(">rot", O.ROT) +CALL opcode("@", O.GET) +CALL opcode("!", O.SET) +CALL opcode("create", O.CREATE) +CALL opcode("in@", O.IN) +CALL opcode("outb!", O.OUT) +CALL opcode("immediate", O.IMMEDIATE) +CALL opcode("drop", O.DROP) +CALL opcode("execute", O.EXEC) +CALL opcode("lookup", O.LOOKUP) +CALL opcode("word@", O.WORD) +CALL opcode("number", O.NUMBER) +CALL opcode("lit_", O.LIT) +CALL opcode("+", O.ADD) +CALL opcode("-", O.SUB) +CALL opcode("*", O.MUL) +CALL opcode("/", O.DIV) +CALL opcode("<", O.LT) +CALL opcode("=", O.EQ) +CALL opcode("jz_", O.JZ) +CALL opcode("jmp_", O.JMP) +CALL opcode(">r", O.RPUSH) +CALL opcode("r>", O.RPOP) +CALL opcode("r@", O.RTOP) +CALL opcode("rdrop", O.RDROP) +CALL opcode("rswap", O.RSWAP) +CALL opcode(",", O.COMMA) +CALL opcode("message", O.MESSAGE) +CALL opcode("yelp", O.YELP) +CALL opcode("trace", O.TRACE) +CALL assemble("rot >rot ret") +CALL assemble("over", "swap dup >rot ret") +CALL assemble("2dup", "over over ret") +CALL assemble("$var", "r> ret") +CALL assemble("$const", "r> @ ret") +CALL assemble("not", "jz_ 4 lit_ 0 ret lit_ 1 ret") +CALL assemble("and", "jz_ 5 jz_ 4 jmp_ 5 drop lit_ 0 ret lit_ 1 ret") +CALL assemble("or", "not swap not and not ret") +CALL assemble(">=", "< not ret") +CALL assemble("<=", "2dup < >rot = or ret") +CALL assemble(">", "<= not ret") +CALL assemble("state", "$var 0") + +CALL assemble("doword", "state @ not or jz_ 3 execute ret , ret") +CALL assemble("donum", "state @ jz_ 5 lit_ lit_ , , ret") +CALL assemble("donext", "lookup jz_ 3 doword ret number jz_ 3 donum ret yelp ret") +CALL assemble("interpret", "word@ dup lit_ 0 >= jz_ 4 donext jmp_ -9 drop ret") +CALL assemble("[", "lit_ 0 state ! ret"): CALL execute(O.IMMEDIATE) +CALL assemble("]", "lit_ 1 state ! ret") +CALL assemble(":", "word@ create ] ret") +CALL assemble(";", "lit_ ret , [ ret"): CALL execute(O.IMMEDIATE) +CALL assemble("lit", "lit_ lit_ , , ret") +CALL assemble("'", "word@ lookup drop drop state @ jz_ 2 lit ret"): CALL execute(O.IMMEDIATE) + +CALL loadfile("boot.qf") +END SUB + SUB execute (op%) - IF trace% > 0 THEN - tp$ = "NA" + IF trace% > 0 AND tracevm THEN + tp$ = "N/A" IF sp > 0 THEN tp$ = STR$(top) - PRINT #trace%, "ip:"; ip; " op:"; op%; " sp:"; sp; " tp:"; tp$; " rsp:"; rsp + PRINT #trace%, "ip:"; ip; " sp:"; sp; " rp:"; rsp; " tp:"; tp$; " fn:"; guessdef$(ip); " op:"; lookupop$(op%); END IF SELECT CASE op% CASE IS >= 0 @@ -226,6 +271,9 @@ SUB execute (op%) CASE O.WORD word$ = nextword$ IF word$ <> "" THEN + IF trace% > 0 THEN + PRINT #trace%, "read: "; word$ + END IF CALL push(mkstr(word$)) ELSE CALL push(-1) @@ -267,6 +315,15 @@ SUB execute (op%) l = pop CALL push(l / r) + CASE O.BITAND + r = pop + l = pop + CALL push(l AND r) + CASE O.BITOR + r = pop + l = pop + CALL push(l OR r) + CASE O.LT r = pop l = pop @@ -281,29 +338,57 @@ SUB execute (op%) END IF CASE O.JZ IF pop = 0 THEN - ip = ip + mem(ip) + 1 + ip = ip + mem(ip) ELSE ip = ip + 1 END IF CASE O.JMP - ip = ip + mem(ip) + 1 + ip = ip + mem(ip) CASE O.RPUSH CALL rpush(pop) CASE O.RPOP CALL push(rpop) - + CASE O.RDROP + z = rpop + CASE O.RSWAP + x% = rpop + y% = rpop + CALL rpush(x%) + CALL rpush(y%) + CASE O.RTOP + CALL push(rpeek) CASE O.COMMA here = mem(P.HERE) mem(here) = pop mem(P.HERE) = here + 1 CASE O.YELP - PRINT strings$(pop); "?" + PRINT strings$(pop); "? line "; inline% + CASE O.TRACE + tracevm = pop + CASE O.MESSAGE + CALL push(mkstr(messages$(pop))) + CASE ELSE PRINT "Unknown op "; op% ip = -1 END SELECT END SUB +FUNCTION guessdef$ (ptr%) + guessdef$ = "???" + IF ptr% < 0 THEN + guessdef$ = "**INJECTED**" + ELSE + FOR i = mem(P.LATEST) - 1 TO 0 STEP -1 + IF words(i).df < ptr% THEN + guessdef$ = RTRIM$(words(i).nm) + GOTO doneguessdef + END IF + NEXT + END IF +doneguessdef: +END FUNCTION + SUB interpret (st$) IF interpretcp < 0 THEN CALL push(mkstr("interpret")) @@ -318,6 +403,35 @@ SUB interpret (st$) CALL vm END SUB +SUB loadfile (filename$) + inline% = 0 + OPEN filename$ FOR INPUT AS #2 + WHILE EOF(2) = 0 + LINE INPUT #2, line$ + inline% = inline% + 1 + CALL interpret(line$) + WEND + CLOSE #2 + inline% = -1 +END SUB + +FUNCTION loadimg (filename$) + OPEN filename$ FOR BINARY AS #3 + IF LOF(3) > 0 THEN + FOR i = 0 TO WORDCOUNT - 1 + GET #3, , words(i) + NEXT + filememsize = LOF(3) - SEEK(3) + FOR i = 0 TO filememsize / 2 + GET #3, , mem(i) + NEXT + loadimg = 1 + ELSE + loadimg = 0 + END IF + CLOSE #3 +END FUNCTION + FUNCTION lookup (w$) lookup = -1 FOR i = 0 TO mem(P.LATEST) @@ -329,6 +443,21 @@ FUNCTION lookup (w$) found: END FUNCTION +FUNCTION lookupop$ (op%) + lookupop$ = STR$(op%) + FOR i = 0 TO mem(P.LATEST) + IF words(i).df = op% THEN + lookupop$ = RTRIM$(words(i).nm) + GOTO lookupopdone + ELSEIF op% < 0 AND words(i).df > 0 THEN + GOTO lookupopdone + ELSEIF op% > 0 AND words(i).df > op% THEN + GOTO lookupopdone + END IF + NEXT +lookupopdone: +END FUNCTION + FUNCTION mkstr% (st$) istr = mem(P.NEXTSTR) mem(P.NEXTSTR) = (istr + 1) MOD 32 @@ -355,7 +484,7 @@ FUNCTION nextword$ foundword: IF wordstart <> 0 THEN nextword$ = MID$(in$, wordstart, length) - in$ = MID$(in$, wordstart + length) + in$ = MID$(in$, wordstart + length + 1) ' consume the space END IF END FUNCTION @@ -390,6 +519,17 @@ SUB rpush (v%) rsp = rsp + 1 END SUB +SUB saveimg (filename$) + OPEN filename$ FOR BINARY AS #3 + FOR i = 0 TO WORDCOUNT - 1 + PUT #3, , words(i) + NEXT + FOR i = 0 TO mem(P.HERE) + PUT #3, , mem(i) + NEXT + CLOSE #3 +END SUB + FUNCTION top top = stack(sp - 1) END FUNCTION diff --git a/trace.txt b/trace.txt new file mode 100755 index 0000000..33f5f8f --- /dev/null +++ b/trace.txt @@ -0,0 +1,346 @@ +read: array +read: ops +read: 2 +read: allot +read: array +read: optypes +read: 2 +read: allot +read: var +read: currop +read: : +read: op1 +read: ops +read: @ +read: ; +read: : +read: op2 +read: ops +read: 1 +read: + +read: @ +read: ; +read: 0 +read: const +read: OP_NONE +read: 1 +read: const +read: OP_REG8 +read: 2 +read: const +read: OP_REG16 +read: 3 +read: const +read: OP_SREG +read: 4 +read: const +read: OP_IMM +read: : +read: op! +read: ( +read: currop +read: @ +read: >r +read: optypes +read: r@ +read: + +read: ! +read: ops +read: r@ +read: + +read: ! +read: 1 +read: r> +read: + +read: currop +read: ! +read: ; +read: : +read: assembled +read: 0 +read: currop +read: ! +read: ; +read: : +read: mkreg +read: makedo +read: , +read: does> +read: @ +read: swap +read: makedo +read: , +read: , +read: does> +read: dup +read: @ +read: swap +read: 1 +read: + +read: @ +read: op! +read: ; +read: OP_REG8 +read: mkreg +read: reg8 +read: OP_REG16 +read: mkreg +read: reg16 +read: OP_SREG +read: mkreg +read: sreg +read: 0 +read: reg16 +read: ax +read: 0 +read: reg8 +read: al +read: 4 +read: reg8 +read: ah +read: 1 +read: reg16 +read: cx +read: 1 +read: reg8 +read: cl +read: 5 +read: reg8 +read: ch +read: 2 +read: reg16 +read: dx +read: 2 +read: reg8 +read: dl +read: 6 +read: reg8 +read: dh +read: 3 +read: reg16 +read: bx +read: 3 +read: reg8 +read: bl +read: 7 +read: reg8 +read: bh +read: 4 +read: reg16 +read: sp +read: 5 +read: reg16 +read: bp +read: 6 +read: reg16 +read: si +read: 7 +read: reg16 +read: di +read: 0 +read: sreg +read: es +read: 1 +read: sreg +read: cs +read: 2 +read: sreg +read: ss +read: 3 +read: sreg +read: ds +read: : +read: # +read: OP_IMM +read: op! +read: ; +read: : +read: read-impl +read: ( +read: dup +read: @ +read: swap +read: dup +read: 1 +read: + +read: @ +read: swap +read: 2 +read: + +read: ; +read: : +read: match-impl +read: ( +read: begin +read: dup +read: > +read: 0 +read: while +read: 1 +read: - +read: 2dup +read: + +read: @ +read: over +read: optypes +read: + +read: @ +read: != +read: if +read: drop +read: drop +read: 0 +read: ret +read: then +read: repeat +read: drop +read: drop +read: 1 +read: ; +read: : +read: inst +read: ( +read: makedo +read: , +read: 0 +read: , +read: does> +read: dup +read: @ +read: currop +read: @ +read: != +read: if +read: 0 +read: message +read: yelp +read: ret +read: then +read: 1 +read: + +read: @ +read: begin +read: dup +read: while +read: read-impl +read: currop +read: @ +read: match-impl +read: if +read: execute +read: drop +read: assembled +read: ret +read: else +read: drop +read: then +read: repeat +read: drop +read: 1 +read: message +read: yelp +read: ; +read: : +read: do.data +read: ( +read: 2 +read: + +read: ; +read: : +read: inst-nextimpl +read: do.data +read: 1 +read: + +read: ; +read: : +read: inst-opcount +read: do.data +read: @ +read: ; +read: : +read: impl +read: ( +read: here +read: >r +read: >r +read: ( +read: r@ +read: inst-nextimpl +read: @ +read: , +read: , +read: r@ +read: inst-opcount +read: begin +read: dup +read: while +read: 1 +read: - +read: swap +read: , +read: repeat +read: drop +read: r> +read: inst-nextimpl +read: r> +read: swap +read: ! +read: ; +read: : +read: int +read: &hcd +read: outb! +read: outb! +read: assembled +read: ; +read: 2 +read: inst +read: mov +read: 2 +read: inst +read: movb +read: : +read: outw! +read: dup +read: &hff +read: and +read: outb! +read: 256 +read: / +read: outb! +read: ; +read: OP_IMM +read: OP_REG16 +read: :noname +read: &hb8 +read: op1 +read: + +read: outb! +read: op2 +read: outw! +read: ; +read: ' +read: mov +read: impl +read: OP_IMM +read: OP_REG8 +read: :noname +read: &hb0 +read: op1 +read: + +read: outb! +read: op2 +read: outb! +read: ; +read: ' +read: movb +read: impl +read: \ +read: \ +read: \ +read: ax +read: &h4c01 +read: # +read: mov +read: &h21 +read: int