;------------------------------------------------------------------------------ ; ; "zasmb" ; ; (C) P.F.Ridler 1985 ; ; ; This program assembles a file of "Zilog" mnemonic source code and produces ; from it an excuteable .COM file or an "Intel" Hex format file. ; ; The command line for execution is ; ; zasmb [d:]name[.ext] [hex] ; ; ; Free use is granted for educational and private, non-commercial purposes ; only. ; ; Copies of the program may be made for backup purposes and for private ; exchange so long as this notice remains within the program, ; but the program may not be circulated by way of trade nor be entered ; into a communications network. ; ; Enquiries about other uses should be addressed to: ; ; P.F.Ridler, ; 4, Lewisam Ave., ; Chisipite, ; ZIMBABWE. ; ;----------------------------------------------------------------------------- ; ; Z80 assembler ; ; latest change 22 Jan 86 ; ; "phase" error checking introduced ; "org" error message improved 22 Jan 86 ; origin for .HEX changed to 0000H 22 Jan 86 ;2.0 Intel "Hex" output 25 Dec 85 ;1.5 "include" nested 24 Nov 85 ;1.4 hasher changed to just adding ASCII 21 Sep 85 ; going mad on " l " 27 Jul 85 ;1.3 return to editor 27 Jul 85 ; "ld a, " fixed 27 Jul 85 ; abort if "include" missing in pass 1 9 Jul 85 ; push sp, ld sp,de fixed 30 Apr 85 ; precedence in "xprshn" 18 Feb 85 ; "db 'aaaa'," 10 Feb 85 ; variable length operator table 8 Feb 85 ;1.2 conditional assembly 8 Feb 85 ; "ld (hl),' '" gives value error 26 Dec 84 ; " equ N" fixed 11 Dec 84 ; "read" fixed 10 Nov 84 ; "read" files 29 Oct 84 ; "arop a, " fixed 26 Oct 84 ; delete .COM file if errors 26 Oct 84 ;1.1 hash symbol table search 20 Oct 84 ; string search and length modified 19 Oct 84 ; multiple definition check added 13 Oct 84 ;1.0 started 8 Sep 84 ; ;------------------------------------------------------------------------------ ; wboot equ 0000H cdrive equ 0004H bdos equ 0005H dffcb equ 005CH ; bel equ 7 tab equ 9 lf equ 10 cr equ 13 eof equ 26 esc equ 27 ; true equ 1 false equ 0 ; debugs equ false ; notype equ 0 ;expression types numtyp equ 1 namtyp equ 2 strtyp equ 3 pctype equ 4 onebyt equ 5 twobyt equ 6 izreg equ 7 regtyp equ 8 ; pseudop equ 14 ; codtyp equ 11H ;line types comtyp equ 12H dstyp equ 13H dbtyp equ 14H equtyp equ 15H orgtyp equ 16H ; addhl equ 86H ;some necessary opcodes adchl equ 8EH sbchl equ 9EH jpopc equ 0C3H ; creg equ 11H ;single registers areg equ 17H bcreg equ 20H ;register pairs dereg equ 21H hlreg equ 22H spreg equ 23H ixreg equ 24H iyreg equ 25H afreg equ 26H ireg equ 18H rreg equ 19H ; rmask equ 10H ;register masks rpmask equ 20H ; maxnch equ 7 ;max. no. of characters in name ovrhds equ 5 ;link, address and flag bytes ; bffsiz equ 512 ;no. of bytes in source buffers maxlvl equ 4 ;max. level for "include"'s edit equ true ;set this false if editor interaction ; not possible ; ; org 100H ; jp zasmb ; ccp ds 2 z80ext db 'Z80' ;source file extension comext db 'COM' ;object " " hexext db 'HEX' ;"Hex" " " lstext db 'LST' ;list " " ; nstnt dw 0 ;no. of symtab entries nstsr dw 0 ;no. of symtab searches taddr ds 2 ;^transfer ("dma") address fcb ds 2 ;^fcb to be used ; ; ; next group of storage must be contiguous ; errflg db ' ' ;error character for this line lnnobf db ' ' ;holds (5) digits of line number db ' ' pcbuff db ' ' ;holds (4) digits of "pc" db ' ' codbff db ' ' ;holds digits of code db ' ' ; linbff ds 80H ;holds source line lnbptr ds 2 ;points to next char in line buffer ; lintyp ds 1 ;type of line to display pc ds 2 ;current program counter pcstart dw 100H pchex ds 2 ;auxiliary pc for "Hex" length ds 2 ;length of current instruction or data datfas ds 2 inst datbff ds 80 ;current instruction (or data from db) passno ds 1 ;current pass. pass 1=0, pass 2=-1 namlth ds 1 ;char count in "nambff" nambff ds 16 ;holds current name datlft ds 1 ;no of bytes of data left to display regflg ds 1 ;flags if expression is name endflg ds 1 ;end of program flag ; (to allow printing of end line) havlbl ds 1 ;true if line has label opcode ds 2 ;current opcode from symbol table reg1 ds 1 ;register code, arg 1 reg2 ds 1 ;register code, arg 2 savval ds 2 ;saved contents of "xprval" lstflg ds 1 ;listing flag lstcls ds 1 ;list file close flag temp ds 2 ;temp 2 byte area mult ds 2 ;radix of number system stfas ds 2 ;address of next symbol table entry stend ds 2 ;last available space for symtab udfflg ds 1 ;undefined flag from "xprshn", udfptr ds 2 ;pointer to error col nerrs ds 2 ;no. of errors lnndx ds 2 ;index to "lineno" for display nlines ds 2 ;line number in current segment totlns ds 2 ;total no. of lines switch ds 1 ;flag to show if i/p file changed hexflg ds 1 ;generate "Hex" if true ; ; include d:zasmb.z81 ; ; getnam push hl ;collect name and put it into "nambff" push de push bc ld hl,nambff ld a,' ' ;nambff=' ' ld (hl),a ld de,nambff+1 ld bc,15 ldir ld hl,nambff ld b,1 ;length call readch ;get next non-space char gtnm1 cp a,'a' ;allow "a".."z","0".."9","_","@" jp c,gtnm2 cp a,'z'+1 jp c,gtnm3 gtnm2 cp a,'@' jr z,gtnm3 gtnm21 cp a,'_' jr z,gtnm3 cp a,'@' jr z,gtnm3 cp a,'0' jr c,gtnm9 ;<"0" cp a,'9'+1 jr nc,gtnm9 ;>"9" gtnm3 ld (hl),a ;put l/c char into "nambff" inc hl inc b push hl ld hl,(lnbptr) ;get next char from line buffer ld a,(hl) call uctolc inc hl ld (lnbptr),hl pop hl jp gtnm1 ; gtnm9 ld a,b ld (namlth),a ;length, including count call backup pop bc pop de pop hl ret ; ; numptr ds 2 ; numarg push hl ;convert digits to value push de ;hex, binary and decimal allowed push bc ld hl,(lnbptr) ;save pointer to start of number ld (numptr),hl ld b,0 ;length counter numg1 ld a,(hl) inc hl call uctolc cp a,'0' jr c,numg2 cp a,'9'+1 jr c,numg11 cp a,'a' jr c,numg2 cp 'f'+1 jr nc,numg2 numg11 inc b jp numg1 ; numg2 cp a,'h' ;radix? jp nz,numg21 ld de,16 ; radix 16 jp numg31 ; numg21 dec hl dec hl ld a,(hl) call uctolc cp a,'b' ;binary? jp nz,numg22 dec b ld de,2 ;radix 2 jr numg3 numg22 cp a,'d' jr nz,numg23 dec b ld de,10 jr numg3 numg23 ld de,10 ;default radix ; numg3 inc hl numg31 ld (lnbptr),hl ld (mult),de ld de,0 ;value=0 ; numg5 ld hl,(numptr) ld a,(hl) inc hl ld (numptr),hl call uctolc cp a,'a' jp c,numg51 add a,9 ;for "a"-"f" numg51 and a,0FH push bc ;save counter push af ;get binary value of this digit ld hl,(mult) call mltply pop af ld e,a ld d,0 add hl,de ;add in new digit ex de,hl pop bc ;restore counter dec b jp nz,numg5 ;loop if more ; ld (tval),de ;save value pop bc pop de pop hl ret ; ; strlth ds 2 ; gtstrg push hl ;get a string in single quotes push de ;mustn't use "readch" to avoid case conversion ld bc,00 ld (strlth),bc ld hl,(lnbptr) ld de,(datfas) gtst1 ld a,(strlth) ;if (string_length>=80) cp a,80 ; error jr z,gtst5 ld a,(hl) ;get next character inc hl cp a,cr ;if (ch==cr) jr z,gtst5 ; error cp a,'''' ;if (ch=="'") jr nz,gtst2 ld a,(hl) ; get character. no "uctolc" here inc hl cp a,'''' ; if (ch<>"'") jr nz,gtst6 ; end of string gtst2 ld (de),a ;string[length]=ch inc de ld bc,(strlth) ;length=length+1 inc bc ld (strlth),bc jr gtst1 gtst5 call aerror gtst6 ld bc,(strlth) ;if (string_length=0) ld a,b or a,c jr nz,gtst61 inc bc ; string_length=1 ld (strlth),bc xor a,a ; string[1]= ld (de),a inc de gtst61 ld (datfas),de dec hl ;put last char back ld (lnbptr),hl pop de pop hl ret ; ; namarg call getnam ;argument is a name call stsrch jp nz,namg1 ;if undefined ld a,(hl) ; keep address ld (tval),a inc hl ld a,(hl) ld (tval+1),a inc hl ld a,(hl) ; save register flags ld (regflg),a jr namg2 ; namg1 ld hl,0 ;process undefined name ld (tval),hl ;set value to 0000 ld a,(udfflg) or a,1 ld (udfflg),a ;set undefined flag ld hl,(lnbptr) ld (udfptr),hl namg2 ret ; ; ; expression evaluator (returns expression value in "xprval") ; ; valid operators are: +, -, *, / , \ (mod), & (and), | (or) and ~ (not) ; elements are: names, numbers, and '$' for pc ; fcttyp ds 1 fctval ds 2 ; factor push hl push de ld hl,00 ld (fctval),hl ld a,notype ld (fcttyp),a call readch ;readch if debugs call dspnxt db ' >factor ch=',0 call dspall endif cp a,'a' ;if (ch in [a..z,'@']) jr nc,fctr0 cp a,'@' jr nz,fctr1 jr fctr01 fctr0 cp a,'z'+1 jr nc,fctr1 fctr01 call backup call namarg ; name ld a,(regflg) or a,a jr nz,fctr02 ld a,twobyt ld (fcttyp),a ld hl,(tval) ld (fctval),hl jp fctr6 fctr02 cp a,izreg ld hl,00 ld (fctval),hl jr nz,fctr03 ld a,twobyt ld (fcttyp),a jp fctr6 fctr03 ld a,regtyp ld (fcttyp),a jp fctr6 fctr1 cp a,'0' ;elseif (ch in [0..9]) jr c,fctr2 cp '9'+1 jr nc,fctr2 call backup call numarg ; number ld a,h cp a,0 jr z,fct11 cp a,0FFH jr nz,fct12 fct11 ld a,onebyt jr fct13 fct12 ld a,twobyt fct13 ld (fcttyp),a ld hl,(tval) ld (fctval),hl jp fctr6 fctr2 cp a,'[' ;elseif (ch=="[") jr nz,fctr3 call arxprn ; arxprn ld hl,(axpval) ld (fctval),hl call readch ; readch cp a,']' ; if not(ch==']') call nz,serror ; serror jr fctr6 fctr3 cp a,'$' ;elseif (ch=='$') jr nz,fctr4 ld hl,(pc) ld (fctval),hl ld a,twobyt ld (fcttyp),a jr fctr6 fctr4 cp a,'''' ;elseif (ch=="'") jr nz,fctr5 call gtstrg ; getstring ld a,(strlth) cp a,1 ; if (length(string)<>1) error call nz,serror ld hl,(datfas) ; datfas=datfas-1 dec hl ld (datfas),hl ld a,(hl) ; factval=datfas ld (fctval),a ld a,onebyt ; facttyp=onebyte ld (fcttyp),a jr fctr6 fctr5 call backup ;else ld hl,00 ; put ch back ld (fctval),hl fctr6 if debugs call dspnxt db ' term ',0 endif call factor term1 call readch ;readch cp a,'*' ;case ch of jr nz,term11 ld hl,(fctval) ; '*' : push hl ; push(factval) call factor ; factor ld de,(fctval) pop hl ; pop(fact1val) call mltply ; factval=fact1val*factval jr term14 term11 cp a,'/' jr nz,term12 ld hl,(fctval) ; '/' : push hl call factor ld de,(fctval) pop hl call div16 ; factval=fact1val/factval jp term14 term12 cp a,'\' jr nz,term13 ld hl,(fctval) push hl call factor ld de,(fctval) pop hl call div16 ; factval=fact1val mod factval ex de,hl jp term14 term13 cp a,'&' ; '&' jr nz,term5 ld hl,(fctval) push hl call factor ld de,(fctval) pop hl ld a,h ; factval=fact1val & factval and a,d ld h,a ld a,l and a,e ld l,a ; term14 ld (fctval),hl jp term1 term5 call backup term6 ld a,(fcttyp) ld (trmtyp),a ld hl,(fctval) ld (trmval),hl if debugs call dspnxt db ' arxprn ch=',0 call dspall endif cp a,'+' ;aop0=monadic operator jr z,arxp0 cp a,'-' jr z,arxp0 cp a,'~' jr z,arxp0 call backup ld a,'+' arxp0 ld (aop0),a call term ld a,(aop0) ;case aop0 of cp a,'+' ; '=' :do nothing jr z,arxp1 cp a,'-' jr nz,arxp01 ld hl,00 ; '-' : ld de,(trmval) or a,a sbc hl,de ld (trmval),hl jp arxp1 arxp01 cp a,'~' jr nz,arxp02 ; '~' : arxp02 ; else :do nothing ; arxp1 call readch ;while (ch in ["+","-","~","|"]) cp a,'+' ; case ch of jr nz,arxp11 ld hl,(trmval) ; '+' : push hl ; push(termval) ld a,(regflg) push af call term ; term pop af ld (regflg),a ld de,(trmval) ; pop(term1val) pop hl ; termval=term1val+termval add hl,de jr arxp19 arxp11 cp a,'-' jr nz,arxp12 ld hl,(trmval) ; '-' : push hl ld a,(regflg) push af call term pop af ld (regflg),a ld de,(trmval) pop hl or a,a sbc hl,de jr arxp19 arxp12 cp a,'~' jr nz,arxp13 ld hl,(trmval) ; '~' : push hl call term ld de,(trmval) pop hl ld a,h xor a,d ld h,a ld a,l xor a,e ld l,a jr arxp19 arxp13 cp a,'|' jr nz,arxp2 ld hl,(trmval) ; '|' : push hl call term ld de,(trmval) pop hl ld a,h or a,d ld h,a ld a,l or a,e ld l,a ; arxp19 ld (trmval),hl jp arxp1 arxp2 call backup arxp3 ld a,(trmtyp) ld (axptyp),a ld hl,(trmval) ;axpval=termval ld (axpval),hl if debugs call dspnxt db ' xprshn ',0 endif ; xor a,a ld (op),a ;op=nop ld (regflg),a ;regflg=0 ld a,notype ld (xprtyp),a ld hl,0 ld (xprval),hl ;value=0 call readch ;readch cp a,'a' jr nc,xprn0 ;if (ch in letters) cp a,'' jr nz,xprn1 jr xprn01 xprn0 cp a,'z'+1 jr nc,xprn1 xprn01 call backup call arxprn ld a,(axptyp) ld (xprtyp),a ld hl,(axpval) ld (xprval),hl jp xprn9 xprn1 cp a,'''' ;elseif (ch=="'") jr nz,xprn2 call gtstrg ; getstring ld a,(strlth) ; if (string_length>1) cp a,2 jr c,xprn11 ld e,(hl) ; exprnvalue= inc hl ld d,(hl) ld (xprval),de ld a,strtyp ; exprntype=string ld (xprtyp),a jp xprn9 xprn11 ld hl,(datfas) ; else #have string[1] dec hl ld (datfas),hl ; datfas=datfas-1 ld a,(hl) push af ; push(ch) call arxprn ; arithexprn pop af ; pop(ch) ld hl,(axpval) ; exprnval=arexpval+ch ld d,0 ld e,a add hl,de ld (xprval),hl ld a,onebyt ; exprtype=onebyte ld (xprtyp),a jp xprn9 ; xprn2 call backup ;else call arxprn ld a,(axptyp) cp a,notype jr nz,xprn21 call serror jr xprn9 xprn21 ld (xprtyp),a ld hl,(axpval) ld (xprval),hl ; xprn9 if debugs call dspnxt db ' or found ld (nlines),hl call dspdot ld hl,linbff ;reset line buffer pointer ld (lnbptr),hl gtln1 call getbyt ;get a byte from disc buffer cp a,eof ret z ;if return gtln2 ld (hl),a inc hl cp a,lf jr nz,gtln1 ;else loop until found ret ; ; backup push hl ;put character back into line buffer ld hl,(lnbptr) ;after look ahead dec hl ld (lnbptr),hl pop hl ret ; ; dsfill push af ;fill "ds" space with s push hl ld a,(passno) ;if (pass2) or a,a jr z,dsfl2 ld a,(dsflag) ; if (dsflag) or a,a jr z,dsfl11 ld hl,(dslgth) ; for i=1 upto dslgth dsfl1 ld a,h or a,l jr z,dsfl11 xor a,a ; writebyte(0) call wrbyte dec hl jr dsfl1 dsfl11 xor a,a ; dsflag=false ld (dsflag),a ld hl,00 ; dslgth=0 ld (dslgth),hl dsfl2 pop hl pop af ret ; ; ; set error flags ; aerror push af ld a,'A' ;argument error jr error ; berror push af ld a,'B' jr error ; ferror push af ld a,'F' ;"include" file not found jr error ; lerror push af ld a,'L' ;lable too long jr error ; merror push af ld a,'M' ;multiple definition jr error ; oerror push af ld a,'O' ;op-code jr error ; rerror push af ld a,'R' ;range error jr error ; serror push af ld a,'S' ;syntax error jr error ; uerror push af ld a,'U' ;undefined variable jr error ; verror push af ld a,'V' ;value error jr error ; xerror push af ld a,'X' ;extra character on line jr error ; error ld (errflg),a ;set error flag push hl ld hl,(lnbptr) ld (errptr),hl pop hl pop af ret ; ; stbuff ds 15 ;buffer for symbol table entry symadr ds 2 ;^address of address in last "ptn2st" ; ; ds 128 ;just the usual stack stack equ $ ; ; ; zasmb ld sp,stack call setup ;display heading and initialise xor a,a ld (passno),a ;indicate pass 1 ; pass2 xor a,a ld (dsflag),a ;ds_flag=false ld (lstcls),a ;list_close=false ld (lstflg),a ;list_flag=off ld a,'.' ld (chdsp),a ld hl,-1 ld (nlines),hl ;nlines=-1 inc hl ld (level),hl ;include_level=0 ld (totlns),hl ;total_lines=0 ld (nerrs),hl ;nerrors=0 ld (nstsr),hl ld (dslgth),hl ;ds_length=0 ld hl,(pcstart) ld (pc),hl ;pc=pcstart (100H for .COM, 0000H for .HEX) ld (pchex),hl ld hl,srcbff ;set up to read from source file ld (ipbuff),hl ld hl,srcend ld (ipbndx),hl ld (ipbend),hl ld hl,srcfcb ld (pipfcb),hl ; ; ; main loop - read a source line ; process label and opcode ; print line (unless option=n) ; output hex (if necessary) ; back to main loop for next line ; ; next ld sp,stack ld hl,00 ld (xprval),hl ld (length),hl ld hl,datbff ld (datfas),hl ld a,false ld (udfflg),a ld (endflg),a ld (switch),a ;i/p file switched=false ld (havlbl),a ld a,' ' ld (errflg),a ld a,codtyp ld (lintyp),a call getlin ;get next line cp a,eof jr nz,next0 ld a,(level) ;if (level==0) or a,a jp z,endop1 ; jump to endop1 ld a,true ;else ld (switch),a ; sitch=true next0 ld a,(linbff) ;get char in col 0 cp a,tab jp z,next2 ;tab, so no label cp a,cr jp z,ndstmt ;null line cp a,' ' jp z,next2 ;no label cp a,';' jr nz,next1 ld a,comtyp ld (lintyp),a jp ndstmt next1 ld a,true ld (havlbl),a call getnam ;get label call readch cp a,':' ;ignore ":" call nz,backup ; calculate length of label and build entry ld b,1 ;length ld hl,nambff ld de,stbuff+1 next11 ld a,(hl) ;collect label cp a,' ' jr z,next12 ld (de),a inc hl inc de inc b jr next11 next12 ld a,b ;check name length cp a,maxnch+2 ;allow for length byte jr c,next13 call lerror jp ndstmt ;else label error next13 ld (stbuff),a ; length ex de,hl xor a,a ; link=00 inc hl ld (hl),a inc hl ld (hl),a ld a,(pc) ld (hl),a inc hl ; address=pc ld a,(pc+1) ld (hl),a inc hl ld (hl),0 ; type=0 ld a,(passno) or a,a ;if pass=0 jr nz,next15 call stsrch ; stsrch jr nz,next14 ; if found ld hl,(flgadd) ; flag as multiply defined ld a,(hl) or a,80H ld (hl),a jr next2 ;else next14 call ptn2st ; enter symbol into table ld (symadr),hl ; save address for "equ" jr next2 next15 call stsrch ;elseif (pass=2) #check phase error!!! jr nz,next16 ; stsrch #must be found!!! ld hl,(flgadd) ; if found ld a,(hl) and a,80H ; if bit 7 set jr z,next2 call merror ; set "multiply defined" flag jr next2 ; else next16 ld a,1 ; set "undefined" flag ld (udfflg),a ld hl,(lnbptr) ld (udfptr),hl next2 call getnam ;process opcode ld a,(nambff) cp a,' ' jp z,ndstmt ;if no opcode must be comment call opsrch ;search op-code table jr z,next21 call oerror ;op-code error jp ndstmt next21 ld a,(hl) ld (opcode),a inc hl ld a,(hl) ld (opcode+1),a ;save opcode inc hl ld a,(hl) ;get type byte cp a,pseudop call c,dsfill dec a add a,a ;-1 and double for table index ld e,a ld d,0 ld hl,typtbl add hl,de ld e,(hl) inc hl ld d,(hl) ex de,hl jp (hl) ;dispatch to proper instruction type ; ; include d:zasmb.z82 ;pseudo ops ; ; ; e n d o f s t a t e m e n t p r o c e s s i n g ; ; chkend push af ;check that there is nothing else on line call readch cp a,';' ;??? jr z,chnd1 cp a,cr jr z,chnd1 cp a,lf jr z,chnd1 cp a,' ' jp p,chnd0 add a,40H chnd0 ld (xch),a call xerror ;extra character(s) on line chnd1 pop af ret ; ; end1 ld (inst),a ld a,1 jp endlth ; ; end2 ld (inst),hl ld a,2 jr endlth ; ; endahl ld (inst),a ld (inst+1),hl ld a,3 jr endlth ; ; endhla ld (inst),hl ld (inst+2),a ld a,3 jr endlth ; ; end4 ld (inst),hl ld (inst+2),de ld a,4 jp endlth ; ; endlth ld (length),a ; ndstmt ld a,(errflg) ;if (not error) cp a,' ' call z,chkend ; check end ld a,(nocode) ;if (nocode) cp a,true jr nz,ndst0 ld hl,00 ; length=0 ld (length),hl ld a,comtyp ; linetype=comment ld (lintyp),a ndst0 ld a,(errflg) ;if (errflg=='F') cp a,'F' jr nz,ndst01 call dsplin ; display line call dsperr ; display error jp abort ; abort ndst01 ld a,(passno) ;elseif (pass2) or a,a jp z,ndst6 ld a,(udfflg) ; if (undefined) or a,a jr z,ndst1 ld hl,(udfptr) ld (lnbptr),hl call uerror ; errflg='U' ndst1 ld a,(errflg) ; if (errflg<>" ") cp a,' ' jr z,ndst2 call dsplin ; display line call dsperr ld hl,(nerrs) ; nerrors=nerrors+1 inc hl ld (nerrs),hl jr ndst3 ndst2 ld a,(lstflg) ; if ((lstflg)or(errflg)) or a,a jp z,ndst5 ndst3 call lstlin ; send line to .LST file ld a,(errflg) ; if (errflg<>" ") cp a,' ' jp z,ndst5 call lsterr ndst5 ld a,(length) ; if ((length>0)and ld b,a or a,a jr z,ndst6 ld a,(lintyp) ; (line_type<>"ds")) cp a,dstyp jr z,ndst6 ld hl,inst ; for i=1 to length ndst51 ld a,(hl) inc hl ndst55 call wrbyte ; write_byte djnz ndst51 ; ndst6 ld a,(switch) ;if (input switched) cp a,true jr nz,ndst61 xor a,a ld (ndots),a ; ndots=0 ld hl,(totlns) ld de,(nlines) inc de ;line numbers start from 0 add hl,de ld (totlns),hl ld hl,level ; level=level-1 dec (hl) ld hl,ch4dsp ld de,(level) add hl,de ld a,(hl) ld (chdsp),a ld hl,buffers ld de,(level) add hl,de add hl,de ld a,(hl) inc hl ld h,(hl) ld l,a ;HL=^index[level] ld e,(hl) inc hl ld d,(hl) inc hl ld (ipbndx),de ld e,(hl) inc hl ld d,(hl) inc hl ld (nlines),de ld (pipfcb),hl ld de,36 add hl,de ld (ipbuff),hl ld de,bffsiz add hl,de ld (ipbend),hl ld hl,(pipfcb) call dspfnm ndst61 ld hl,(pc) ;pc=pc+length ld de,(length) add hl,de ld (pc),hl ld a,(endflg) ;if not endflag or a,a jp z,next ; go process next line ld a,(passno) cpl ;pass=not pass ld (passno),a cp a,0 jp z,endit ; xor a,a ;reset current extent ld hl,(pipfcb) ld bc,12 add hl,bc ld (hl),a ld hl,(pipfcb) ;reset current record ld bc,32 add hl,bc ld (hl),a call opnfil call dspnxt db cr,lf,lf,'Pass 2 ',cr,lf,0 ld a,8 ld (ndots),a ld hl,(pipfcb) call dspfnm xor a,a ;reset end-line flag ld (endflg),a jp pass2 ; ; endit ld a,(hexflg) ;if (hex output) cp a,true jr nz,endit0 call wrhxbff ; move last hex record to disc call wrhxbff ; terminator record endit0 ld a,(objfas) ;if not new record cp a,128 jr z,endit1 ld a,eof ; put ^Z into write buffer call wrbyte ld a,128 ; force write endit1 ld (objfas),a call wrbyte ld de,objfcb ld (fcb),de ld hl,(nerrs) ;if (nerrors==0) ld a,h or a,l jr nz,endt11 call clsfil ; close .COM file jr nz,endit2 call dspnxt db cr,lf,bel,'Cannot close output file. Disc full?' jp abort ;else endt11 call delfil ; delete .COM file ; endit2 ld a,cr call wrlist ld a,lf call wrlist ld a,(lstfas) ;if not new record cp a,128 jr z,endt21 ld a,eof ; put ^Z into list buffer call wrlist ld a,128 ; force write endt21 ld (lstfas),a call wrlist ld de,lstfcb ld (fcb),de ld a,(lstcls) ;if (list_close) or a,a jr z,endt22 call clsfil ; close .LST file jr nz,endit3 call dspnxt db cr,lf,bel,'Cannot close output file. Disc full?' jp abort ;else endt22 call delfil ; delete file ; endit3 ld hl,(pc) dec hl ld de,lstadd ld a,h call cnv2hex ld a,l call cnv2hex ; call dspnxt db cr,lf,lf,'Last address used = ' lstadd db 'xxxxH',0 ; ld hl,(stfas) ld de,nxtadd ld a,h call cnv2hex ld a,l call cnv2hex call dspnxt db cr,lf,'Next symbol address = ' nxtadd db 'xxxxH',0 ; ld hl,(stfas) ld de,symtab or a,a sbc hl,de ld de,stlgth ld a,h call cnv2hex ld a,l call cnv2hex call dspnxt db cr,lf,'Symbol table length = ' stlgth db 'xxxxH',0 ; call dspnxt db cr,lf,lf,'No. of symbol table searches = ',0 ld hl,(nstsr) ld de,lnnobf ;errbff call decval ld hl,lnnobf ;errbff call dspdec ; call dspnxt db cr,lf,'No. of symbol table entries = ',0 ld hl,(nstnt) ld de,lnnobf ;errbff call decval ld hl,lnnobf ;errbff call dspdec ; call dspnxt db bel,cr,lf,lf,'Assembly complete. ',0 ; ld hl,(nlines) ;totlns+1 to account for line 0 ld de,(totlns) add hl,de inc hl ld de,lnnobf call decval ld hl,lnnobf call dspdec call dspnxt db ' lines, ',0 ld hl,(nerrs) ld de,0 call cphlde jr nz,endit5 call dspnxt db 'no errors',0 jr endit6 endit5 ld hl,(nerrs) ld de,lnnobf ;errbff call decval ;put "nerrs" into "lineno" ld hl,lnnobf ;errbff call dspdec ;display "lineno" call dspnxt db ' error',0 ld hl,(nerrs) ld de,1 call cphlde jp z,endit6 ld a,'s' call dspch endit6 ld a,'.' call dspch jp wboot ; abort call dspnxt db bel,cr,lf,lf,'Assembly abandoned.',0 jp wboot ; ; ; ; Opcode Table ; ; Each symbol table entry is of varying length. ; ; The first byte contains the length of the opcode mnemonic plus one. ; ; The second byte holds the first character of the name. ; ; Following the name are 2 bytes holding the the order code ; and then a 1 byte type. ; ; The table is searchec by hashing on the first character of the ; menmonic and then scanned serially. ; ; ; op-code table ; ; index to alphabetical subsections ; ; opcndx dw opcta,opctb,opctc,opctd,opcte,opctf,opct0 dw opcth,opcti,opctj,opct0,opctl,opct0,opctn dw opcto,opctp,opct0,opctr,opcts,opct0,opct0 dw opct0,opct0,opctx,opct0,opct0 ; ; op-code table. ; ; opcodes should be in order of frequency within sections. ; opcta db 3 db 4,'add', 80H, 86H, 6 db 4,'and', 0A0H,0A6H, 6 db 4,'adc', 88H, 8EH, 6 opctb db 1 db 4,'bit', 046H, 0,12 opctc db 8 db 5,'call', 0CDH,0C4H, 3 db 3,'cp', 0B8H,0BEH, 6 db 4,'cpd', 0EDH,0A9H, 1 db 5,'cpdr', 0EDH,0B9H, 1 db 4,'cpi', 0EDH,0A1H, 1 db 5,'cpir', 0EDH,0B1H, 1 db 4,'cpl', 02FH, 0, 1 db 4,'ccf', 03FH, 0, 1 opctd db 10 db 3,'db', 3, 0,14 db 3,'ds', 2, 0,14 db 3,'dw', 4, 0,14 db 4,'dec', 05H, 0BH,13 db 5,'defb', 3, 0,14 db 5,'defs', 2, 0,14 db 5,'defw', 4, 0,14 db 5,'djnz', 10H, 0, 4 db 4,'daa', 27H, 0, 1 db 3,'di', 0F3H, 0, 1 opcte db 6 db 3,'ei', 0FBH, 0, 1 db 3,'ex', 0EBH, 0,10 db 4,'equ', 1, 0,14 db 4,'exx', 0D9H, 0, 1 db 4,'end', 5, 0,14 db 6,'endif', 10, 0,14 opctf db 1 db 5,'forg', 11, 0,14 opcth db 1 db 5,'halt', 076H, 0, 1 opcti db 11 db 4,'inc', 04H, 03H,13 db 3,'in', 0DBH, 0, 7 db 4,'ind', 0EDH,0AAH, 1 db 5,'indr', 0EDH,0BAH, 1 db 4,'ini', 0EDH,0A2H, 1 db 5,'inir', 0EDH,0B2H, 1 db 8,'include', 8, 0,14 db 3,'if', 9, 0,14 db 4,'im0', 0EDH, 46H, 1 db 4,'im1', 0EDH, 56H, 1 db 4,'im2', 0EDH, 5EH, 1 opctj db 2 db 3,'jr', 018H, 0, 4 db 3,'jp', 0C3H, 0C2H,3 opctl db 6 db 3,'ld', 0, 0, 8 db 4,'ldd', 0EDH,0A8H, 1 db 5,'lddr', 0EDH,0B8H, 1 db 4,'ldi', 0EDH,0A0H, 1 db 5,'ldir', 0EDH,0B0H, 1 db 5,'list', 7, 0,14 opctn db 2 db 4,'neg', 0EDH, 44H, 1 db 4,'nop', 000H, 0, 1 opcto db 7 db 3,'or', 0B0H,0B6H, 6 db 4,'out', 0D3H, 0, 7 db 4,'org', 6, 0,14 db 5,'otdr', 0EDH,0BBH, 1 db 5,'otir', 0EDH,0B3H, 1 db 5,'outd', 0EDH,0ABH, 1 db 5,'outi', 0EDH,0A3H, 1 opctp db 2 db 4,'pop', 0C1H, 0, 9 db 5,'push', 0C5H, 0, 9 opctr db 17 db 4,'ret', 0C9H, 0,11 db 3,'rl', 10H, 0, 2 db 4,'rla', 17H, 0, 1 db 4,'rlc', 00H, 0, 2 db 5,'rlca', 07H, 0, 1 db 4,'rld', 0EDH, 6FH, 1 db 3,'rr', 18H, 0, 2 db 4,'rra', 1FH, 0, 1 db 4,'rrc', 08H, 0, 2 db 5,'rrca', 0FH, 0, 1 db 4,'rrd', 0EDH, 67H, 1 db 5,'read', 8, 0,14 db 4,'rst', 0C7H, 0, 5 db 4,'res', 086H, 0,12 db 5,'reti', 0EDH, 4DH, 1 db 5,'retn', 0EDH, 45H, 1 db 6,'reorg', 12, 0,14 opcts db 7 db 4,'sub', 90H, 96H, 6 db 4,'sbc', 98H, 9EH, 6 db 4,'scf', 37H, 0, 1 db 4,'sla', 20H, 0, 2 db 4,'sra', 28H, 0, 2 db 4,'srl', 38H, 0, 2 db 4,'set', 0C6H, 0,12 opctx db 1 db 4,'xor', 0A8H, 0AEH, 6 opct0 db 1 db 1,' ' ; ; cndtbl db 3,'nz' ;condition table db 2,'z ' db 3,'nc' db 2,'c ' db 3,'po' db 3,'pe' db 2,'p ' db 2,'m ' ; ; ; registers have to be entered by hashing. ; ; regtbl db 2,'b', 0,0, 0,0, 10H ;registers db 2,'c', 0,0, 0,0, 11H db 2,'d', 0,0, 0,0, 12H db 2,'e', 0,0, 0,0, 13H db 2,'h', 0,0, 0,0, 14H db 2,'l', 0,0, 0,0, 15H db 2,'a', 0,0, 0,0, 17H db 3,'bc', 0,0, 0,0, 20H db 3,'de', 0,0, 0,0, 21H db 3,'hl', 0,0, 0,0, 22H db 3,'sp', 0,0, 0,0, 23H db 3,'ix', 0,0, 0,0, 24H db 3,'iy', 0,0, 0,0, 25H db 3,'af', 0,0, 0,0, 26H db 2,'i', 0,0, 0,0, 18H db 2,'r', 0,0, 0,0, 19H ; ; ch4dsp db '.','_',',',':',';' ; ; pipfcb ds 2 ;holds address of current input fcb ; objfcb ds 1 ;output file control block ds 35 lstfcb ds 1 ;list " " " ds 35 ; ; buffers dw level0,level1,level2,level3,level4 ; level0 ds 2 ;index to buffer ds 2 ;current line no. srcfcb ds 36 ;fcb srcbff ds bffsiz ;buffer srcend equ $ ;end of buffer ; level1 ds 2 ;0 ds 2 ;2 ds 36 ;4 ds bffsiz ;40 ; level2 ds 2 ds 2 ds 36 ds bffsiz ; level3 ds 2 ds 2 ds 36 ds bffsiz ; level4 ds 2 ds 2 ds 36 ds bffsiz ; ipbndx ds 2 ;index for current input buffer (source or read) ipbuff ds 2 ;holds address of current input buffer ipbend ds 2 ;holds address of end of current input buffer ; ; objfas ds 2 ;object file buffer pointer objbff ds 128 ;object file buffer lstfas ds 2 ;list file buffer pointer lstbff ds 128 ;list file buffer ; ; ; hash table ; hshtbl ds 512 ; ; ; Symbol Table ; ; Each symbol table entry is of varying length. ; ; The first byte contains the length of the name plus one. ; ; The second byte holds the first character of the name. ; ; Following the name are 2 bytes of address (or value for "equs" ; and 1 byte of type (used in opcodes). ; ; db 'symtab>>' ; symtab ds 0 ;first available space in "symtab" ; ; end