Category : Assembly Language Source Code
Archive   : ASSEMBLE.ZIP
Filename : CHASM.BAS
$':Ù* * 9
.':Ù* CHeap ASseMbler for the IBM PC. * d
8':Ù* *
B':Ù* Begun 6/15/82 by Dave Whitman * º
L':Ù*********************************** Â
V':Ù Ö
`':Ùmain program ó
j' Pà :Ùinitialize t' :Ùwipe out transient code =~' þ ½ "chasm.ovl",',ALL,© PÃêrÉ _' îM :Ùset up sym table ' º' :Ùpass 1: build sym table ½' ( :Ùpass 2: generate obj code & listing צ' "L :Ùclean up Þ°'þ º':Ù******************************************* DÄ':Ù* SUBROUTINE PASSONE * wÎ':Ù* Adds user-defined symbols to sym table. * ªØ':Ù******************************************* ²â':Ù ¿ì'PASS ç óö'LOCTR ç :Ù0-255 reserved for p.s. prefix (LINENUM ç
(±é Ó ÿ£() 6( :Ùget source line, initialize P( |) :Ùgetline a(( :Ùparse it x2( ê) :Ùparse <( :Ùif label, enter in sym table ÈF( LABEL$ èæ "" Í x- :Ùnewentry îP( :Ùif op, decode, & update loctr Z( OP$ èæ "" Í À0 :Ùupdate_loctr 3d( :Ùprogress report @n( M Gx( ² M( v(:Ù********************************* (:Ù* SUBROUTINE PASSTWO * È (:Ù* Generates obj code & listing. * ñª(:Ù********************************* ù´(:Ù ¾( ªK :Ùpass2_init È(:Ù )Ò(±é Ó ÿ£() MÜ( :Ùget source line, initialize gæ( |) :Ùgetline zð( :Ùparse line ú( ê) :Ùparse §) :Ùphase error? Õ) LABEL$ èæ "" Í . :Ùcheck_phase ) :Ùif op, update loctr, generate obj. code 2") OP$ èæ "" Í À0 :Ùupdate_loctr Z,) :Ùoutput obj. code & listing line r6) LJ :Ùoutput @) :Ùprogess report J) M T) ² ±^):Ùwipe out msg ßh) X ç ÿ(): Y ç Û: Ê ,: ÎO): Ê Y,X år) |):Ù******************************************** M):Ù* SUBROUTINE GETLINE * ):Ù* Gets line of source code for processing. * µ):Ù* and initializes for new iteration. * é¤):Ù******************************************** ñ®):Ù ¸)° #, INPLINE$ Â)LINENUM ç LINENUM é EÌ)NEEDOFFSET ç NONE: DSFLAG ç FALSE TÖ)OBJLEN ç Zà) ê):Ù***************************************************** Ôô):Ù* SUBROUTINE PARSE * þ):Ù* Parses input line for any label, op, or operands. * N*:Ù***************************************************** V*:Ù t*LINEPTR ç : LINEPTR2 ç ¨&*LABEL$ ç "": OP$ ç "": SOURCE$ ç "": DEST$ ç "" °0*:Ù Ñ:*:Ùset endptr to end of code D* ENDPTR ç Ø(INPLINE$,";") ê :Ùjust before comment ]N* ENDPTR ç ê Í ENDPTR ç ÿ(INPLINE$) :Ùno comment, set to eol eX*:Ù ~b*:Ùno code? (return) l* ENDPTR ç Í p+ v*:Ù º*:Ùconvert to all caps Æ* + Î*:Ù ä*:Ùlabel (if any) ¨* ÿ(INPLINE$,) ç " " Í Ð* "²* , :Ùgetfield 8¼* LABEL$ ç FLD$ @Æ*:Ù OÐ*:Ùop-code hÚ* , :Ùgetfield ~ä* Ó FOUND Í p+ î* OP$ ç FLD$ ¶ø*:Ùsave ptr to start of operands Í+ OPDPTR ç LINEPTR Õ +:Ù ù+:Ùdestination operand (if any) + , :Ùgetfield (*+ Ó FOUND Í p+ ;4+ DEST$ ç FLD$ C>+:Ù bH+:Ùsource operand (if any) {R+ , :Ùgetfield \+ Ó FOUND Í p+ ¦f+ SOURCE$ ç FLD$ ¬p+ ´z+:Ù Ô+:Ùinternal subroutine caps ÿ+:ÙScans inpline$ up to comment field, :+:Ùconverting l.c. chars. to u.c.. Skips over strings. O¢+ I ç Ì ENDPTR k¬+ C$ ç ÿ(INPLINE$,I,) ¶+ :Ùskip strings À+ C$ èæ "'" Í è+ ÂÊ+ STRGEND ç Ø(Ié,INPLINE$,C$) ïÔ+ STRGEND æ Í I ç STRGEND: ò+ Þ+ :Ùconvert eè+ ÿ(C$) çæ a î ÿ(C$) èç z Í C$ ç ÿ(ÿ(C$) ê ): ÿ(INPLINE$,I,) ç C$ oò+ I uü+ ¸,:Ù*********************************************************** û,:Ù* SUBROUTINE GETFIELD * >,:Ù* Starting at lineptr, trys to return next field in FLD$. * $,:Ù* Sets found if sucessful. Moves lineptr past field. * Ä.,:Ù*********************************************************** Ì8,:Ù úB,:Ùfind next non-delimiter or run off end L, ±é LINEPTR èç ENDPTR FV, Ø(" ,",ÿ(INPLINE$,LINEPTR,)) ç Í t, c`, LINEPTR ç LINEPTR é lj, ² t,:Ùif past end, not found ª~, LINEPTR èç ENDPTR Í , ¿, FOUND ç FALSE È, Ð,:Ù ï¦,:Ùstrings terminated by ' °, ÿ(INPLINE$,LINEPTR,) èæ "'" Í ì, Eº, STRGEND ç Ø(LINEPTRé,INPLINE$,"'") `Ä, STRGEND ç Í ì, Î, LINEPTR2 ç STRGEND é Ø, 2- â,:Ù Íì,:Ùotherwise, find next delimter or go 1 past end åö, LINEPTR2 ç LINEPTR - ±é LINEPTR2 èç ENDPTR 3
- Ø(" ,",ÿ(INPLINE$,LINEPTR2,)) æ Í 2- R- LINEPTR2 ç LINEPTR2 é [- ² c(-:Ù u2-:Ùcopy field §<- FLD$ ç ÿ(INPLINE$,LINEPTR,LINEPTR2êLINEPTR) ¯F-:Ù âP-:Ùmove lineptr past field, set found & return úZ- LINEPTR ç LINEPTR2 d- FOUND ç TRUE n- I x-:Ù********************************************** -:Ù* SUBROUTINE NEWENTRY * µ -:Ù* Adds new symbol to sym table with default * ë -:Ù* attributes. (may be changed by pseudo-ops) * !! -:Ù********************************************** )!ª-:Ù J!´-:Ùalready in table? (error) a!¾- TARGET$ ç LABEL$ !È- þ. :Ùoperand_lookup !Ò- Ó FOUND Í . ®!Ü- ERRS ç ERRS é õ!æ- #,"****Error: Duplicate definition of ";LABEL$;" in ";LINENUM þ!ð- "ú-:Ù !".:Ùtable full? (error) >". NUMSYM è MAXSYM Í @. U". ERRS ç ERRS é "". #, "****Error: Too many user symbols in "; LINENUM ",. ¢"6.:Ù ½"@.:Ùelse make new entry Ö"J. NUMSYM ç NUMSYM é ñ"T. SYM$(NUMSYM) ç LABEL$ #^. VAL1(NUMSYM) ç LOCTR '#h. SYMTYPE(NUMSYM) ç NEAR /#r.:Ù 5#|. ^#.:Ù********************************* #.:Ù* SUBROUTINE CHECK_PHASE * °#.:Ù* Label value same both passes? * Ù#¤.:Ù********************************* ñ#®. OP$ ç "EQU" Í ô. $¸.TARGET$ ç LABEL$ #$Â. þ. :Ùoperand_lookup +$Ì.:Ù b$Ö. (SYMTYPE(TABLEPTR) î (NEAR ï MEM)) ç FALSE Í ô. $à. VAL1(TABLEPTR) ç LOCTR Í ô. ·$ê. ERRS ç ERRS é : #, "****Phase Error" ½$ô. ö$þ.:Ù************************************************* /%/:Ù* SUBROUTINE OPERAND_LOOKUP * h%/:Ù* Trys to find TARGET$ in sym table. If there, * ¡%/:Ù* sets FOUND true, & TABLEPTR to its'position. * Ú%&/:Ù************************************************* ÷%0/:Ùscan table for symbol &:/ TABLEPTR ç Ì NUMSYM G&D/ SYM$(TABLEPTR) ç TARGET$ Í / :Ùfound Z&N/ TABLEPTR b&X/:Ù |&b/:Ùfailure exit point &l/ FOUND ç FALSE &v/ ±&/:Ùsucess exit point Ä&/ FOUND ç TRUE Ì&/
'/:Ù********************************************************* N'¨/:Ù* SUBROUTINE LOOKUP_OP * '²/:Ù* Given op-code in op$, & operand types in dtype & * Ð'¼/:Ù* stype, trys to find op in opcode table. If sucessful, * (Æ/:Ù* sets found true, & opptr to its' position. * R(Ð/:Ù********************************************************* }(Ú/:Ùbinary search for good starting pt. (ä/ MOVE ç NUMOP: ST ç MOVEì ®(î/ ±é MOVE æç Ã(ø/ MOVE ç MOVEì )0 OP$ æ OPCODE$(ST) Í ST ç ST é MOVE :¡ ST ç ST ê MOVE ) 0 ST è Í ST ç ;)0 ST æ NUMOP Í ST ç NUMOP D) 0 ² L)*0:Ù x)40:Ùscan for entry matching all 3 fields )>0 OPPTR ç ST Ì NUMOP Â)H0 OPCODE$(OPPTR) æ OP$ Í 0 :Ùfailed ç)R0 OPCODE$(OPPTR) èæ OP$ Í z0 *\0 (SRCTYPE(OPPTR) î STYPE) ç FALSE Í z0 G*f0 (DSTTYPE(OPPTR) î DTYPE) ç FALSE Í z0 ^*p0 ¢0 :Ùfound! m*z0 OPPTR *0:Ùfailure exit *0 FOUND ç FALSE *0 ²*¢0:Ùsuccessful exit Ä*¬0 FOUND ç TRUE Ë*¶0 ú*À0:Ù*************************************** )+Ê0:Ù* SUBROUTINE UPDATE_LOCTR * X+Ô0:Ù* Decodes operation & advances loctr. * +Þ0:Ù* On pass 2, generates obj. code. * ¶+è0:Ù*************************************** ¾+ò0:Ù à+ü0:Ùset operand types & values ý+1 :Ùdestination operand -,1 TARGET$ ç DEST$: <2 :Ùtype_operand E,1 DTYPE ç TARGTYPE ],$1 DVAL1 ç TARGVAL1 u,.1 DVAL2 ç TARGVAL2 ,81 :Ùsource operand ,B1 :Ùspecial case: RET op æ,L1 OP$ ç "RET" Í STYPE ç PROCTYPE(STKTOP): 1 ÿ,V1 :Ùnormal source 3-`1 TARGET$ ç SOURCE$: <2 :Ùtype_operand M-j1 STYPE ç TARGTYPE g-t1 SVAL1 ç TARGVAL1 -~1 SVAL2 ç TARGVAL2 -1:Ù ·-1:Ùfind op in op table (not there: error) Ê-1 TARGET$ ç OP$ ä-¦1 / :Ùlookup_op ÷-°1 FOUND Í
2
.º1 PASS ç Í N.Ä1 ERRS ç ERRS é : #,"****Syntax Error: ";OP$;DTYPE;STYPE ».Î1 ((ACUM8 ï ACUM16 ï REG8 ï REG16 ï SEG ï CS) î (DTYPE ï STYPE)) Í 2 ø.Ø1 (STYPE î (NONE ï IMMED8 ï IMMED16)) ç FALSE Í 2 "/â1 Ø("BW",ÿ(OP$,)) èæ Í 2 ?/ì1 DIAG ç DIAG é /ö1 #,"****Diagnostic: Specify word or byte operation" / 2 £/
2 FLAG ç OFLAG(OPPTR) «/2:Ù ã/2:Ùbranch for mach ops & pseudo-ops to update loctr 0(2 FLAG î MACHOP Í 8; :¡ b> 022 P0<2:Ù********************************************************* 0F2:Ù* SUBROUTINE TYPE_OPERAND * Ò0P2:Ù* Sets TARGTYPE to reflect TARGET$'s type. Sets * 1Z2:Ù* TARGVAL1 to its' value. If the operand is a register, * T1d2:Ù* sets TARVAL2 to its' val2. If an offset appears, * 1n2:Ù* NEEDOFFSET gets the its' type, and OFFSET its' value. * Ö1x2:Ù********************************************************* Þ12:Ù ò12:Ùany operand? 22 ÿ(TARGET$) æ Í ´2 &2 2 TARGTYPE ç NONE /2ª2 D2´2:Ùin sym table? c2¾2 þ. :Ùoperand_lookup x2È2 Ó FOUND Í ú2 2Ò2 TARGTYPE ç SYMTYPE(TABLEPTR) ½2Ü2 TARGVAL1 ç VAL1(TABLEPTR) õ2æ2 TABLEPTR èç PREDEF Í TARGVAL2 ç VAL2(TABLEPTR) þ2ð2
3ú2:Ùnumber? )33 4 :Ùtest_number >33 Ó FOUND Í 63 X33 TARGTYPE ç NUMTYPE q3"3 TARGVAL1 ç NUMVAL z3,3 363:Ùdirect mem. ref.? ª3@3 ü5 :Ùmemref ¿3J3 Ó FOUND Í r3 Õ3T3 TARGTYPE ç MEM ï3^3 TARGVAL1 ç MEMADDR ø3h3 4r3:Ùoffset off register? 74|3 d7 :Ùparse_disp_off_reg L43 Ó FOUND Í ¸3 e43 TARGTYPE ç MEMREG ~43 TARGVAL1 ç REGVAL 4¤3 4®3:Ùoffset? «4¸3 9 :Ùoffset À4Â3 Ó FOUND Í ê3 Ü4Ì3 TARGTYPE ç OFFSETYPE ø4Ö3 TARGVAL1 ç OFFSETVAL 5à3 5ê3:Ùcharactor? 5ô3 Ê: 35þ3 Ó FOUND Í &4 W54 TARGTYPE ç IMMED8 ï IMMED16 r54 TARGVAL1 ç CHARVAL |54 5&4:Ùstring? 504 ÿ(TARGET$,) èæ "'" Í X4 Æ5:4 TARGTYPE ç STRING Ï5D4 ×5N4:Ù 6X4:Ùnot found? assume near label or mem ref. (error on pass 2) x6b4 PASS ç Í #,"****Error: Undefined symbol ";TARGET$: ERRS ç ERRS é 6l4 TARGTYPE ç NEAR ï MEM 6v4 Ì64:Ù******************************************* ÿ64:Ù* SUBROUTINE TEST_NUMBER * 274:Ù* Trys to interpret TARGET$ as a number. * e74:Ù* If sucessful, sets FOUND true, NUMVAL * 7¨4:Ù* to its' value and NUMTYPE to its' type. * Ë7²4:Ù******************************************* Ó7¼4:Ù å7Æ4FOUND ç FALSE 8Ð4TN$ ç TARGET$ :Ùworking copy 8Ú4:Ù #8ä4:Ùhex number? A8î4 ÿ(TN$,) èæ "H" Í z5 T8ø4 :Ùlop off H s85 TN$ ç ÿ(TN$,ÿ(TN$)ê) 8 5 :Ùscan for non-hex digits (exit) ¨85 I ç Á8 5 I ç Ì ÿ(TN$) Û8*5 C$ ç ÿ(TN$,I,) 945 Ø("0123456789ABCDEF",C$) ç Í 9>5 I '9H5 :Ùget value F9R5 NUMVAL ç ÿ("&H" é TN$) `9\5 :Ùset type, return m9f5 Ô5 u9p5:Ù 9z5:Ùdecimal number? ´95 :Ùscan for non-dec digits (exit) Í95 I ç Ì ÿ(TN$) ç95 C$ ç ÿ(TN$,I,) :¢5 Ø("0123456789-+",C$) ç Í :¬5 I /:¶5 :Ùget value G:À5 NUMVAL ç ÿ(TN$) O:Ê5:Ù b:Ô5:Ùsucess exit t:Þ5 FOUND ç TRUE Ø:è5 ÿ(ÿ(NUMVAL)) è Í NUMTYPE ç IMMED16 ï IMMED8 :¡ NUMTYPE ç IMMED16 Þ:ò5 ;ü5:Ù******************************************** F;6:Ù* SUBROUTINE MEMREF * z;6:Ù* Trys to interpret target$ as a direct * ®;6:Ù* mem ref. If sucessful, sets FOUND true, * â;$6:Ù* & MEMADDR to the address referanced. * <.6:Ù******************************************** <86:Ù >