IMD 1.18: 22/01/1996 6:46:55 micro cornucopia kaypro user group disk 17 z80 tools     17-DISK DOC CRC COMCRC DOC CRCKLISTCRC DASM COMJ DASM DOC !"#$DASM DOCT%&'()*+,-./DASM MAC0123456789:;<=>?DASM MAC@ABCDEFGHIJKLMNODASM MACPQRSTUVWXYZ[\]^_DASM MAC`abcdefghijklmnoDASM MACMpqrstuvwxyDASMZLG MACz{|}~DASMZLG MACDISASMBLDOC&README TXT KAYPRO DISK #17 Z80 TOOLS XLATE2.COM XLATE2.MAC XLATE2.DOC XLATE2 translates 8080 assembly language programs into Z80 assembly language. The output files may be assembled with MicroSoft's M80 assembler. This program is perfect for the Z80 assembly language programmer who has to work with 8080 programs from time to time. The output file can also be assembled with the CROWECPM assembler on Micro Cornucopia's disk KXLATE2 COM(XLATE2 DOCXLATE2 MACXLATE2 MACXLATE2 MAC&10 with a few modifications. Refer to XLATE2.DOC for more information on this super program. XLATE2.MAC is the M80 assembly language source. DASM.COM DASM.MAC DASMZLG.MAC DASM.DOC DISASMBL.DOC There have been several people who have called us that want a good dis- assembler but can't get around the unfriendly ZZSOURCE. DASM is a rewrite of ZZSOURCE that is much easier to use. The file DISASMBL.DOC contains information on the disassembly process for the first time user. DAS  M.DOC is the documentation for ZZSOURCE and describes the features of DASM. The assembly language source for this program is in the files DASM.MAC and DASMZLG.MAC. To verify all the files on this disk type: CRC *#"ɯ2i2}! "!"]]2 s : ~# ++FILE NOT FOUND++$: F*}’">͇†]<  CANNOT CLOSE CRCFILE$CRCKLISTCRCSK FULL: CRCFILE$  w# !]͐ DONE$!e S!]Q !eZ @ --> FILE: XXXXXXXX.XXX CRC = oS) \<‘@ ++OPEN FAILED++ !" !" * | ʹ) \!~2 #" Ý: ) > T : ) @ ++FILE READ Eth file - ! ~T #M M 2 2 2 2 ! >2 3o: : @ ***No CRC Files found***$> ʉ ʉw#: <2 P6: .6@ Can not parse string ! ~ʽT #ñM ! > 6 #6^#6! ~T #! 4M #x] #e w~ T #>2 @ - s M@ File not found ! 4 >2 o: G: „: G: „@ *Match* 2 ! 4@ <-- is, was --> : ) > T : ) M 2 ! 4<2 ~# @ Not a space between CRC values<2 G-CATALOG??? Using CRC Type CRC to verify all the files on this disk. Type CRC *.* F to generate CRC's for an entire disk and create a CRC file (CRCKLIST.CRC) for checking the CRC's of a copy of the disk etc. Omitting the F will suppress creation of a CRCKLIST.CRC file. *.* can be replaced with an unambiguous file name for checking just one file. RROR++ <* |): o% |g}o" 2  ; 0T ~T #~A > T > _h : F{͇2h2|: ʲ !\   :\2 ! \  \ ! \  \! \  \<7=Ɓo&   ]  2h2|2   ~$#~# x  : F} *}= ">͇1 ].”#””͡”››tK››͸›* =: =͔="  ʳ ª~#.  ¿~  #~  .+~#0:0~#!A.O.Gy~#0M0 K MMɷ:m2 FSÄCRCKLIST$$$››tK›, › **}|!"*{z*~]*"Ü  DISK FULL: CRCFILE$!"*~#CRC.COM 5.0 6/18/82CRCKFILE???!9" 1 M @ CRC Ver 5.0 CTL-S pauses, CTL-C aborts :] O@ ++Searching for CRCKLIST file++@ Now searching for "CRCKFILE" file++ !  1 .) F!  ͡]͸! ͔0CRCKLIST???CRCKFILE???!9" M à*,*.}|ډ!".*,{z{** u*.".G*.",!".***,}>*.#".ɯ22)! ",". <  NO FILECRC FILE$!   >. @ Checking wi match - : ̓ : J M @ Quantity of lines failed parse test - : ̓ : ~ M @ Quantity of file(s) not found - : ̓ * d͔  ͔ 0T  Җ Wyʩ 0T 0ztiil   --> FILE: XLATE2 .COM CRC = A9 5D --> FILE: XLATE2 .DOC CRC = A2 30 --> FILE: XLATE2 .MAC CRC = 8F 3C --> FILE: DASM .COM CRC = 5E B8 --> FILE: DASM .MAC CRC = E3 80 --> FILE: DASMZLG .MAC CRC = 44 0C --> FILE: CRC .COM CRC = B2 07 --> FILE: DASM .DOC CRC = 50 74 --> FILE: DISASMBL.DOC CRC = 5C BC --> FILE: CRC .DOC CRC = E5 81 --> FILE: 17-DISK .DOC CRC = 51 B8LD SP,HLADC A,ADD A,AND CP OR SBC A,SUB XOR DEC INC ADD HL, DEC INC LD A,LD POP PUSH RET RST @ LD  LD ADD A, ADC A, AND CP OR SUB SBC A, XOR IN A, OUT JR DJNZ JR LD JP CALL :LD A,*LD HL,"LD 2LD CALL JP RLC RRC RL RR SLA (SRA 8SRL @BIT RES SET *EX (SP),JP LD SP,POP PUSH ADD #INC +DEC 4INC 5DEC ADD A,ADC A,SUB x#͙*$,Kx#Kx#%,*>Hͣ#>Lͣ#Kx#/Kx#7*$,Kx##F"$!O͞ͻËX#"$F!͞ͻڋ*ʋ!#ڈ#ÈY#"$F!O ͞ͻ(ڋ*ʋ##Ècx#x#%*x#{X~!(!ͣx##x#ͅ*$#x##*$cx#,Kx#%,*Kx#%,*Kx##}##F!O͞ͻx : %*$( *$++"$##++ͅ%>Cͣ#*x#~>Iʺ>Dͣ#~x#>Rͣ#x#%,**$͙Kx#͙*$%,*Kxmbol Dump starting at symbol Ennnn,.symbol Enter symbol into table Fnnnn,ssss Find nnnn after ssss F or Fnnnn Cont Find or Find nnnn Issss,oooo Inc addrs>=ssss by oooo K.symbol Kill symbol from table L List next 20 lines Lssss,eeee List over range L,eeee List to eeee Lssss List 20 lines from ssss L=nn[,others] Set list default O Print current offset Onnnn Set new offset Pssss,eeee Generate program prolog Q Quiet prefix Rfilename.COM Read file @ offset+100H Rfilename.CTL Read Control Table RfSBC A,AND XOR OR CP FLD p LD !!LD ""LD *#LD 6$LD %**p*DNEGERETNFIM 0VIM 1^IM 2GLD I,AMRETIOLD R,AWLD A,I_LD A,RgRRDoRLDBSBC HL,JADC HL,@&IN AOUT (C),'LD'CP'IN'OUT'OTC(LD K)LD **1%$ DASM, Version 1.5 $O$:]!8I$ Reading in All Files for !]~ͣ##͗$ -- Read Complete --  $ Type H for Help, ? for Stats O$2$2%2$2%1%#:%G ( GOɯ2$2%$ ** Command Error **  ;At#*$+"$*$+$DB ~>,ã#> ã#>;ã#>(ã#>)ã#>Aã#~8!S͌~ͣ##~.ģ#~NZZ.NCC.POPEP.M.~!u͌~ã#%>Hͣ#>Lͣ#*~do$BCDEHLMA~!~!͌~ͣ##~ã#BCDEHLSPBCDEHLAFBCDEIXSPBCDEIYSP~0ã#>Iͣ#{ã#>'ͣ#'£#ͣ#ã#'">0ͣ#'"~ͣ## %>+ͣ#~>Hͣ#*#^#V+!= 7: %(͎  :% z>0( z({'">Hͣ#{ 80EX DE,HLEX AF,AF'EXXEX (SP),HL'DAADIEIvHALT/CPL?CCFNOP7SCFJP (HL)RLCARLARRCARRARETilename.SYM Read Symbol Table Rfilename.DOC Read Comments Table Rfilename.ALL Read CTL, SYM, DOC, COM Sfilename.ASM Save ASM File Sfilename.CTL Save CTL File Sfilename.SYM Save SYM File Sfilename.DOC Save DOC File Sfilename.ALL CTL, SYM, DOC, ASM Unnnn Set Comment Table addr X Restart DASM Z Write EOF to ASM File ? Print Statistics ç $Restart DASM (Y/N)? ͖Y§ $Restarting DASM ä _͗#!%~ B" (, #>2$$ ORG z{'">Hͣ#͗#B" !,##~ʧ ++~#~8 +~#~I ç DASM for ZILOG-Standard Mnemonics Derived from ZZSOURCE/RESOURCE $> *$|(F#m*$*$"$#"$F!x͞ͻ 8*$#80#"$_!^#V*$~# #~2 % > ͣ##~(*$: % #)/5APV\et} *BPbs&AXbx#cx#ͅx#͙x#%͙*x#%͙*/x#͟x#7x#~8ox#ͅ*$cx#ͅ*$#~ 8[0>'ͣ#:%x# ~ 8 >Hͣ#x#0ͣ#x#%#~>Hͣ#*x#%#~>Hͣ#*>Aͣ#x#N*$#~_*$0KBCDpEL!FH7 IPK!LO PQZRySUX^Z3?$ HELP on DASM -- Command Summary ;addr,comment Enter Comment at addr ;addr List comment at addr ; List Comments Table ;addr, Delete Comment A (see L) Attempt to find DB's B (see L) Build Symbol Table C Dump Control Table Cnnnn Dump Ctrl Table at nnnn Cnnnn,x Set Ctrl (x=BEHISW) Dnnnn Dump from nnnn on Daaaa,bbbb Dump over range D,bbbb Dump thru bbbb D Dump 80H more D=nn Set Dump Size Default DS Dump the Symbol Table DS.sy  #F#~+A8H#~+(B-(>F>2$#~ͣ#$ EQU ~+~'">Hͣ#͗#2$##~͌#́$>2%%!%~# ú *$*$"$!%~ Sʑ=t,ʡB"*$"$ ( (, #B""$*$"$*$"$ $Addr +0 +2 +4 +6 +8 +A +C +E ASCII *$́$&5"="~'"#}="}="}="} >!ͣ#~ 88>.ͣ##}(=">!ͣ#͗#"$:$:$0ç #B"#"$,ʕ ʕ ʧ !%~. ! 0*%!,^#V#~5">=ͣ#F> O#~ͣ##A="́$͗#ç :$=2$͗#>2$$Offset = *ing .DOC file... y!$"$Saving .SYM file... !$"$Saving .CTL file... )$Create a New .ASM File (Y/N)? ͖Y§ !$">2%2$"$++ Writing ASM Enabled Use Z Command or E Control to Close File ++ ç !e$x$Gç !,"^#V#~#G"+> U#~U##> U#> U#>U##z"U#z"U#{"U#{"U#!e$x$#!e$x$(!e$x$ Êyç o*$##6*$$++ No File Accessed Permitted until ASM Closed ++ ç $++ Unexpected EOF ++ ç !%~ B"  (, #~*$5"$ SYMTBL = !,5"*$5"͗#$PC = *$5"͗#$OFFSET = *$5"͗#*$|($COMNTS = *$5"*$5"͗#}͡ç $CTLTBL = !&5"~###< +++5"×#$Symbol Comments are O:%>N >Fͣ#ͣ#×#!%~ (+B""$*$"$ ( (, #B" *$"$*$́$*$~#"$ ~ &+5"=":$/_:$/W> >2$$END 2$:%ʧ >U##2%$++ ASM File Closed ++ ç #:%‰!e$x$.͗Ù!$"$ Reading DOC file... m!$"$Reading SYM file... _!$"$Reading CTL file... `!8~#͌++ѷOx$0Hx$(0++"%7!,~# ~( #~7#o0$#~#G7!%B"~ (, #~. +!8͗# $ was Killed +++Ϳ!!x 8  bk# 6A͡ ç !%~. ! Ϳ!ç DM##~#͌*${ z(`i"$##6#~#+(-(08 :8A8[8 +"w#"w# 80"ͣ#"ã#|'"}'"> ã#~.( ~0:8AG0))))o#! ^#V~!" %2|\<$ File Not Found * %| \! ~#" %8$++ Unexpected EOF ++ ç >w\\<$5"͗#ç !%~ (B" "$͗#:%‰2\2h!%:% : ~@2\##]UU~ (#.(~ .#> >2 %2 %>2 %2 %2 %2 %2$:$2$2$!%~ (N,(> (:= !#B"{ 2$2$~#,( ( ʧ B""$ ( (, #B""$2$́$:$( :$= *$:$:$ҧ : %(3*$*$~ͽ$8##~#ͽ$0+&*$>B"$>I*$|(F*$8=##F#~;+ $"$.7>2$ #~\ ͗#ͣ# * "$l͗#*$ͬ+8###~I(OE3#^#V*$> "%2$SBiHcW5ͣ#$: Invalid CTL Entry ç L2ç ͬ+8###Ѿ2 %ͬa: %I(W(H(B(S( E(K( ##w!~#+<( }ç : %K E(H(B( W( I(S !&~###< T]###+~} | s#r#: %w!&~#+<7#z+ {###ͬ!&́$^#V#z< ͗#}ç +!8͗#~ͣ##>:ͣ#="="5">=ͣ#> ͣ#~ͣ#="="#)ç "!&^#V#z<(+>,U#~U#> U#> U##>U##`Ùw"!&ͦ"($,(:80))))oͦ"s#r#ͦ"w#6#6o!%~ #O #~F( 2%ç B"#  (, 8K~ ʧ *$s#r##w #"$6#6pç$"$Reading COM file... Ue2hU!e$x$ _Ù!e$x$Uç w"*$|2\ e$Last Block Read into Memory at 5"$ Last Block Ends at Relative &"$5"͗#!e$x$ Z!e$x$ mÙ$++ NO, that would overlay the Disassembler because the Offset is too small: $ ++ !,"$##6o*$"$6#6w"ͦ" ( ( (͵s#r##ͦ" ( (w#p :80))))oͦ"#:%‰!e$x$!$"$ Sav 2|!" %\ $\<$++ Close Error ++ ç $++ Write Error ++ * %w," %\ !" %*$|(F(#~ͣ#!"$"$> ͣ#> ã#>*_:%:%!${U#{ :$(!$5͡#%>P !%^#6 !%#~ ʗ#a8{0_w2$2%~ͣ##~ #>P2%>2$>2$2$!%"%!"$"$"$!L"$!"$!"$"$ɯ2,!,"$> 2%!"&>I2%!"$"$6#6#  (-(͗#ç $ Abort (Y/N)? ͖Yç ?ALLASMCOMCTLSYMDOC.K$:$/o:$/g#>2$$DS |}'">Hͣ#͗#"$>2$$DW *$*$^#V0͗#*$##"$͗#2$>2$2%<2$$DB *$*$:$~( 8 8>Hͣ#:%2%0ͣ##*$#"$:% :%J*$+!]:%2%]>,ͣ#}>'ͣ#:%<2%~ͣ#~'̣##*$#"$:% :%(3*$+!0(:%<2%#08+~# (~ 8>'ͣ#ú>'ͣ#͗#!%~ B" (, #B" BK!,#~+8 ~8~w#~w+##~ʧ #o>g$Scratch Area Start = !&5"$ Scratch Area End = *.5"$ COM Start = 0100 COM End =  *$~#+<7#z+ {##~͌#*$́$^#V#z<ʧ 5">;ͣ#F#~ͣ#͗##~#<+T]##~͌#~#O2$*$+!s H~+(-(# >:ͣ#K͗#2$="="*$5">2$!%6L#z "{ "!% 8s#r*$T]xo|g"$##6++DM*%{ z( s#r#p#w!,##~#(,8 Ox$(   itimate purchase of licensed software. I do not regularly use any programs which I have not purchased. (Yes, I do occasionally "try" one, but then buy it if I plan on using it). I have been asked by software businesses to NOT distribute ZESOURCE - because of it's ability to produce good .asm source quickly. But, there are so many disassemblers out, why not a good, conversational one? Please use it in the spirit in which it was contributed: to enlarge your understanding of the micro- computer******************** A disassembler for Z80 programs by Dave Barker (from RESOURCE by Ward Christensen) {NOTE: Most of the text of this file was written by Ward Christensen. I have modified or added to it to make it agree with the features of ZESOURCE, which is RESOURCE enhanced to disassemble into TDL Z80 mnemonics.} Suggestions? Call me eve's at (805) 526-2438 (D.Barker) ---------------- ZESOURCE commands are inconsistent at best. - ZESOURCE is a kludge based on years of disassValzah would have solved that by making resource relocatable and moving itself up under BDOS. I wasn't that industrious. Instead, ZESOURCE uses the concept of an "invisible" OFFSET. After all, what do you care where it is as long as it LOOKS like it's at 100h? So, you set an offset. O2F00 sets it to 2F00 Hex. Reading a .COM file (RFOO.COM) causes it to come into 3000 on. If you say D100 or L100 it dumps or lists what LOOKS like your program. Internally, ZESOURCE is adding the offset to the D world around you, and to allow you to customize programs which you legitimately own, for your own use. "Semper non rippus offus" ---- NOTE: any command taking a hex address (Dnnnn, etc) may take a value in the form .label but arithmetic may not be performed. (i.e. d.start is ok, but d.start+8 not) ---------------- Overall structure of ZESOURCE: It is a .COM file, which runs at 100H. It goes thru 1C00 or so, then the stack. At 1D00 is a 512 entry table for control commands. Each is 3 bembler experience and hacking, and was never "planned" - just coded sitting at a tube, and modified over 2 years before being contributed to the CP/M UG. For example, to kill a symbol: k.label but to kill a control value: caddr,k and to kill a comment: ;addr, but ZESOURCE does the job like no other I have seen. ---------------- N-O-T-E: Pardon the editorial, but I feel hardware without good software is useless to 99% of us. Most good software has to be paid for. I strongly support the leg and L addresses. DASM will set an offset for you automatically. What should you set the offset to? Well, that depends upon how many symbols you will use. O2400 will load the program at 2500, thus allowing only 2300-24FF for symbols, i.e. 512 bytes or about 50-60 labels. If you didn't leave enough space, then used B to build a default symbol table, the table could run into and clobber your .com file! (easy recovery, however: just change the offset to being higher, and read in the .COM file agai DASM ************************************************************* MICRO CORNUCOPIA NOTE: I didn't have a copy of DASM.DOC so this is a copy of ZESOURCE.DOC. ZESOURCE is an extension of RESOURCE for TDL mnemonics and this is a further extension that provides Zilog mnemonics. (You don't know how I've looked for this). Anyway, if anyone has the real ZZSOURCE.DOC, please let me know where it is so I can offload it or please send it in. Dave Thompson *******************************************ytes long, and controls the format of the re-sourced list, i.e. is it DB, DS, DW, instructions, etc. At 2300 is the start of the symbol table. It has no defined length as such. If it is not used, it occupies only 2 bytes. If you want to re-source something which is in memory, such as a PROM, a program previously loaded in high memory, "CP/M itself", or whatever, you can just do so. However, typically you want to disassemble a program which runs at 100H, which is were ZESOURCE runs. Bob Van   n) Each entry takes 3 bytes + the symbol length, and if you like 7 byte labels like I do, that means 10 bytes/label. An offset of 2F00 should be adequate. If you want to put comments into the disassembled program, you will have to designate an area to Use for the comments. The U command (e.g. U4000) specifies what area is to be used. Before issuing the O (offset) command, do: L5 7 which will show the JMP to BDOS, which is the highest memory you may use. (Note if you have, for example, an e) * Forgetting how big the .COM file you are disassembling was. * Using ZESOURCE to rip off software (yes, I know, you heard that before, but only 3 in 100 needed to be told, and 2 in 100 needs to be told again, and 1 in 100 doesn't give a rat's fuzzy behind anyway!!) * Forgetting to take checkpoints when disassembling large files. You may even want to rotate the names under which things are saved: STEMP1.SYM STEMP1.CTL STEMP1.DOC * Missing a label: Suppose you have a contt offset. Hoo, boy! Hope this kludge of documentation is enough to get you going - hmmm, better give you some of the gotcha's I've discovered... ---- WATCH FOR ---- * Symbols overflowing into the .COM. (Use ? command to see how full symbol table is) * Control entries overflowing into .SYM (altho I can't believe anyone will have a program with more than 512 control entries!!!) * Comments overflowing into BDOS (ug!!) * Using an offset which is not in free memory and overlaying ress + whatever). Then you QB100,400 and viola!! ZESOURCE overlaid your "E" control with a "B". ---------------- ZESOURCE is relatively complete. (well, actually, the phrase "rampant featureitis" has been "mentioned"). ...But there's always another day, and another K... SO... Here's my "wish list" ..it might save you telling me YOU think such-and-such would be nice... * Targets of LHLD, SHLD should automatically be flagged as type DW in the control table. Ditto LDA and mpty 4K memory board in high memory, you can Use THAT for comments). Let's take an example: You have an 8K file, FOO.COM which you want to disassemble. It will have about 300 labels. 300 x 10 is 3000, or call it 4K (what's a K unless your tight). The symbol table starts at 2300. 4K more is 3300. Let's load the .COM at 3300, so since it normally starts at 100H, the offset is 3200. O3200 is the command. We then RFOO.COM to read it in. It says 5300 2100 which means it came into actual memory torol entry for a DW, resulting in: DFLT: ;172C DW 100H but somewhere in the program, the following exists: LDA 172DH Even if you did a B and have a label L172D, it won't show up since it's in the middle of a DW. Instead, do this: K.l172d kill the old label e172d,.dflt+1 put in the new label as a displacement off the beginning. * improperly disassembling DW's (see previous item). You might be tempted to make DFLT a DB so that DFLT: ;172C DB 0 L172D: ;17BDOS or whatever. * The B(uild) command gobbling up too much when building a DB: "B" will take a DB 'GOBBELDY GOOK' followed by LXI H,FOO and take the LXI as a '!' (21H) so you'll have to manually stick a new "I" control entry in at the address of the LXI. You might also delete the incorrect "I" entry which ZESOURCE stuck in (typically at the second byte of the LXI) * Trying to dump real memory without setting the offset back to 0. (then forgetting to set it back to its proper valueSTA as DB or as second half of DW. Ditto targets of LXI as DB (?). * E5C,.FCB followed by E6C,.FCB+ should automatically calculate the appropriate displacement, and put it in the symbol table. * The comments facility should be enhanced to allow total SUBSTITUTION of entire line(s) of the code, i.e. at address such-and-such, replace the next 3 bytes with the following arbitrary line. This would help those "how do I explain what was being done" cases such as: LXI H,BUFFER AND 0 5300, but 2100 if we are talking with respect to loading at 100. Thus, we could set our comments table up after the .COM program - say at 6000: U6000 The ? command shows the memory utilization for control, symbol, and comments entries. (no, I never put in anything to keep track of the .COM - you'll just have to do that yourself). If you ever want to dump real memory, you'll have to reset the offset to 0: O0 but then set it back. If you are not sure what it is, typing O will tell the curren2D DB 1 Note that while this disassembles and reassembles properly, it is not "as correct" as the technique used in the previous item. * Having the "B" command overlay your "E" control entry. What? Well, "B"uild is pretty dumb. If he finds 8 DB type characters in a row, he fires off a DB from then on until he runs out of those characters. Suppose your program was 200 long (ended at 3FF), and you had zeroed (aha! Nice DB candidates) memory there (there meaning at your offset add  FF00H ---------------- ZESOURCE types an "*" prompt when it is loaded. You may then enter any of the following commands. Each command is a single letter followed by operands. Commas are shown as the delimiter, but a space will also work. ---------------- ---------------- ; Put comments into the program. (must execute 'u' command first, to assign area for comments to be placed) ;addr,comment enter a comment ;addr lists existing comment ; lists entire comments table ;addr,assuming FCB is at 5C) but would be allowed to be entered. Note when a new symbol is entered any ather symbol at that address will be killed. This prevents having two symbols with the same address. If you have a label which has the wrong address, you need not explicitly kill the old one before entering the new. A label which is spelled exactly the same as an existing one will replace the existing one even if the addresses are different. ---------------- Find occurrence of addretring in memory which disassembles as: DB 'Invalid operand',0DH DB 0AH You might want to change it putting the 0DH,0AH together on the second line - just enter a "B" control entry for the address of the 0DH. The same technique could be used to make DB 'TYPESAVEDIR ERA REN ' appear as DB 'TYPE' DB 'SAVE' DB 'DIR ' DB 'ERA ' DB 'REN ' ---------------- dump: - dxxxx Dumps 80H from xxxx on daaaa,bbbb Dumps from aaaa thru bbbb d,bbbb Continues, thru bbbb d Co0. NOTE when using L to list the .ASM program to disk, you should either list the entire program at once using: Lssss,eeee or, you can list small pieces at a time. As long as you list again without specifying a starting address, (L or L,nnnn) then the output file will continue uninterrupted. You may do dump commands, and others, without affecting what is being written to disk. ---------------- offset for disassembly - o print current offset onnnn establish new offset (note  deletes existing comment note that '\' is treated as a new line, i.e. \test\ will be formatted: ; ;TEST ; ---------------- Attempt to find DB's while listing the program. - This command works just like 'L', but attempts to find DB's of 8 chars or longer. (see 'L' command for operand formats) ---------------- Build default sym tbl (LXXXX) labels for each - 2 byte operand encountered. Note 'B' is identical to 'L' except labels are built. (see 'L' command for operand formss or label. Note this function - runs until interrupted (press any key). fnnnn,ssss find address nnnn in memory. Start the search at ssss. Runs forever. Press any key to stop. f continue previous find command fnnnn find nnnn starting at address you last stopped at in the f command ---------------- kill symbol from table - k.symbol ---------------- list (disassemble). This command is used to list the - file, or to list it to disk after enabling the .ASM file save via 'ntinues, 80H more NOTE 80H is the default dump length. If you have a larger display, you can change the default via: d=nn nn is the HEX new default. For example, a 24 line tube could display 100H: d=100 or.. d=100,200 Defaults to 100, dumps 200-2ff ---------------- enter symbol: - ennnn,.symbol symbol may be of any length, and contain any char A-Z or 0-9, or "+" or "-". This allows: E5D,.FCB+1. Note the "+" is not checked, i.e. E5D,.FCB+2 would be wrong (the offset is always added to any address specified in an a, b, d, or l command. to dump real memory, the offset must be reset to 0 (O0) before the dump.) ---------------- prolog generation - this routine generates an - ORG instruction, and equates for any label outside of a given low-hi address pair. (the start and end addresses of your program). e.g. if disassembling from 100 to 3ff, it will generate 'fcb equ 5ch' if FCB is in the symbol table. In typical use, you would 'sfilename.aats) ---------------- Control table usage: - c dump ctl tbl cnnnn dump from starting cnnnn,x define format from nnnn to next entry. values of x: B = DB (attempts ASCII printable, 0DH, 0AH, 0) W = DW (attempts label) S = DW to next ctl entry I = instructions K = kill this ctl entry E = end of disassembly NOTE every control entry causes a "control break" (NO, ZESOURCE was NOT written in RPG) which means a new line will be started. Thus if you have a sSFILENAME.ASM' command l lists 10 lines from prev pc lssss,eeee lists from ssss to eeee l,eeee lists from current pc to eeee lssss lists 10 lines at ssss Note that if you have a control 'e' entry, then the list will stop when that address is found. This allows you to 'lstart,ffff'. The 10 line default may be changed via: L=nn where nn is a HEX line count, e.g. L=14 set to 20 lines/screen You can change the default and list, e.g. L=9,100 Dflt to 9 lines, list at 10  sm' then use the P command to write the prolog, then the L command to write the program itself. Pstart addr,end addr quiet command: any command which is preceeded by a q - will be done 'quietly'. For example, to save a .asm program, you could just do: ql100,3ff or ql100,ffff if you have set the 'e' control in the control table. Another use is to build a default symbol table by taking a pass thru the program: QB100,xxxx ---------------- read .com, .ctl, .sym, or .doc file - re: if your symbol table is nearing the .com file, then just set a new offset (higher) and re-load the .com) if you want to dump r-e-a-l memory, you would have to reset the offset to 0: o0 (but don't forget to reset it to 1f00 before continuing with your program.) If you are disassembling something which is in memory at it's correct address (such as looking at ccp) then don't set the offset. It defaults to 0 when dis is first loaded. ---> l100 list your program - lists "about" 10 lines.ESOURCE usage. Given: a COM file (lets say test.com) which runs at 100 (as any good COM file should), and goes thru 2FF. lines preceeded with ---> are typed by you. ---> ZESOURCE ---> o2200 set the offset to 2200, which means the program will read into 2200 + 100 = 2300. ---> rtest.com reads the com file into memory. system says: 2500 0300 which is the actual hi load addr, (2500) and the original hi load addr (300) REMEMBER this address (300) because you might want to put a "4 4f50xxxx xxxxxxxx xxxxxxxx *...copyr ight....* 0110 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx *xxxxxxxx ........* thus you would want to instruct the disassembler to switch to db mode at 103, and back to instruction mode at 117, thus: c103,b c117,i Continue doing this, bracketing every ascii db which is in the middle of instructions, by a b control instruction and an i control instruction. Note that multiple db's in a row need not have separate cnnnn,b instructions, but that these do caufilename.com reads in at offset+100h rfilename.ctl loads the ctl table rfilename.sym loads the sym file rfilename.doc loads the comments table (note 'u' command must have been issued) rfilename.all loads the doc, sym, and ctl files with one command ---------------- save .asm, .ctl, .sym, or .doc file - sfilename.asm use 'l' command to write, z to end sfilename.ctl saves the ctl table stablename.sym saves the sym file sfilename.doc saves the comments table sfilename.all saves the ---> d100 do a dump of your program. NOTE that typically here are the steps to disassembling a program which has just been read into memory: Use the dump command to find the ASCII DB areas. Note that the 'a' command may be used to automatically find the db's, but you must then check them to insure that they don't extend too far. All printable characters, 0dh, 0ah, and 00h are considered candidates for ascii db's. At least 8 characters in a row must be found to make sure that long sequE" (end of assembly) control entry there. <<<>>> that all 'L' (disassembly list) and 'D' (dump) commands work with the offset added. Thus, you should learn to forget that the disassembler is in memory, and think of it as if your program were actually at 100. D100 will dump your program. also note: if the program being "ZESOURCEd" will have a fairly large symbol table, then you will have to set the offset higher: o2f00 or some such. (the ? command will show symbol table usagse a 'line break', i.e. if you have a table of ascii commands, for example: 02e5 db 'load' 02e9 db 'save' the disassembler would disassemble these as: 02e4 db 'loadsave' you could put in an additional control entry: c2e9,b, which would cause the disassembler to generate: 02e4 db 'load' 02e8 db 'save' which is much more readable and realistic. Note that before generating each byte of a db, a symbol table lookup is done to determine if there is a label at that location, and if so, a n doc, sym, and ctl files with one command ---------------- use area of memory for comments table - unnnn such as ud000 if you had an open board at 0d000h ---------------- purge sym tbl and CTL tbl x - ---------------- close .asm file (note that a preferred way to close the .asm file is to have specified a control entry for the end address (e.g. c1ff,e)) z - -------------------------------------------- -------------------------------------------- Here is a sample of the Zences of mov instructions won't be taken as db's. Use the cnnnn,k command to kill erronious entries put in the control table by the a command, but then immediately put in the right address, such as via cnnnn,i if you wanted to scan the program for ascii db's yourself, use the 'c' (control) command to set the beginning and end of ascii areas. F JZ 078BH XRA A STA 1712H STA 1714H CALL 1647H CMC DCR C LDAX B NOP JMP 0177H L01F8: ;01F8 CALL L1647 ;16 dump as: 0100 c317014  ew line is started. Thus if 'loadlit' and 'savelit' were in the symbol table, as the labels on the 'load' and 'save' above, no separate 'b' control instruction would be required as the label would cause the break. <<<>>> that at this time the automatic label checking is n-o-t done for ds instructions. Make sure that each ds instrucion references only up to the next label. This means that multiple ds's in a row must each be explicitly entered into the control table. Presence of a label buffer for disk I/O. You want it to disassemble to: DKBUF ;07CF DS 80H You do this as follows: C7CF,S to start the DS C84F,B to define it's end, and E7CF,.DKBUF to put the symbol in the table. Continue, iteratively using the 'l' command and the 'c' and 'e' commands until you have the listing in a nice format. You will then probably want to save the control symbol, and comments tables. Or, you could have been saving them at checkpoint times (so if you make a major mistake you  b (for build labels) instead of l (for list program). The b commands causes lnnnn default labels to be inserted in the symbol table for every 2 byte operand encountered (LXI, SHLD, JMP, etc). It will undoubtedly make some you don't want, such as L0000. You will have to: K.L0000 kill label L0000 from the table. When you encounter data reference instructions, try to determine what type of area the instruction points to. Typically,, LXI instructions may point to a work area which should be dntering a 'e' control, or typing a z command will then close the .asm file. The listing may be interrupted, and continued. Since the l command types only 10 lines, use laddr,ffff to list thru the end of the assembly. If this is the 'final' save of the .asm file, you will probably want to put an 'org' at the beginning of the output file, as well as generate equ instructions for any references outside of the program. For example, a typical cp/m program will have references to: bdos at 5 fcb is not sufficient. ---- steps, continued: After building the control entries with cnnnn,b and cnnnn,i put in a control entry cnnnn,e which defines the address of the end of your program. The l command will then automatically stop there, and in addition, if you are in 'save xxx.asm' mode, the output .asm file will be closed. If you do mot define a control 'e' entry, then you will have to use the break facility to stop the l command (don't use control-c as that will re-boot cp/m). If you wecould go back to a previous one). To save a control file: sfilename.CTL (any filename, may include a: or b:) To save a symbol file: sfilename.sym To save a comments file: sfilename.doc (not ".com" of course) NOTE that the filetypes must be used as shown, but that any legal filename (or disk:filename such as b:xxxx.CTL) may be used. You could now control-c to return to CP/M, and come back later to resume your disassembly: ZESOURCE o2200 rtemp.com rtemp.sym rtemp.ctl uxefined as a DS, or to an ASCII string, in which case we will have already made it a 'b' control instruction. Operands of LHLD and SHLD instructions should be made DW instructions. For example if you encounter LHLD 0534H, then issue a control instruction: C534,W NOTE that whatever mode you are last in will remain in effect. Therefore if 534,w is the last entry in the control table, all data from there on will be taken to be DW's. Suppose that you determine that address 7cf is a 128 byte at 5ch tbuff at 80h the 'p' (for prologue) command generates the org, then scans the symbol table and generates equates: BDOS EQU 05H FCB EQU 05CH (etc.) If you have a "e" control entry in your file, you can list as follows: laddr,ffff - the listing will continue until the "e" control entry is found additional commands: if you entered a label in the symbol table but now want to get rid of it: k.symbol note to rename a symbol, such as when you had a system- assigned lnnnn labre writing an .asm file, you would have to user the z command to close the file. Next, you would list your program to determine how it looks. when you recognize a routine by it's function, insert a label. For example, if you saw that location 7ef was a character out routine (type) then enter a label into the symbol table: E7EF,.TYPE NOTE that all symbols start with a '.', so as to be dis- tinguished from hex data. NOTE that if you want the disassembler to make default labels for you, usexxx (such as u4000) rtemp.doc This will take you back exactly where you left off. If you want to save a .asm file out to disk, do the following: Make sure that there is a control entry defining the end of the program (such as c200,e) or else you will have to specify the ending address and manually type a z command to close the file. sfilename.asm A message will indicate that the file is opened. Any subsequent a, b, or l command will have whatever is listed written to disk. Encou  el but now want to make it meaningful: k.l0334 e334,.type you could even: e.l0334,.type k.l0334 but that takes more typing. here are some more commands: ? prints statistics on symbol and control table usage, etc. c prints the entire control table cnnnn prints the control table starting at address nnnn ds dumps the symbol table. Interrupt it by typing any key. ds.symbol starts dumping at the specified symbol, or the nearest symbol. thus "ds.f" starts 0 lines from prev pc Lssss,eeee Lists from ssss to eeee L,eeee Lists from current pc to eeee Lssss Lists 10 lines at ssss L=nn nn is hex list default # of lines O Print current offset Onnnn Establish new offset Pstart addr,end addr Generate program prolog Q Before any command suppresses console output: QB100,200 Rfilename.COM Reads in at offset+100h Rfilename.CTL Loads the ctl table Rfilename.SYM Loads the sym file Rfilename.DOC Loads the comments table Rfilename.ALL LoadEQU SYMTAB+2000H ;INITIAL OFFSET VALUE COMTBL EQU INITOFF+4000H ;BEGINNING OF COMMENTS SYMMAX EQU 12 ;MAX NUMBER OF CHARS/SYMBOL (<= 12) INITLCNT EQU 20 ;NUMBER OF LINES TO DISPLAY VIA L, A, B INITDLEN EQU 80H ;NUMBER OF BYTES TO DISPLAY VIA D INITPC EQU 100H ;INITIAL VALUE OF PC INITELST EQU 0FFFFH ;INITIAL END OF LIST VALUE IBUFLEN EQU 80 ;LENGTH OF INPUT LINE BUFFER ; CP/M Constants WBOOT EQU 00H BDOS EQU 05H FCB EQU 5CH FCBNR EQU 7CH FCBTYPE EQU 65H RECLEN EQU 80H ; ; Beg the dump at the first label starting with the letter 'f'. ....have fun, and let me know of any problems or suggested improvements ------------------------ ZESOURCE "Quick" command summary Any address may be replaced by .symbol i.e. D.START ;addr,comment Enter a comment ;addr Lists existing comment ; Lists entire comments table ;addr, Deletes existing comment A(see "L" for operands) Attempt to find DB's B(see "L" for operands) Build default sym tbl (Lxxxx) C Dump ctl t; ; Program: DASM ; Version: 1.5 ; Author: Richard Conn ; Date: 16 Aug 82 ; Previous Versions: 1.3 (23 May 82), 1.4 (12 June 82) ; Previous Versions: 1.0 (1 May 82), 1.1 (8 May 82), 1.2 (15 May 82) ; Derivation: ZZSOURCE and RESOURCE ; ; DASM is a TDL/ZILOG Disassembler derived from Dave Barker's ; ZZSOURCE and Ward Christensen's RESOURCE by Richard Conn. Refer to ; the documentation on RESOURCE and the built-in HELP data for information ; on the commands used for DASM. A Help fis the doc, sym, and ctl files Sfilename.ASM Save .ASM file. Write w/L, Z to end Sfilename.CTL Saves the CTL table Sfilename.SYM Saves the sym file Sfilename.DOC Saves the comments table Sfilename.ALL Saves the doc, sym, and ctl files Unnnn Use nnnn for comments table X Purge all symbols and control Z Write eof to .ASM file ? Prints statistics (sym, ctl, comments) inning of Program ; ORG 0100H JP START JP GETCMD ;This is an easy entry point for a restart. ; ; The following INCLUDE is used to include the appropriate file defining ; the Mnemonics for the desired language. Choices at this time are: ; DASMZLG.MAC -- ZILOG-Standard Mnemonics ; DASMTDL.MAC -- TDL Mnemonics ; IF ZILOG INCLUDE DASMZLG.MAC ;Include ZILOG Mnemonic File ENDIF IF TDL INCLUDE DASMTDL.MAC ;Include TDL Mnemonic File ENDIF ; ; PRINT HEADERS ; START: LD SP,bl Cnnnn Dump ctl starting at nnnn Cnnnn,x Define format from nnnn (B,E,I,S,W) Dxxxx Dumps 80H from xxxx on Daaaa,bbbb Dumps from aaaa thru bbbb D,bbbb Dump thru bbbb D Dump 80H more D=nn nn= Hex dump size default. Ds Dumps the symbol table. Ds.symbol Sym dump starting at .symbol Ennnn,.symbol Enter symbol into table, kill old Fnnnn,ssss Find address nnnn starting at ssss F Continue previous find command Fnnnn Find nnnn K.symbol Kill symbol from symbol table L Lists 1le is also being planned for DASM. ; VERS equ 15 ; Version Number .Z80 ; USE ZILOG MNEMONICS ASEG ; USE ABSOLUTE SEGMENTS ; Values for TRUE and FALSE FALSE equ 0 TRUE equ NOT FALSE ; Set one and ONLY one of the following to TRUE ZILOG equ TRUE TDL equ FALSE ; Initial Values for DASM RDCOMQ EQU FALSE ;TRUE OF QUERY USER TO READ COM FILE ; WHEN 'ALL' IS FILE TYPE CTLTBL EQU ENDALL ;BEGINNING OF CONTROL TABLE SYMTAB EQU CTLTBL+600H ;BEGINNING OF SYMBOL TABLE INITOFF   OLDST ;SET STACK CALL PSTRNG DEFB 0DH,0AH,'DASM, Version ' DEFB VERS/10+'0','.',(VERS MOD 10)+'0',0DH,0AH,0 ; ; PERFORM REENTRANT INITIALIZATION ; CALL INIT0 ;INITIALIZE BUFFERS SO DASM IS REENTRANT CALL INIT ;CLEANUP INITIALIZATION ; ; READ IN ALL FILES IF A FILE WAS SPECIFIED ; LD A,(FCB+1) ;GET FIRST LETTER OF FILE NAME CP ' '+1 ;VALID CHAR? JR C,SIGNON ;SKIP READ IF NOT VALID CHAR CALL PSTRNG DEFB 0DH,0AH,'Reading in All Files for ',0 LD HL,FCB+1 ;PT TO FILE NAME LD B,OL VALUES DEFW INCMNT DEFB 'K' ;KILL SYMBOL DEFW KILL DEFB 'L' ;LIST CODE DEFW LIST DEFB 'O' ;SET OFFSET DEFW SETOS DEFB 'P' ;GENERATE PROLOG DEFW PROLOG DEFB 'Q' ;QUIET MODE DEFW QUIET DEFB 'R' ;READ FILES DEFW READ DEFB 'S' ;SAVE FILES DEFW SAVE DEFB 'U' ;SET COMMENTS DEFW UAREA DEFB 'X' ;PURGE SYMBOLS AND CONTROL DEFW PURGE DEFB 'Z' ;CLOSE ASM FILE DEFW CLOSE DEFB '?' ;STATISTICS DISPLAY DEFW STAT DEFB 0 ;END OF COMMAND TABLE ; ;COMMAND: H ; PRINT HELPA ;END OF TABLE IF 0 JR Z,WHAT ;TELL USER THAT COMMAND WAS INVALID INC DE ;PREP FOR NO MATCH INC DE ;...PT TO NEXT COMMAND INC DE CP B ;MATCH? JR NZ,PRCLOOP ;CONTINUE LOOPING IF NOT DEC DE ;PT TO ADDRESS LD A,(DE) ;GET ADR HIGH LD B,A ;... IN B DEC DE ;PT TO LOW LD A,(DE) ;GET ADR LOW LD C,A ;... IN C PUSH BC ;ADDRESS ON STACK RET ;"JUMP TO" COMMAND ; ; GENERAL ERROR ; WHAT: XOR A LD (WRTENAB),A LD (HUSH),A CALL PSTRNG DEFB 0DH,0AH,'** Command Error * DEFB 'Issss,oooo Inc addrs>=ssss by oooo' ;LINE 12 DEFB 0DH,0AH,'K.symbol Kill symbol from table ' DEFB 'L List next ' DEFB (INITLCNT/10)+'0',(INITLCNT MOD 10)+'0' DEFB ' lines' ;LINE 13 DEFB 0DH,0AH,'Lssss,eeee List over range ' DEFB 'L,eeee List to eeee' ;LINE 14 DEFB 0DH,0AH,'Lssss List ' DEFB (INITLCNT/10)+'0',(INITLCNT MOD 10)+'0' DEFB ' lines from ssss ' DEFB 'L=nn[,others] Set list default' ;LINE 15 DEFB 0DH,0AH,'O Print current offset ' DEFB 'Onnnn Set new offset' 8 ;8 CHARS ARDNAME: LD A,(HL) ;GET CHAR CALL COUT ;PRINT IT INC HL ;PT TO NEXT DJNZ ARDNAME CALL ALLRD ;READ IN ALL FILES CALL PSTRNG DEFB 0DH,0AH,'-- Read Complete --',0DH,0AH,0 ; ; PRINT REST OF SIGNON MESSAGE ; SIGNON: LD DE,HEADER ;PRINT HEADER FROM INCLUDE FILE LD C,9 CALL BDOS CALL PSTRNG ;PRINT INITIAL INFO DEFB 0DH,0AH,'Type H for Help, ? for Stats',0DH,0AH,0 JR GETCMD ;PERFORM COMMAND PROCESSING ; ; CLEAN UP DASM AND COMPLETELY REINITIALIZE ; CLEAN: CAL INFORMATION ; HELP: CALL PSTRNG ;JUST ONE BIG PRINT ;LINE 1 DEFB 0DH,0AH,' HELP on DASM -- Command Summary' ;LINE 2 DEFB 0DH,0AH,';addr,comment Enter Comment at addr ' DEFB ';addr List comment at addr' ;LINE 3 DEFB 0DH,0AH,'; List Comments Table ' DEFB ';addr, Delete Comment' ;LINE 4 DEFB 0DH,0AH,'A (see L) Attempt to find DB''s ' DEFB 'B (see L) Build Symbol Table' ;LINE 5 DEFB 0DH,0AH,'C Dump Control Table ' DEFB 'Cnnnn Dump Ctrl Table at nnnn' ;LINE 6 DEFB *',0DH,0AH,0 JR GETCMD ; ; COMMAND TABLE -- CONTAINS COMMAND LETTER FOLLOWED BY ADDRESS OF ROUTINE ; AND ENDS IN 0 AS THE NEXT COMMAND LETTER ; CMDTABL: DEFB 0DH ;EMPTY LINE DEFW GETCMD DEFB ';' ;COMMENTS DEFW CMNT DEFB 'A' ;BUILD ASCII DEFW ASCASM DEFB 'B' ;BUILD LABELS DEFW BLDASM DEFB 'C' ;CONTROL TABLE DEFW CTL DEFB 'D' ;MEMORY DUMP DEFW DUMP DEFB 'E' ;ENTER SYMBOL DEFW ENTER DEFB 'F' ;FIND LABEL DEFW FIND DEFB 'H' ;HELP DEFW HELP DEFB 'I' ;INCREMENT SYMB ;LINE 16 DEFB 0DH,0AH,'Pssss,eeee Generate program prolog ' DEFB 'Q Quiet prefix' ;LINE 17 DEFB 0DH,0AH,'Rfilename.COM Read file @ offset+100H ' DEFB 'Rfilename.CTL Read Control Table' ;LINE 18 DEFB 0DH,0AH,'Rfilename.SYM Read Symbol Table ' DEFB 'Rfilename.DOC Read Comments Table' ;LINE 19 DEFB 0DH,0AH,'Rfilename.ALL Read CTL, SYM, DOC, COM ' DEFB 'Sfilename.ASM Save ASM File' ;LINE 20 DEFB 0DH,0AH,'Sfilename.CTL Save CTL File ' DEFB 'Sfilename.SYM Save SYM File' ;LINE 21 DEFBL INIT ;DO INITIALIZATION ; ; MAIN COMMAND PROCESSING LOOP ; GETCMD: XOR A ;A=0 LD (WRTENAB),A ;DISABLE OUTPUT TO FILE LD (HUSH),A ;SET NOT QUIET LD (XCPTR),A LD (XCPTR+1),A LD SP,OLDST ;RESET STACK ; ; INPUT COMMAND LINE AND CAPITALIZE ; CALL PROMPT ;INPUT COMMAND LINE VIA BDOS ; ; PROCESS COMMAND LINE ; PRCEDE: LD A,(INBUF+2) ;PT TO FIRST CHAR OF COMMAND LINE LD B,A ;GET IT LD DE,CMDTABL ;PT TO COMMAND TABLE PRCLOOP: LD A,(DE) ;GET COMMAND FROM COMMAND TABLE OR 0DH,0AH,'Cnnnn,x Set Ctrl (x=BEHISW) ' DEFB 'Dnnnn Dump from nnnn on' ;LINE 7 DEFB 0DH,0AH,'Daaaa,bbbb Dump over range ' DEFB 'D,bbbb Dump thru bbbb' ;LINE 8 DEFB 0DH,0AH,'D Dump 80H more ' DEFB 'D=nn Set Dump Size Default' ;LINE 9 DEFB 0DH,0AH,'DS Dump the Symbol Table ' DEFB 'DS.symbol Dump starting at symbol' ;LINE 10 DEFB 0DH,0AH,'Ennnn,.symbol Enter symbol into table ' DEFB 'Fnnnn,ssss Find nnnn after ssss' ;LINE 11 DEFB 0DH,0AH,'F or Fnnnn Cont Find or Find nnnn '    0DH,0AH,'Sfilename.DOC Save DOC File ' DEFB 'Sfilename.ALL CTL, SYM, DOC, ASM' ;LINE 22 DEFB 0DH,0AH,'Unnnn Set Comment Table addr ' DEFB 'X Restart DASM' ;LINE 23 DEFB 0DH,0AH,'Z Write EOF to ASM File ' DEFB '? Print Statistics' ;LINE 24 DEFB 0DH,0AH,0 JP GETCMD ; ;COMMAND: X ; PURGE ALL SYMBOLS AND CONTROL ; PURGE: CALL PSTRNG ;PROMPT USER DEFB 'Restart DASM (Y/N)? ',0 CALL CHIN ;GET SINGLE CHAR AND CAP CP 'Y' JP NZ,GETCMD CALL PSTRNG ;PRINT FUNCTION DEFB 'RestaT IT DEC HL ;PT BACK TO CHAR COUNT CP 'A' ;IF FIRST LETTER IS LESS THAN A, DON'T GENERATE 'EQU' JR C,PRLG3 ; ; SCAN SYMBOL FOR '+' OR '-' AND DON'T GENERATE 'EQU' IF IT CONTAINS ONE ; PRLG2: INC HL ;PT TO NEXT CHAR LD A,(HL) ;GET IT CP '+' ;CHECK JR Z,PRLG3 CP '-' ;CHECK JR Z,PRLG3 DJNZ PRLG2 ;LOOP POP HL ;GET PTR TO SYMBOL CHAR COUNT LD B,(HL) ;B=CHAR COUNT LD A,1 ;ENABLE DISK OUTPUT LD (WRTENAB),A ; ; PRINT SYMBOL EQUATE; HL PTS TO BYTE BEFORE SYMBOL AND B=NUMBER OF CHA 2ND ADDRESS IN DE CP 0DH ;ERROR IF JP NZ,WHAT POP BC ;BC=START ADDRESS, DE=END ADDRESS LD HL,SYMTAB ;PT TO SYMBOL TABLE PRLG1: INC HL ;SKIP OVER SYMBOL ADDRESS INC HL LD A,(HL) ;GET 1ST CHAR OF SYMBOL OR A ;END OF SYMBOL TABLE? (CHAR COUNT = 0) JP Z,GETCMD ;DONE IF SO DEC HL ;PT TO SYMBOL ADDRESS DEC HL LD A,(HL) ;COMPARE SYMBOL ADDRESS TO CURRENT ADDRESS SUB C ;... IN BC INC HL LD A,(HL) SBC A,B JR C,GENEQU ;GENERATE EQU IF SYMBOL < START ADDRESS DEC HL ;UIET: LD A,1 ;TURN ON QUIET MODE LD (HUSH),A LD DE,INBUF+2 ;COPY COMMAND LINE LEFT 1 CHARACTER LD HL,INBUF+3 SHFTBF: LD A,(HL) ;COPY IN ORDER TO CONTINUE PROCESSING LD (DE),A ;... NORMALLY INC HL INC DE CP 0DH JR NZ,SHFTBF JP PRCEDE ;RETURN TO MAIN COMMAND PROCESSOR ; ;COMMAND: D ; DUMP THE MEMORY, SYMBOL TABLE, OR SET THE DEFAULT DUMP LENGTH ; DUMP: LD HL,(DMPSTRT) ;GET PTR TO STARTING ADR FOR DUMP PUSH HL EX DE,HL ;... IN DE LD HL,(DMPLEN) ;GET DEFAULT LENGTH OF rting DASM',0DH,0AH,0 JP CLEAN ;RESTART DASM AT INIT ; ; INPUT A SINGLE CHAR IN A VIA THE BDOS AND CAPITALIZE IT; FOLLOW WITH ; CHIN: LD C,1 ;GET CHAR FROM CON: CALL BDOS AND 5FH ;CAPITALIZE PUSH AF CALL CRLF POP AF RET ; ;COMMAND: P ; ENTER PROLOG INTO ASSEMBLY LANGUAGE PROGRAM ; PROLOG: LD HL,INBUF+3 ;PT TO STARTING ADDRESS LD A,(HL) ;NO ADDRESS SPECIFIED? CP 0DH ;ERROR IF SO JP Z,WHAT CALL CNVRT ;CONVERT ADDRESS VALUE TO BINARY IN DE CP ' ' ;CHAR AFTER ARS ; LOOPB: INC HL ;PT TO NEXT CHAR LD A,(HL) ;GET IT CALL COUT ;PRINT IT DJNZ LOOPB ;LOOP FOR NUMBER OF CHARS IN B CALL PSTG DB 9,'EQU',9,0 POP BC ;GET START ADR POP HL ;PT TO CHAR COUNT OF CURRENT SYMBOL LD A,(HL) ;CHECK FOR HIGH-ORDER VALUE OR A ;DON'T PRINT SIGNIFICANT ZERO CALL NZ,PASHEX DEC HL ;PT TO LOW-ORDER VALUE LD A,(HL) ;GET IT CALL PHEX ;PRINT IT LD A,'H' ;FOLLOWING 'H' FOR 'nnH' AND NEW LINE CALL COUT CALL CRLF XOR A ;DISABLE WRITE TO DISK LD (WRTENAB),APT TO SYMBOL LOW-ORDER ADDRESS AGAIN LD A,(HL) ;COMPARE SYMBOL ADDRESS TO END ADDRESS SUB E INC HL LD A,(HL) SBC A,D JP C,WITHIN ;PROCESS NORMALLY IF START <= SYMBOL <= END ; ; SYMBOL IS NOT IN RANGE OF: ; START ADDRESS <= SYMBOL <= END ADDRESS ; GENERATE EQUATE FOR IT ; GENEQU: PUSH HL ;SAVE PTR TO SYMBOL PUSH BC ;SAVE START ADDRESS INC HL ;PT TO SYMBOL CHAR COUNT LD B,(HL) ;B=CHAR COUNT PUSH HL ;SAVE PTR TO CHAR COUNT INC HL ;PT TO FIRST LETTER OF SYMBOL LD A,(HL) ;GEDUMP ADD HL,DE ;CALCULATE END ADDRESS OF DUMP LD (DMPEND),HL ;SAVE IT POP DE LD HL,INBUF+3 ;LOOK AT COMMAND LINE LD A,(HL) ;GET CHAR AFTER THE 'D' CP 0DH ;IF , THEN DUMP FROM DMPSTRT TO DMPEND JP Z,DMPHDR CP 'S' ;IF S, THEN DUMP THE SYMBOL TABLE JP Z,DMPSYM CP '=' ;IF =, THEN SET THE DEFAULT DUMP LENGTH JP Z,DUMP5 CP ',' ;IF ',', THEN DUMP FROM CURRENT TO END SPEC JP Z,DUMP1 ; ; NUMBER SHOULD FOLLOW THE D -- PROCESS IT ; DUMP0: CALL CNVRT ;GET VALUE PUSH HL ;SADDRESS = ? JR Z,PRLG0 ;CONT IF SO CP ',' ;CHAR AFTER ADDRESS = ','? JP NZ,WHAT ;ERROR IF NOT ',' OR PRLG0: INC HL ;PT TO 2ND ADDRESS PUSH DE ;SAVE FIRST ADDRESS ON STACK PUSH HL ;SAVE PTR TO 2ND ADDRESS LD A,1 ;TURN ON DISK OUTPUT LD (WRTENAB),A CALL PSTG ;PRINT NEW ORG DEFB 9,'ORG',9,0 POP HL POP DE LD A,D ;ORG AT FIRST ADDRESS CALL PASHEX ;PRINT AS 'nnH' LD A,E CALL PHEX LD A,'H' CALL COUT CALL CRLF PUSH DE ;SAVE FIRST ADDRESS CALL CNVRT ;GET INC HL ;PT TO HIGH-ORDER VALUE OF SYMBOL ; ; SYMBOL IS WITHIN THE DESIRED RANGE (START <= SYMBOL <= END) ; WITHIN: INC HL ;PT TO CHAR COUNT OF SYMBOL LD A,(HL) ;GET IT CALL SKIP ;SKIP TO NEXT SYMBOL INC HL ;PT TO ITS ADDRESS CALL BRKCHK ;CHECK FOR BREAK JP PRLG1 ;CONTINUE GENERATING PROLOG ; ; SKIP CURRENT SYMBOL FOR ONE REASON OR ANOTHER ; PRLG3: POP HL ;RESTORE REGS AND CONTINUE POP BC POP HL JR WITHIN ; ;COMMAND: Q PREFIX ; EXECUTE THE COMMAND IN THE QUIET MODE ; Q  VE IT LD HL,(DMPLEN) ;GET DEFAULT LENGTH ADD HL,DE ;COMPUTE END OF DUMP LD (DMPEND),HL ;SAVE IT POP HL ;GET START ADDRESS OF DUMP ; ; CHECK FOR DELIMITER AFTER FIRST NUMBER ; DUMP1: CP 0DH ;IF , DUMP FOR THE DEFAULT LENGTH JR Z,DUMP3 CP ' ' ;IF , GET 2ND NUMBER JR Z,DUMP2 CP ',' ;IF ',', GET 2ND NUMBER JP NZ,WHAT ;ERROR IF NOT ; ; EXTRACT 2ND NUMBER FROM DUMP COMMAND ; DUMP2: INC HL ;PT TO NUMBER PUSH DE CALL CNVRT ;RETURN IT IN DE EX DE,HL LD (DMPEND) LINE LD (DMPSTRT),HL ;COMPARE CURRENT START ADDRESS TO END ADDRESS LD A,(DMPEND) SUB L LD A,(DMPEND+1) SBC A,H JR NC,DUMP4 ;CONTINUE IF CURRENT START <= END JP GETCMD ;RETURN TO COMMAND PROCESSING OTHERWISE ; ; SET THE DEFAULT NUMBER OF BYTES TO DUMP ; DUMP5: INC HL ;PT TO VALUE CALL CNVRT ;RETURN VALUE IN DE INC HL DEC DE EX DE,HL LD (DMPLEN),HL ;SAVE VALUE EX DE,HL CP ',' JP Z,DUMP0 CP ' ' JP Z,DUMP0 CP 0DH JP Z,GETCMD JP WHAT ; ; DS -- DUMP THE SYMBOL TALL SPACE ;PRINT A SPACE ; ; DUMP AS HEX ; DMPLN: LD A,(HL) ;GET BYTE CALL PHEX ;PRINT AS HEX INC HL ;PT TO NEXT LD A,L ;PRINT ONE SPACE FOR EVERY 2 VALUES AND 1 CALL Z,SPACE LD A,L ;PRINT TWO SPACES EVERY 4 AND 3 CALL Z,SPACE LD A,L ;PRINT THREE SPACES EVERY 8 AND 7 CALL Z,SPACE LD A,L ;CHECK FOR END OF DUMP LINE (EVERY 16) AND 0FH JR NZ,DMPLN LD A,'!' ;PRINT BEGINNING '!' CALL COUT POP HL ;GET PTR TO FIRST BYTE ; ; DUMP AS ASCII ; DMPASC: LD A,(HL) LD B,C ;SP COUNT IN B SPIT1: CALL SPACE DJNZ SPIT1 CALL SPCRLF ;NEW LINE CALL BRKCHK ;CHECK FOR BREAK JR FRMSYM ;CONTINUE ; ; PRINT AND EXIT ; SPITCR: CALL CRLF ;NEW LINE JP GETCMD ; ; COUNT DOWN ECNT AND OUTPUT ON ZERO ; SPCRLF: LD A,(ECNT) ;GET COUNT DEC A LD (ECNT),A RET NZ CALL CRLF ;NEW LINE ; ; INIT ECNT ; IECNT: LD A,4 ;SET 4 ENTRIES LD (ECNT),A RET ; ; PRINT THE VALUE OF THE OFFSET. ; PRNTOS: CALL PSTRNG DB 'Offset = ',0 LD HL,,HL ;SET END ADDRESS OF DUMP POP DE ;GET START ADDRESS OF DUMP IN DE ; ; ADD OFFSET TO BEGINNING AND ENDING DUMP ADDRESSES ; ON INPUT, DE=START OF DUMP ADDRESS ; DUMP3: LD HL,(OFFSET) ;GET OFFSET PUSH HL ;SAVE IT ADD HL,DE ;ADD TO BEGINNING DUMP ADDRESS LD (DMPSTRT),HL ;SET PTR LD HL,(DMPEND) ;GET END ADDRESS OF DUMP POP DE ;GET OFFSET IN DE ADD HL,DE ;ADD OFFSET TO END ADDRESS OF DUMP LD (DMPEND),HL ;NEW END ADDRESS OF DUMP CP 0DH ;MAKE SURE AFTER DUMP COMMAND JP NABLE ; DMPSYM: CALL IECNT ;INIT ECNT LD HL,INBUF+4 ;PT TO CHAR AFTER 'DS' LD A,(HL) ;GET IT CP '.' ;SYMBOL SPECIFIED? JR NZ,FRMBGN ;NO, SO DUMP FROM BEGINNING OF TABLE CALL LNGTH ;COMPUTE LENGTH OF GIVEN SYMBOL CALL PLCSYM ;RETURN PTR TO THIS SYMBOL IN HL JR NC,FRMSYM ;PROCESS NORMALLY IF FOUND LD HL,(SYMRKR) JR FRMSYM FRMBGN: LD HL,SYMTAB ;PT TO TABLE FRMSYM: LD E,(HL) ;GET ADDRESS OF SYMBOL IN DE INC HL LD D,(HL) INC HL LD A,(HL) ;GET LENGTH OF SYMBOL IN A OR A ;GET CHAR CP ' ' ;PRINT . IF LESS THAN JR C,PERIOD CP 7FH ;PRINT . IF GREATER THAN JR C,CHRCTR ; ; PRINT '.' ; PERIOD: LD A,'.' ; ; PRINT CHAR IN A AND ADVANCE FOR UP TO 16 CHARS ; CHRCTR: CALL COUT ;PRINT CHAR INC HL ;PT TO NEXT LD A,L ;END OF LINE? AND 0FH ;EVERY 16 JR Z,LCMPLT ;DONE IF SO AND 7 ;EXTRA SPACE FOR EVERY 8 CALL Z,SPACE JR DMPASC ;CONTINUE ASCII DUMP ; ; TIDY UP THE LINE ; LCMPLT: LD A,'!' ;PRINT ENDING '!' CALL COUT CALL CRLF ;NEW(OFFSET) ;GET IT AND PRINT IT CALL PVALUE CALL CRLF ;NEW LINE JP GETCMD ; ;COMMAND: O ; SET OR PRINT OFFSET ADDRESS ; SETOS: LD HL,INBUF+3 ;FORMAT: O c/r LD A,(HL) ;.. or Oxxxx c/r CP 0DH ;IF JUST O, DO IT VIA PRNTOS JR Z,PRNTOS CALL CNVRT ;GET VALUE IN DE CP 0DH ;ERROR? JP NZ,WHAT EX DE,HL ;SAVE AS OFFSET LD (OFFSET),HL CALL CRLF ;NEW LINE AND PRINT NEW VALUE JR PRNTOS ; ; SET UP THE FILE CONTROL BLOCK. ; SETFCB: LD A,(FOPEN) ;FILE OPEN? OR A ;0 IF NOT Z,WHAT ;ERROR IF NOT ; ; PRINT HEADER FOR DUMP AND THEN PERFORM DUMP ; DMPHDR: CALL PSTRNG ;PRINT A HEADER FOR THE DUMP DEFB 'Addr +0 +2 +4 +6 +8 +A +C +E ASCII' DEFB 0DH,0AH,0 ; ; MAIN DUMP LOOP ; CNTDMP: LD HL,(DMPSTRT) ;GET START ADDRESS OF DUMP DUMP4: CALL BRKCHK ;CHECK FOR BREAK PUSH HL ;SAVE PTR TO NEXT BYTE CALL TWOS ;MAKE HL CONTAIN RELATIVE VALUE CALL PVALUE ;... BY SUBTRACTING OFFSET; THEN PRINT IT POP HL ;GET PTR PUSH HL ;SAVE PTR C ;DONE IF LENGTH = 0 JP Z,SPITCR EX DE,HL ;PRINT VALUE OF SYMBOL CALL PVALUE EX DE,HL LD A,'=' ;PRINT = CALL COUT LD B,(HL) ;GET LENGTH OF SYMBOL IN B LD A,SYMMAX+1 ;COMPUTE DIFF FROM MAX SUB B LD C,A ;DIFFERENCE IN C (NUMBER OF SPACES AFTER SYM) INC HL ; ; PRINT THE SYMBOL PTED TO BY HL; B=NUMBER OF BYTES LONG THE SYMBOL IS ; SPIT: LD A,(HL) ;GET SYMBOL CHAR CALL COUT ;PRINT IT INC HL ;PT TO NEXT DJNZ SPIT ;UNTIL DONE ; ; PRINT TRAILING SPACES AFTER SYMBOL ;    JP NZ,CANT LD (FCB),A ;SET DEFAULT DRIVE LD (FCB+12),A ;SET EXTENT NUMBER TO ZERO LD HL,INBUF+3 ;PT TO FIRST LETTER OF POSSIBLE FILE NAME LD A,(INBUF+4) ;GET SECOND LETTER CP ' ' ;ERROR IF JUST JP Z,WHAT CP ':' ;GET AND SET DRIVE IF ':' JR NZ,SMDRV LD A,(HL) ;GET SPECIFIED DRIVE SUB '@' ;CONVERT IT TO BINARY LD (FCB),A ;SET DRIVE NUMBER IN FCB INC HL INC HL ; ; WRITE FILE NAME AND TYPE INTO FCB ; SMDRV: LD DE,FCB+1 ;PT TO FILE NAME FIELD OF FCB LD B,8 CALL SOR L, A, OR B FROM COMMAND LINE ; LIST2: CALL CNVRT ;GET VALUE IN DE EX DE,HL LD (PC),HL ;SET PC TO IT EX DE,HL CP 0DH ;DONE? JR Z,TENL ;DO DEFAULT NUMBER IF SO CP ' ' ;GET 2ND ARG IF JR Z,LIST3 CP ',' ;SAME IF ',' JP NZ,WHAT ;ERROR OTHERWISE ; ; GET 2ND ARG FOR L, A, OR B COMMAND ; LIST3: INC HL ;PT TO FIRST CHAR OF 2ND ARG CALL CNVRT ;GET ITS VALUE IN DE EX DE,HL LD (ENDLST),HL ;SET END OF LISTING TO IT XOR A ;TURN OFF LINE COUNTING LD (CNTENAB),A ; ; MAIN PR BY B COMMAND LD (BUILD),A XOR A ;TURN OFF BUILD BY A COMMAND LD (ASCBLD),A JR LIST1 ; ;COMMAND: L ; DISASSEMBLE WITH THE 'L' OPTION ; LIST: XOR A ;TURN OFF A AND B FLAGS LD (BUILD),A LD (ASCBLD),A LIST1: XOR A ;DISABLE OUTPUT TO DISK LD (WRTENAB),A LD A,(NLINES) ;SET LINE COUNT LD (LCTR),A LD (CNTENAB),A ;ENABLE LINE COUNT LD HL,INBUF+3 ;PT TO CHAR AFTER L, A, OR B COMMAND LD A,(HL) ;GET IT CP 0DH ;DO DEFAULT NUMBER IF EOL JR Z,TENL CP ',' ;USE CURRENT POSITION L ;PT TO NEXT CALL ISITASC JR NC,FOLLOW DEC HL ;PT TO NON-ASCII CHAR CALL TWOS ;SUBTRACT OFFSET FROM LOCATION EX DE,HL ;RESULT IN DE PUSH DE ;SAVE PTR TO BYTE AFTER DB STRING FOR 'I' CONTROL LD HL,(PC) ;GET VALUE OF BEGINNING OF ASCII STRING EX DE,HL ;... IN DE LD A,'B' ;SET B CONTROL POINT CALL FTCTL0 ;A='B', DE=ADDRESS POP HL LD (PC),HL ;SET NEW ADDRESS TO CONTINUE FROM EX DE,HL LD A,'I' ;A='I', DE=ADDRESS FOR INSTR CONTROL CALL FTCTL0 ; ; NOW LOOK FOR ANY COMMENTS AT THISLIDE ;PUT FILE NAME LD B,3 CALL SLIDE ;PUT FILE TYPE RET ; ; WRITE CHARS PTED TO BY HL INTO BUFFER PTED TO BY DE; WRITE AT MOST B ; CHARS, AND FILL THE BUFFER PTED TO BY DE ; SLIDE: LD A,(HL) ;GET NEXT CHAR CP 0DH ;DONE? JR Z,BLANK ;BLANK FILL IF SO INC HL ;PT TO NEXT CP '.' ;FILE TYPE FOLLOWS? JR Z,BLANK ;BLANK FILL IF SO LD (DE),A ;PUT CHAR INC DE ;PT TO NEXT DJNZ SLIDE ;COUNT DOWN ; ; CHECK FOR ERROR IF AFTER 8 CHARACTERS IN THE FILENAME ; AFTR8: LD A,(HL) OCESSING LOOP FOR L, A, AND B COMMANDS ; TENL: CALL BRKCHK ;CHECK FOR BREAK LD A,(CNTENAB) ;CHECK FOR LINE COUNTING IN PROGRESS OR A ;0 = NO JR Z,CONTL ;CONTINUE IF NOT LD A,(LCTR) ;GET COUNT DEC A ;COUNT DOWN JP M,GETCMD ;RETURN TO COMMAND PROCESSING IF DONE JR FLAGA ; ; COMPARE ENDLST WITH PC ; CONTL: LD HL,(ENDLST) ;DONE WITH DISPLAY? LD A,(PC) SUB L LD A,(PC+1) SBC A,H JP NC,GETCMD ; ; CHECK FOR A OR B COMMANDS ; FLAGA: LD A,(ASCBLD) ;A COMMAND IF ASCBLD NOT ZERFOR FIRST ARG IF ',' JR Z,LIST3 CP ' ' ;SAME AS ',' JR Z,LIST3 CP '=' ;SET DEFAULT NUMBER OF LINES IF '=' JR NZ,LIST2 ; ; SET DEFAULT NUMBER OF LINES FOR LIST ; NWLNCT: INC HL ;PT TO ARG CALL CNVRT ;GET IT IN DE LD A,E ;ERROR IF ZERO OR A JP Z,WHAT LD (NLINES),A ;SET COUNTS LD (LCTR),A LD A,(HL) ;GET NEXT CHAR INC HL CP ',' ;CONTINUE IF COMMA OR SPACE JR Z,LIST2 CP ' ' JR Z,LIST2 CP 0DH ;DONE IF JP Z,GETCMD JP WHAT ;ERROR OTHERWISE ; ; GET FIRST ARG F ADDRESS ; MOREL: LD HL,(COMST) ;COMMENT TABLE IN USE? LD A,H ;ADDRESS IS ZERO IF NOT OR L JR Z,NCMT LD HL,(PC) ;HL PTS TO PC EX DE,HL ;DE PTS TO PC CALL CMCHK ;CHECK COMMENT TABLE FOR MATCH JR C,NCMT ;NO MATCH INC HL ;PT TO CHAR COUNT OF COMMENT INC HL LD B,(HL) ;B=NUMBER OF CHARS IN COMMENT INC HL ;PT TO FIRST CHARACTER LD A,(HL) ;A=FIRST CHAR OF COMMENT CP ';' ;A ';' COMMENT IS LISTED AFTER THE OPCODE DEC HL ;PT BACK TO CHAR COUNT JR NZ,MOREL1 ;CONTINUE IF NO ';' LD (X;GET NEXT CHAR CP 0DH ;OK IF RET Z CP '.' ;OK IF '.' INC HL ;PT TO NEXT AFTER '.' RET Z JR AFTR8 ; ; BLANK FILL FOR THE REMAINDER OF THE NAME ; BLANK: LD A,' ' ;GET LD (DE),A ;PUT IT INC DE ;PT TO NEXT DJNZ BLANK ;COUNT DOWN RET ; ;COMMAND: A ; BUILD ASCII STRINGS USING DB'S ; ASCASM: LD A,1 ;SET FLAG LD (ASCBLD),A XOR A ;TURN OFF BUILD BY B COMMAND LD (BUILD),A JR LIST1 ;PERFORM LIST ; ;COMMAND: B ; BUILD LABELS ; BLDASM: LD A,1 ;TURN ON BUILDO OR A JR Z,MOREL ; ; THIS IS THE MAJOR FUNCTION TO BUILD ASCII DB'S ; BUILDA: LD HL,(PC) ;HL PTS TO NEXT BYTE (RELATIVE) EX DE,HL ;PTR IN DE LD HL,(OFFSET) ;HL CONTAINS OFFSET ADD HL,DE ;HL PTS TO NEXT BYTE ABSOLUTE LD B,8 ;LOOK FOR 8 ASCII CHARS IN A ROW LOOP8: LD A,(HL) ;CHECK FOR ASCII CHAR CALL ISITASC ;IS IT ASCII? JR C,MOREL ;NO, SKIP TO NEXT BYTE INC HL ;YES, PT TO NEXT DJNZ LOOP8 ; ; FIND END OF THIS ASCII STRING ; FOLLOW: LD A,(HL) ;LOOK UNTIL NON-ASCII INC H  CPTR),HL ;SAVE THE COMMENT ADDRESS JR NCMT ; ; THIS ROUTINE WILL ; PRINT COMMENTS ; LIKE THIS ; NWLN: SCF NWLN0: LD A,1 ;ENABLE WRITING LD (WRTENAB),A CALL C,SEMI ;OUTPUT SEMI BEFORE NEW COMMENT XOR A OR B ;CHECK CHAR COUNT FOR DONE RET Z ;DONE IF ZERO CHARS LEFT CNTCMT: INC HL ;PT TO NEXT CHAR LD A,(HL) ;GET IT CP '\' ;NEW LINE? JR NZ,NTBKSL CALL CRLF ;NEW LINE DEC B ;DEC CHAR COUNT JR NWLN ;CONT NTBKSL: CALL COUT ;PRINT CHAR DEC B ;DECREMENT COUNT JR NZ,CNTUE ; ; DW CTL -- PROCESS DW AND LOOK FOR LABELS ; WMODE: LD A,1 ;ENABLE WRITING LD (WRTENAB),A CALL PSTG ;PRINT 'DW' DEFB 'DW',9,0 LD HL,(PC) ;GET PC EX DE,HL ;... IN DE LD HL,(OFFSET) ;GET OFFSET ADD HL,DE ;HL PTS TO ACTUAL BYTE PAIR LD E,(HL) ;SET DE TO DW VALUE INC HL LD D,(HL) CALL PRNTDE ;PRINT DW VALUE CALL CRLF LD HL,(PC) ;ADVANCE PC TO BYTE AFTER DW VALUE INC HL INC HL LD (PC),HL JP TENL ;CONTINUE PROCESSING ; ; NEW LINE AND CONTINUE ; STPLN: CALL CRLF LD (NXTCTL),HL ;SAVE IT EX DE,HL ;... IN DE ALSO XOR A ;DISABLE WRITE LD (WRTENAB),A POP AF ;GET CONTROL MODE CP 'S' ;DS? JP Z,DSMODE CP 'B' ;DB? JP Z,BMODE CP 'H' ;DB HEX? JP Z,HMODE CP 'W' ;DW? JP Z,WMODE CALL COUT ;ELSE PRINT AS ERROR CALL PSTRNG DEFB ': Invalid CTL Entry',0DH,0AH,0 JP GETCMD ; ; EXECUTE HERE IF THE 'I' CTL IS IN EFFECT -- INTERPRET AS INSTRUCTION ; DE PTS TO BYTE WHICH IS BEING PROCESSED ; ICTL: CALL DASM ;INVOKE DISASSEMBLER XOR A ;DISABLE  LTLF: OR '0' ;MASK FOR ASCII CALL COUT ;PRINT DIGIT ; ; ADVANCE TO NEXT BYTE ; MVUP: INC HL ;PT TO NEXT BYTE EX DE,HL ;... IN DE LD HL,(PC) ;PT TO PC INC HL ;ADVANCE PC LD (PC),HL EX DE,HL ;DE PTS TO PC, HL PTS TO NEXT BYTE ; ; CHECK TO SEE IF THE NEXT CONTROL POINT BEEN REACHED ; CNXCTL: LD A,(NXTCTL) ;COMPARE AGAINST PC CP E JR NZ,TRYSYM LD A,(NXTCTL+1) CP D JP Z,QTB ; ; SEE IF WE ARE POINTING TO A SYMBOL'S ADDRESS ; TRYSYM: LD HL,(PC) ;PC IN DE EX DE,HL CCMT RET MOREL1: CP '*' ; A '*' COMMENT REPLACES THE ENTIRE LINE JR NZ,MOREL2 LD (RPLPTR),HL JR NCMT ; ; PRINT COMMENT PTED TO BY HL AND THEN NEW LINE ; MOREL2: CALL NWLN ;PRINT COMMENT CALL CRLF ; ; NOW PROCESS THE BYTE AS AN INSTRUCTION IF IT IS ; NCMT: LD HL,(PC) ;PT TO PC EX DE,HL ;... IN DE CALL SCHCTL ;CHECK CONTROL TABLE DEC HL ;PT TO CONTROL MODE OF PREVIOUS ENTRY JR C,RDCTL ;IF NO MATCH, CONTROL MODE OF PREVIOUS ENTRY IS IT INC HL ;SINCE MATCH, PT TO CONTROL MO JP TENL ; ; DB HEX MODE -- BUILD HEX DB'S ; HMODE: XOR A ;SET FLAG LD (ADB),A JR BMODE1 ; ; DB MODE -- BUILD ASCII STRINGS LONGER THAN 8 CHARACTERS ; BMODE: LD A,0FFH ;SET FLAG FOR ASCII LD (ADB),A BMODE1: XOR A ;INIT LENGTH TO ZERO LD (BLNGTH),A INC A ;ENABLE WRITING LD (WRTENAB),A CALL PSTG ;PRINT 'DB' DEFB 'DB',9,0 ; ; PROCESS BYTES OF DB ; MOREB: LD HL,(PC) ;GET RELATIVE ADDRESS EX DE,HL ;... IN DE LD HL,(OFFSET) ;GET OFFSET ADD HL,DE ;PT TO ACTUAL BYTE WRITE LD (WRTENAB),A JP TENL ; ; DS CTL -- DE CONTAIN NEXT CTL ADDRESS ; DSMODE: PUSH DE ;SAVE NEXT CONTROL LD A,(PC) ;COMPUTE -PC IN HL CPL LD L,A LD A,(PC+1) CPL LD H,A INC HL ADD HL,DE ;HL = LENGTH OF SPACE DEFINED LD A,1 ;ENABLE WRITING LD (WRTENAB),A CALL PSTG ;PRINT 'DS' DEFB 'DS',9,0 LD A,H ;PRINT SIZE OF AREA CALL PASHEX LD A,L CALL PHEX LD A,'H' CALL COUT CALL CRLF POP HL ;GET PTR TO NEXT CONTROL ENTRY LD (PC),HL ;SET PC TO IT JP TENL ;CONTINALL SYMSCH ;LOOK FOR SYMBOL JP NC,STPLN ;NEW LINE IF THERE IS A SYMBOL LD A,(BLNGTH) ;INCREASE LINE BY 2 ADD A,2 LD (BLNGTH),A CP 27 JP NC,STPLN ;NEW LINE IF STRING EXCEEDS 27 CHARS LD A,',' ;SEPARATE BY COMMA OTHERWISE CALL COUT JP MOREB ; ; VALID CHAR ... BEGIN PROCESSING AS QUOTED STRING ; LTRUB: LD A,'''' ;OUTPUT QUOTE CALL COUT LD A,(BLNGTH) ;INC LENGTH INC A LD (BLNGTH),A LD A,(HL) ;GET CHAR ; ; OUTPUT AS ASCII CHARS ; MORASC: CALL COUT ;PRINT CHAR LD A,(HL)DE OF MATCHED ENTRY INC HL INC HL ; ; CHECK CONTROL MODE ; RDCTL: LD A,(HL) ;GET CONTROL MODE CP 'I' ;IS IT INSTRUCTION? JR Z,ICTL ;PROCESS IF SO CP 'E' ;END OF PROGRAM? JP Z,CLOSE ;DONE IF SO PUSH AF ;ELSE SAVE CONTROL MODE INC HL ;PT TO ADDRESS OF NEXT CONTROL MODE LD E,(HL) ;ADDRESS IN DE INC HL LD D,(HL) PUSH DE ;SAVE ADDRESS OF NEXT CONTROL ENTRY LD HL,(PC) ;PT TO PC EX DE,HL ;... IN DE CALL HSYM ;PRINT SYMBOL IF THERE POP HL ;HL IS ADDRESS OF NEXT CONTROL ENTRY  LD A,(ADB) ;CHECK FOR ASCII BUILD OR A ;0=NO LD A,(HL) ;GET BYTE OF DB JR Z,LTSPC ;XXH BUILD CP 0AH ;? JR C,LTLF ;PROCESS IF LESS THAN CP ' ' ; JR C,LTSPC ;PROCESS IF LESS THAN CP 7FH ;? JP C,LTRUB ;PROCESS IF GREATER THAN ; ; PRINT BYTE AS HEX NUMBER ; LTSPC: CALL PASHEX ;PRINT BYTE IN A AS HEX LD A,'H' CALL COUT LD A,(BLNGTH) ;INCREASE LENGTH BY 2 ADD A,2 LD (BLNGTH),A JR MVUP ; ; CHAR IS LESS THAN -- MAKE IT SINGLE DIGIT (LIKE 9 FOR TAB) ;    ;CHECK FOR QUOTE CP '''' ;COMPARE CALL Z,COUT ;DOUBLE QUOTE INC HL ;PT TO NEXT CHAR EX DE,HL ;... IN DE LD HL,(PC) ;INCR PC INC HL LD (PC),HL EX DE,HL ;DE=NEXT PC LD A,(NXTCTL) ;CHECK FOR CONTROL CP E JR NZ,YET LD A,(NXTCTL+1) CP D JR Z,FNLQT ; ; CHECK FOR SYMBOL HERE ; YET: PUSH HL LD HL,(PC) EX DE,HL CALL SYMSCH POP HL JR NC,FNLQT ;OUTPUT ENDING QUOTE AND NEW LINE FOR SYMBOL LD A,(BLNGTH) ; BREAK INC A ;INCR LINE LENGTH ; ; KEEP THE LINES LESS THAN 27 DC A,H LD H,A ;HL PTS TO FIRST BYTE OF NEXT SYMBOL JR INCM2 ;CONTINUE PROCESSING ; ;COMMAND: ? ; STATISTIC OUTPUT ; STAT: CALL PSTRNG ;THIS IS RATHER STRAIGHT-FORWARD, SO FEW COMMENTS DEFB 'Scratch Area Start = ',0 LD HL,ENDALL CALL PVALUE ;PRINT VALUE CALL PSTRNG DEFB 0DH,0AH DEFB 'Scratch Area End = ',0 LD HL,(6) LD L,0 CALL PVALUE ;print the beginning of BDOS (not CCP) CALL PSTRNG DEFB 0DH,0AH,0AH DEFB 'COM Start = 0100',0dh,0ah DEFB 'COM End = ',0 LD HL,(R C,E POP DE ;DE=START ADDRESS LD HL,SYMTAB ;PT TO TABLE ; MAJOR LOOP FOR SCANNING SYMBOL TABLE -- HL PTS TO LOW SYM ADDRESS BYTE INCM2: INC HL ;PT TO HI SYM ADDRESS LD A,(HL) ;GET HI DEC HL ;PT TO LOW SYM ADDRESS CP D ;COMPARE JR C,INCM4 ;SKIP SYMBOL ENTRY JR NZ,INCM3 ;SYMBOL IS GREATER SO ADD OFFSET TO IT LD A,(HL) ;GET LOW CP E ;COMPARE JR C,INCM4 ;SKIP SYMBOL ENTRY ; ADD OFFSET TO SYMBOL ADDRESS PTED TO BY HL INCM3: LD A,(HL) ;GET LOW ADDRESS BYTE ADD A,C ;ADD LF TABLE) DEC HL DEC HL CALL PVALUE ;PRINT THE VALUE 0FFFFH JP CRLF ; ; PRINT THE STATUS MESSAGE OF THE SYMBOL COMMENTS FACILITY ; CMNTST: CALL PSTRNG ;PRINT THE STATUS OF SYMBOL COMMENTS DEFB 'Symbol Comments are O',0 LD A,(XCSW) OR A LD A,'N' JR NZ,CMTST1 LD A,'F' CALL COUT CMTST1: CALL COUT JP CRLF ; ;COMMAND: F ; FIND THE OCCURRENCE OF ADDRESSES ; FIND: LD HL,INBUF+3 LD A,(HL) CP 0DH ;CHECK FOR NO FURTHER ARGS JR Z,PREVF CALL CNVRT ;GET ARG IN DE EX DLONG ; LD (BLNGTH),A CP 35 JR NC,LASTQT CP 27 JR C,STILL ; ; OVER 17H CHARACTERS HAVE BEEN QUOTED ; DEC HL LD A,(HL) INC HL CP ' ' JR Z,FNLQT STILL: LD A,(HL) CP ' ' JR C,LASTQT CP 7FH JP C,MORASC ; ; PRINT A TRAILING QUOTE ; LASTQT: LD A,'''' ;PRINT QUOTE CALL COUT JP CNXCTL ; ; PRINT ENDING QUOTE AND NEW LINE ; FNLQT: LD A,'''' CALL COUT QTB: CALL CRLF JP TENL ; ;COMMAND: I
, ; INCREMENT SYMBOL TABLE ADDRESSES AFTER AND ON <ELEND) ;GET END ADDRESS CALL PVALUE CALL PSTRNG DEFB 0DH,0AH,0AH DEFB 'SYMTBL = ',0 LD HL,SYMTAB CALL PVALUE LD HL,(SYMEND) CALL PVALUE CALL CRLF CALL PSTRNG DEFB 'PC = ',0 LD HL,(PC) CALL PVALUE CALL CRLF CALL PSTRNG DEFB 'OFFSET = ',0 LD HL,(OFFSET) CALL PVALUE CALL CRLF LD HL,(COMST) LD A,H OR L JR Z,CTLSTT CALL PSTRNG DEFB 'COMNTS = ',0 LD HL,(COMST) CALL PVALUE LD HL,(COMEND) CALL PVALUE CALL CRLF CTLSTT: CALL CTLST CALL CMNTST JP GOW OFFSET BYTE LD (HL),A ;PUT LOW ADDRESS BYTE INC HL ;PT TO HI ADDRESS BYTE LD A,(HL) ;GET HIGH ADDRESS BYTE ADC A,B ;ADD HI OFFSET BYTE LD (HL),A ;PUT HI ADDRESS BYTE DEC HL ;PT TO LOW ADDRESS BYTE ; SKIP TO NEXT SYMBOL -- HL PTS TO LOW ADDRESS BYTE INCM4: INC HL ;PT TO HI ADDRESS INC HL ;PT TO CHAR COUNT LD A,(HL) ;GET CHAR COUNT OR A ;DONE IF ZERO JP Z,GETCMD INC HL ;PT TO FIRST CHAR OF SYMBOL ADD A,L ;ADD SYMBOL LENGTH TO HL LD L,A LD A,0 ;ADD IN HI NOW AE,HL ; ... IN HL LD (FNDADD),HL ;ADDRESS TO LOOK FOR LD HL,(OFFSET) ;GET OFFSET LD (FNDPC),HL ;SET START OF SEARCH ADDRESS EX DE,HL ;RESTORE HL TO PT TO CHAR IN COMMAND LINE CP 0DH ;DONE? JR Z,PREVF CP ' ' ; OR ',' MEAN TO CONTINUE JR Z,FIND0 CP ',' JP NZ,WHAT FIND0: INC HL CALL CNVRT ;GET 2ND ARG FOR FIND CP 0DH JP NZ,WHAT LD HL,(OFFSET) ;SET THIS AS STARTING ADDRESS ADD HL,DE ;WITH PROPER OFFSET LD (FNDPC),HL ;START LOOKING FROM HERE ; ; CONTINUE THE PREVIOUS 'F' ADDRESS> BY ; FOR DISASSEMBLY OF NEW VERSIONS OF PROGRAMS ; INCMNT: LD HL,INBUF+3 ;LOOK AT COMMAND LINE LD A,(HL) ;GET CHAR AFTER 'I' CP 0DH ;ERROR IF EOL JP Z,WHAT CALL CNVRT ;GET FIRST VALUE IN DE PUSH DE ;SAVE STARTING ADDRESS ON STACK CP ' ' ;CHECK FOR VALID DELIMITER JR Z,INCM1 CP ',' ;' ' OR ',' DELIMITER JP NZ,WHAT INCM1: INC HL ;PT TO FIRST CHAR AFTER DELIMITER CALL CNVRT ;GET OFFSET IN DE CP 0DH ;MUST BE EOL NOW JP NZ,WHAT LD B,D ;BC=OFFSET LDETCMD ; ; PRINT PARAMETERS OF CONTROL TABLE ; CTLST: CALL PSTRNG ;PRINT THE START AND END OF CONTROL TABLE DEFB 'CTLTBL = ',0 LD HL,CTLTBL CALL PVALUE ; ; FIND THE END OF THE CTLTBL (FF,FF) ; FNDEND: LD A,(HL) ;GET FIRST BYTE INC HL ;PT TO NEXT AND (HL) ;AND IT IN ... IF BOTH ARE 0FFH, RESULT IS 0FFH INC HL ;PT TO CTL LETTER INC HL ;PT TO NEXT BYTE OF ADDRESS INC A ;IF RESULT WAS 0FFH, A NOW EQUALS 0 JR NZ,FNDEND ;CONTINUE UNTIL A=0 DEC HL ;BACK UP TO PREVIOUS ENTRY (END O  COMMAND ; PREVF: LD HL,(FNDADD) ;GET ADDRESS WE ARE LOOKING FOR EX DE,HL ;... IN DE NYET: CALL BRKCHK ;CHECK FOR BREAK LD HL,(FNDPC) ;PT TO PC LD A,(HL) ;GET BYTE AT PC INC HL ;PT TO NEXT LD (FNDPC),HL CP E ;COMPARE BYTE WITH ADDRESS WE ARE LOOKING FOR JR NZ,NYET LD A,(HL) ;PARTIAL MATCH -- TRY HIGH BYTE CP D JR NZ,NYET ; ; WE FOUND ADDRESS IN MEMORY -- PRINT DATA ; PUSH HL PUSH DE CALL TWOS DEC HL CALL PVALUE ;PRINT LOCATION OF FOUND ADDRESS (RELATIVE) POP DEE FILE TYPE TO THAT PTED TO BY HL ; FIXTYP: LD DE,FCBTYPE LD B,3 XOR A LD (FCB+0CH),A ;zero the extent byte JP SLIDE ; ; FILE TYPE WAS NOT 'ALL', SO CHECK TO SEE WHAT TYPE IT WAS AND PROCESS ; NOTALL: LD HL,FCBTYPE ;CHECK FOR SYM LD DE,TPSYM LD C,3 CALL CHKSTG JR NZ,NOTSYM CALL SYMRD ;READ SYM FILE JP STAT ;PRINT STATS NOTSYM: LD HL,FCBTYPE ;CHECK FOR COM LD DE,TPCOM LD C,3 CALL CHKSTG JP NZ,NOTCOM CALL COMRD ;READ IN A COM FILE JP GETCMD ;CONTINUE COMMAND LOCEED IF NOT ; ; READ IN DOC, SYM, CTL FILES ; CALL ALLRD ;READ IN ALL FILES JP STAT ;PRINT STATISTICS ; ; READ IN ALL FILES -- COMMON ROUTINE ; ALLRD: LD HL,TPDOC ;SET FILE TYPE TO DOC CALL FIXTYP CALL PSTRNG ;TELL USER WHAT IS HAPPENING DEFB 0dh,0ah DEFB 'Reading DOC file...',0dh,0ah,0 CALL DOCRD ;READ FILE IN LD HL,TPSYM ;SET FILE TYPE TO SYM CALL FIXTYP CALL PSTRNG ;TELL USER WHAT IS HAPPENING DEFB 'Reading SYM file...',0dh,0ah,0 CALL SYMRD ;READ FILE IN LD HL,NOTCTL JP ISCTL ;READ IN CTL FILE NOTCTL: LD HL,FCBTYPE ;CHECK FOR DOC FILE LD DE,TPDOC LD C,3 CALL CHKSTG JP NZ,WHAT ;ERROR IF NOT COM, SYM, CTL, OR DOC CALL DOCRD ;READ IN DOC FILE JP STAT ; ; ERROR -- ATTEMPT TO OVERLAY THE SYMBOL TABLE OR DISASSEMBLER ; OSERR: CALL PSTRNG DEFB '++ NO, that would overlay ' DEFB 'the Disassembler',0DH,0AH DEFB 'because the Offset is too small: ' DEFB 0 CALL PRNTOS CALL PSTRNG DEFB ' ++',0DH,0AH,0 RET ; ; READ THE SYMBOL TABLE  POP HL CALL SPACE ;PRINT JR NYET ; ; HL=HL-OFFSET ; TAKE 2'S COMPLEMENT OF OFFSET AND ADD TO H & L. ; TWOS: LD A,(OFFSET) ;GET 2'S COMP OF OFFSET IN DE CPL LD E,A LD A,(OFFSET+1) CPL LD D,A INC DE ADD HL,DE ;HL=HL+DE RET ; ;COMMAND: Z ; CLOSE THE FILE ; CLOSE: CALL HSYM LD A,1 ;ENABLE WRITING TO DISK FILE LD (WRTENAB),A CALL PSTG ;WRITE END STATEMENT DEFB 'END',0DH,0AH,0 XOR A ;DISABLE WRITING TO FILE LD (WRTENAB),A LD A,(FOPEN) ;CHECK IF FILINE PROCESSING ; ; READ IN COM FILE ; COMRD: CALL RDOPEN ;OPEN COM FILE FOR READ LD HL,(OFFSET) ;HL=OFFSET LD A,H CP (SYMTAB+600H) SHR 8 ;CHECK FOR NO OVERWRITE OF SYMTABLE JP C,OSERR LD DE,0100H ;SET DMA ADDRESS TO OFFSET PLUS 100H ADD HL,DE SETDMA: PUSH HL ;SET THE DMA ADDRESS. EX DE,HL LD C,1AH CALL BDOS LD DE,FCB ;READ A RECORD. LD C,14H CALL BDOS OR A ;DONE? JR NZ,RDCMPLT POP HL LD DE,RECLEN ;PT TO NEXT BLOCK FOR READ ADD HL,DE JP SETDMA ;CONTINUE ; ; DTPCTL ;SET FILE TYPE TO CTL CALL FIXTYP CALL PSTRNG ;TELL USER WHAT IS HAPPENING DEFB 'Reading CTL file...',0dh,0ah,0 CALL CTLRD ;READ FILE IN IF RDCOMQ ;ENABLE QUESTION OF COM FILE READ? CALL PSTRNG DEFB 'Read in COM File (Y/N)? ',0 CALL CHIN ;GET RESPONSE CP 'Y' JP NZ,STAT ;PRINT STATISTICS ENDIF LD HL,TPCOM ;SET FILE TYPE TO COM CALL FIXTYP CALL PSTRNG ;TELL USER WHAT IS HAPPENING DEFB 'Reading COM file...',0dh,0ah,0 CALL COMRD ;READ FILE IN RET ; ; SET THFROM DISK ; SYMRD: LD HL,SYMTAB ;PT TO SYMBOL TABLE CALL READFILE ;READ FILE INTO IT LD (SYMEND),HL ;SET END ADDRESS OF SYMBOL TABL INC HL ;PT TO NEXT SYMBOL CHAR COUNT INC HL LD (HL),0 ;SET CHAR COUNT TO ZERO RET ; ; READ THE DOC (COMMENTS) FILE FROM DISK ; DOCRD: CALL AREACK ;MAKE SURE COMMENTS AREA DEFINED LD HL,(COMST) ;PT TO START OF COMMENTS AREA CALL READFILE ;READ FILE IN LD (COMEND),HL ;SET END OF COMMENTS AREA LD (HL),0FFH ;STORE 0FFFFH AS ADDRESS OF NEXT COMMENTE WAS OPEN OR A JP Z,GETCMD LD A,1AH ;FILL WITH ^Z CALL WRTFILE CALL NXTRCRD XOR A ;CLOSE FILE LD (FOPEN),A CALL PSTRNG ;PRINT MESSAGE DEFB '++ ASM File Closed ++',0DH,0AH,0 JP GETCMD ; ;COMMAND: R ; READ A FILE OR FILES ; READ: CALL SETFCB ;LOAD THE FCB WITH THE PROPER FILE NAME AND TYPE LD A,(FOPEN) ;CHECK TO SEE IF A FILE IS ALREADY OPENED OR A JP NZ,CANT ;ABORT IF SO LD HL,FCBTYPE ;CHECK FILE TYPE LD DE,TPALL ;IS IT 'ALL'? LD C,3 CALL CHKSTG JP NZ,NOTALL ;PRONE WITH LOAD OF COM FILE ; RDCMPLT: POP HL ;GET DMA ADDRESS OF LAST READ CALL PSTRNG DEFB 'Last Block Read into Memory at ',0 CALL PVALUE CALL PSTRNG DEFB 0DH,0AH DEFB 'Last Block Ends at Relative ',0 CALL TWOS LD (RELEND),HL ;SAVE RELATIVE END ADDRESS CALL PVALUE CALL CRLF LD DE,RECLEN ;RESET THE DMA ADDRESS TO 80H LD C,1AH CALL BDOS RET ; ; THE READ IS NOT A .SYM OR A .COM FILE ; NOTCOM: LD HL,FCBTYPE ;CHECK FOR CTL FILE LD DE,TPCTL LD C,3 CALL CHKSTG JR NZ,   INC HL LD (HL),0FFH RET ; ; READ FILE SET IN FCB INTO MEMORY PTED TO BY HL ; READFILE: CALL RDOPEN ;OPEN FILE RDFL1: CALL READMA ;READ NEXT BYTE (RETURNED IN A) CP 1AH ;RETURN IF EOF EACHED RET Z CP 9 ;IGNORE , , JR Z,RDFL1 CP 0DH JR Z,RDFL1 CP 0AH JR Z,RDFL1 CALL NUM1 ;CONVERT FROM HEX CHARS TO VALUE IN DE LD (HL),E ;SAVE THE ADDRESS INC HL LD (HL),D INC HL PUSH HL INC HL LD B,0 ;COUNT CHARS IN SYMBOL SYMLUP: CALL READMA ;GET NEXT BYTE CPCK FOR SYM LD DE,TPSYM LD C,3 CALL CHKSTG JP NZ,NTSYM CALL SYMSV JP GETCMD ; ; ROUTINE TO SAVE THE SYMBOL TABLE ; SYMSV: LD HL,SYMTAB ;PT TO SYMBOL TABLE SVFL: CALL OPEN ;OPEN THE FILE LUP2: LD E,(HL) ;GET ADDRESS OF SYMBOL IN DE INC HL LD D,(HL) INC HL LD A,(HL) ;GET LENGTH OF SYMBOL IN A INC HL LD B,A ;... AND B OR A ;DONE IF LENGTH IS ZERO JP Z,WRTEOF ;WRITE EOF TO FILE IF DONE CALL EXPND ;WRITE ADDRESS IN DE AS ASCII CHARS ON DISK LD A,' ' ;OUTPUT CALLHKSTG JP NZ,NTALL ;CHECK FOR SPECIFIC TYPE IF NOT ALL LD HL,TPDOC ;SAVE DOC FILE CALL FIXTYP CALL PSTRNG DEFB 0dh,0ah DEFB 'Saving .DOC file...',0dh,0ah,0 CALL DOCSV LD HL,TPSYM ;SAVE SYM FILE CALL FIXTYP CALL PSTRNG DEFB 'Saving .SYM file...',0dh,0ah,00 CALL SYMSV LD HL,TPCTL ;SAVE CTL FILE CALL FIXTYP CALL PSTRNG DEFB 'Saving .CTL file...',0dh,0ah,0 CALL SVCTL0 CALL PSTRNG ;OPTIONALLY SAVE ASM FILE DEFB 'Create a New .ASM File (Y/N)? ',0 CALL CHIN ;GET CHAR CP 'YC,3 CALL CHKSTG JP NZ,WHAT ;ERROR IF NOT ASM AT THIS POINT JP SVASM ;SAVE ASSEMBLY LANGUAGE (TYPE ALREADY ASM) ; ; SAVE THE COMMENT TABLE ; SVDOC: CALL DOCSV JP GETCMD ; ; SAVE COMMENTS ; DOCSV: CALL AREACK ;FIND END OF COMMENTS LD HL,(COMEND) ;GET PTR IN HL INC HL INC HL LD (HL),0 ;SET NULL FINAL COMMENT LD HL,(COMST) ;PT TO START OF TABLE JP SVFL ;PERFORM STRAIGHT SAVE ; ; ATTEMPT TO OPEN ANOTHER FILE WHILE ASM FILE ALREADY OPENED ; CANT: CALL PSTRNG DEFB '++  9 ;DONE IF OR JR Z,SYMTERM CP 0DH JR Z,SYMTERM LD (HL),A ;STORE BYTE INC HL ;PT TO NEXT INC B ;INCR CHAR COUNT JR SYMLUP SYMTERM: EX (SP),HL LD (HL),B POP HL JP RDFL1 ; ; READ NUMBER FROM DISK FILE (1ST HEX DIGIT IN A ON ENTRY) ; VALUE RETURNED IN DE ; NUM1: LD DE,0 ;INIT NUMBER TO ZERO LUP1: CP ' ' ;DONE IF RET Z CP 1AH ;ERROR IF EOF JP Z,ERROR1 CP '9'+1 ;WITHIN DIGIT RANGE? JR C,NUMER1 ;IS A DIGIT SUB 7 ;CONVERT 'A' TO 'F' TO '9'+1 TO 'E'+1 WRTFILE WRTSYM: LD A,(HL) ;GET NEXT CHAR OF SYMBOL CALL WRTFILE ;WRITE TO DISK INC HL ;PT TO NEXT DJNZ WRTSYM ;COUNT DOWN SIZE OF SYMBOL LD A,0DH ;WRITE NEW LINE CHARS CALL WRTFILE LD A,0AH CALL WRTFILE JR LUP2 ; ; WRITE AN EOF ; WRTEOF: LD A,1AH ;WRITE EOF CALL WRTFILE CALL NXTRCRD RET ; ; EXPAND AN ADDRESS IN DE TO ASCII CHARS AND SAVE ON DISK ; EXPND: LD A,D ;OUTPUT HIGH NYBBLE OF HIGH-ORDER BYTE CALL HINIB ;ROUTINE TO DO THIS CALL WRTFILE ;WRITE ASCII CHAR IN' JP NZ,GETCMD LD HL,TPASM ;SAVE ASM FILE CALL FIXTYP ; ; SAVE THE ASM FILE ; SVASM: LD A,1 ;MARK FILE AS OPEN LD (FOPEN),A XOR A ;DISABLE WRITING AT THIS TIME LD (WRTENAB),A CALL OPEN ;OPEN FILE FOR OUTPUT CALL PSTRNG ;PRINT MESSAGE DEFB '++ Writing ASM Enabled' DEFB 0DH,0AH,'Use Z Command or ' DEFB 'E Control to Close File ++' DEFB 0DH,0AH,0 JP GETCMD ;NOW PROCESS USER'S NEXT COMMANDS ; ; TYPE WAS NOT ALL, SO CHECK FOR SPECIFIC FILE TYPES ; NTALL: LD HL,FCBTYPE ;CHENo File Accessed Permitted ' DEFB 'until ASM Closed ++',0DH,0AH DEFB 0 JP GETCMD ; ; EOF ENCOUNTERED TOO SOON ; ERROR1: CALL PSTRNG DEFB '++ Unexpected EOF ++',0DH,0AH DEFB 0 JP GETCMD ; ;COMMAND: C ; CONTROL TABLE ENTRIES ARE MADE HERE ; CTL: CALL IECNT ;INIT ECNT LD HL,INBUF+3 LD A,(HL) CP 0DH ;DUMP CONTROL TABLE IF JUST A 'C' COMMAND JP Z,CDUMP1 CALL CNVRT ;GET ADDRESS CP 0DH ;ERROR? JP Z,CDUMP ;DUMP IF SO CP ' ' ;DELIMITER? JR Z,CTL0 ;PROCESS 2ND OPERAND IF  NUMER1: SUB '0' ;CONVERT TO BINARY IN A EX DE,HL ;OLD VALUE IN HL ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,HL ;*8 ADD HL,HL ;*16 ADD A,L ;+A LD L,A ;ONLY CHANGES LOW-ORDER BYTE EX DE,HL ;VALUE BACK IN DE CALL READMA CP 1AH JP Z,ERROR1 JR LUP1 ; ;COMMAND: S ; SAVE THE FILES ; SAVE: CALL SETFCB ;LOAD THE FCB FROM THE COMMAND LINE LD A,(FOPEN) ;CHECK FOR FILE ALREADY OPEN OR A ;ABORT IF SO JP NZ,CANT LD HL,FCBTYPE ;CHECK FOR TYPE OF 'ALL' LD DE,TPALL LD C,3 CALL C A TO DISK LD A,D ;OUTPUT LOW NYBBLE CALL LONIB CALL WRTFILE LD A,E ;HIGH OF LOW-ORDER BYTE CALL HINIB CALL WRTFILE LD A,E ;LOW OF LOW-ORDER BYTE CALL LONIB JP WRTFILE ; ; NOT OF TYPE SYM -- CHECK FOR CTL ; NTSYM: LD HL,FCBTYPE ;CHECK FOR CTL TYPE LD DE,TPCTL LD C,3 CALL CHKSTG JP Z,SVCTL ;YES, SO SAVE CTL FILE LD HL,FCBTYPE ;CHECK FOR DOC TYPE LD DE,TPDOC LD C,3 CALL CHKSTG JR Z,SVDOC ;YES, SO SAVE DOC FILE LD HL,FCBTYPE ;CHECK FOR ASM TYPE LD DE,TPASM LD   SO CP ',' ;SAME JP NZ,WHAT ;ERROR OTHERWISE CTL0: INC HL ;PT TO 2ND OPERAND LD A,(HL) ;GET IT (CONTROL TYPE) CALL FTCTL ;PROCESS ENTRY WITH CONTROL TABLE JP GETCMD ; ; PLACE A NEW ENTRY INTO THE CONTROL TABLE ; A=TYPE OF ENTRY (B, E, I, K, S, W) AND DE=ADDRESS ; FTCTL0: PUSH HL ;SAVE REGS PUSH DE ;NEW ADDRESS PUSH AF ;NEW TYPE CALL SCHCTL ;FIND ENTRY IN CONTROL TABLE DEC HL ;PT TO TYPE OF PREVIOUS CONTROL ENTRY JR C,FTCTL1 ;IF CARRY, WE DIDN'T MATCH INC HL ;PT TO TYPE OF  INTO CONTROL TABLE; A=TYPE, DE=ADDRESS, HL=ADDR OF ENTRY ; TO INSERT BEFORE ; LGLCTL: PUSH DE ;SAVE ADDRESS PUSH HL ;SAVE ADDRESS OF ENTRY TO INSERT BEFORE LD HL,CTLTBL ;PT TO FRONT OF TABLE ; ; LOOP TO THE END OF THE TABLE ; LP2END: LD A,(HL) ;CHECK FOR 0FFFFH AT END OF TABLE INC HL AND (HL) ;A=0FFH IF SO INC HL ;PT TO CURR CONTROL TYPE INC HL ;PT TO NEXT CONTROL ADDRESS INC A ;A=0 AND ZERO FLAG SET IF AT END JR NZ,LP2END ;CONTINUE UNTIL AT END OF TABLE LD D,H ;DE= HL,3 ADD HL,DE ;HL PTS TO NEXT ENTRY EX DE,HL ;DE PTS TO NEXT ENTRY, HL PTS TO ENTRY TO DELETE ; ; COPY CONTROL TABLE DOWN ; CMPCT: LD A,(HL) ;CHECK FOR END OF CONTROL TABLE INC HL AND (HL) ;ADDRESS IS 0FFFFH IF END DEC HL INC A ;A=0 MEANS ADDRESS IS 0FFFFH JR Z,PNTHLL LD BC,3 ;NOT AT END -- COPY 3 BYTES DOWN AND CONTINUE EX DE,HL ;HL PTS TO SOURCE, DE TO DEST LDIR ;COPY THE 3 BYTES EX DE,HL ;DE PTS TO NEXT ENTRY, HL PTS TO ENTRY TO DELETE JR CMPCT ;CONTINUE COPY OPERATION  LD A,(HL) ;GET LOW ADDRESS INC HL ;PT TO HIGH AND (HL) ;AND IN HIGH ADDRESS; IF ADDR=0FFFFH, THEN A=0FFH DEC HL ;PT TO LOW ADDRESS INC A ;IF A=0FFH BEFORE, NOW A=0 SCF ;SET CARRY FLAG FOR ERROR RETURN RET Z ;RETURN IF A=0 (WE ARE AT END OF TABLE) INC HL ;PT TO HIGH ADDRESS LD A,D ;GET ADDRESS TO COMPARE AGAINST CP (HL) ;DO COMPARE DEC HL ;PT TO LOW ADDRESS RET C ;RETURN IF ADDRESS IS LESS THAN TABLE ENTRY JR NZ,NXTRY ;CONTINUE IF NOT THE SAME LD A,E ;GET LOW ADDRESS CP (HL) ;CCURRENT ENTRY WHICH MATCHES INC HL INC HL FTCTL1: POP AF ;GET NEW TYPE AND POP DE ;... ADDRESS CP (HL) ;DO OUR TYPES MATCH? POP HL ;RESTORE HL RET Z ;NO CHANGE IF THEY DO ; ; PLACE A NEW ENTRY INTO THE CONTROL TABLE ; FTCTL: LD (OPCTP),A ;SAVE TYPE OF ENTRY CALL SCHCTL ;SCAN FOR A MATCH JP C,PLACE ;NO MATCH, SO ENTRY MUST BE ADDED ; ; MATCH OF ADDRESS, SO SIMPLY CHANGE CONTROL MODE AT THAT POINT ; LD A,(OPCTP) ;GET TYPE OF ENTRY CP 'I' ;INSTRUCTION? JR Z,RNCTL CP 'W' ;DHL=PTR TO NEW LAST TABLE ENTRY LOC LD E,L INC HL ;PT TO ENTRY AFTER LAST ENTRY IN TABLE INC HL INC HL ;HL PTS TO NEW LAST TABLE ENTRY LOCATION EX DE,HL ;DE PTS TO NEW, HL PTS TO OLD POP BC ;BC=ADDRESS OF ENTRY TO INSERT BEFORE ; ; EXPAND THE TABLE BY 3 PLACES UNTIL THE PROPER PLACE IS REACHED ; EXPTBL: DEC HL ;BACK UP DEC DE LD A,(HL) ;COPY PREVIOUS BYTE INTO NEW TABLE LOCATION LD (DE),A LD A,L ;ARE WE AT ENTRY TO INSERT BEFORE? CP C JR NZ,EXPTBL ;CONTINUE IF NOT LD A; ; COPY COMPLETE ; PNTHLL: CALL CTLST ;PRINT CONTROL TABLE INFORMATION JP GETCMD ; ; PLACE AN ENTRY INTO THE CONTROL TABLE ; ON ENTRY, HL PTS TO ENTRY TO INSERT BEFORE ; PLACE: LD A,(OPCTP) ;GET TYPE OF COMMAND CP 'K' ;ERROR IF KILL JP Z,WHAT CP 'E' ;SET END OF PROGRAM AREA JR Z,LGLCTL CP 'H' ;DB HEX JR Z,LGLCTL CP 'B' ;DB JR Z,LGLCTL CP 'W' ;DW JR Z,LGLCTL CP 'I' ;INSTRUCTION JR Z,LGLCTL CP 'S' ;DS JP NZ,WHAT ;ERROR IF NONE OF THESE ; ; PLACE ENTRYOMPARE TO LOW ADDRESS RET Z ;CARRY IS OFF AND ZERO IS SET IF COMPLETE MATCH RET C ;CARRY IS ON AND ZERO IS NOT SET IF TARGET IS LESS ; ; ADVANCE TO THE NEXT TABLE ENTRY ; NXTRY: INC HL ;PT TO HIGH ADDRESS INC HL ;PT TO TYPE OF NEXT CONTROL ENTRY INC HL ;PT TO LOW ADDRESS OF NEXT ENTRY IN TABLE JR SMORE ;CONTINUE ; ; DUMP CONTROL TABLE FROM ADDRESS IN DE ; CDUMP: CALL SCHCTL ;FIND ENTRY IN CONTROL TABLE >= ADDRESS IN DE JR CDUMP2 ; ; DUMP ENTIRE CONTROL TABLE ; CDUMP1: LD HL,W? JR Z,RNCTL CP 'H' ;DB HEX? JR Z,RNCTL CP 'B' ;DB? JR Z,RNCTL CP 'S' ;DS? JR Z,RNCTL CP 'E' ;END OF PROGRAM? JR Z,RNCTL CP 'K' ;KILL SYMBOL? JR Z,DELCTL JP WHAT ;ERROR IF NONE OF THESE ; ; READ A NEW CONTROL MODE ; ENTRY FORM IS: ; DW ADDRESS ; DB CONTROL MODE ; RNCTL: INC HL ;ADDRESS IS SAME INC HL ;PT TO CONTROL MODE LD (HL),A ;ONLY SET NEW CONTROL MODE RET ; ; DELETE THE ENTRY FROM THE CONTROL TABLE ; DELCTL: EX DE,HL ;DE PTS TO ENTRY TO DELETE LD,H ;CHECK HIGH BYTES CP B JR NZ,EXPTBL POP DE ;DE=NEW ENTRY ADDRESS, HL=ADDRESS TO INSERT AT LD (HL),E ;PLACE NEW ENTRY ADDRESS INTO TABLE INC HL LD (HL),D INC HL LD A,(OPCTP) ;PLACE NEW ENTRY TYPE INTO TABLE LD (HL),A RET ; ; SEARCH CTL TBL FOR AN ENTRY FOR (DE) ; ON EXIT, HL PTS TO LOW-ORDER BYTE OF CONTROL TABLE ENTRY IF MATCHED ; OR LESS THAN ; MATCH: C=0 ; NO MATCH: C=1 ; SCHCTL: LD HL,CTLTBL ;PT TO TABLE ; ; IF NO MATCH THEN CARRY IS SET ; SMORE:   CTLTBL ;PT TO FIRST ENTRY IN CONTROL TABLE CDUMP2: CALL BRKCHK ;CHECK FOR ABORT LD E,(HL) ;GET ADDRESS OF CONTROL ENTRY IN DE INC HL LD D,(HL) INC HL LD A,D ;CHECK FOR END OF TABLE AND E ;END IF DE=0FFFFH INC A ;SET A TO 0 IF SO JR NZ,MOREDMP CALL CRLF ;DONE, SO OUTPUT NEW LINE AND PRINT CONTROL INFO CALL CTLST JP GETCMD ; ; DUMP CONTROL TABLE ENTRY TO USER ; MOREDMP: PUSH DE PUSH HL CALL SYMSCH ;SEARCH FOR A SYMBOL WHOSE VALUE = ADDRESS IN DE JR C,AHEAD ;SKIP IF NOT FO;VALUE IN HL ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,HL ;*8 ADD HL,HL ;*16 ADD A,L ;ADD IN NEW VALUE LD L,A EX DE,HL ;VALUE BACK IN DE CALL READMA ;READ NEXT CHAR JR NUMLUP ;CONTINUE ; ; STORE THE ADDRESS ACCUMULATED IN DE INTO THE CONTROL TABLE ; STRDE: LD (HL),E ;STORE ADDRESS INC HL LD (HL),D INC HL CALL READMA ;READ CONTROL MODE CHAR LD (HL),A ;STORE IT INC HL ;PT TO NEXT CONTROL TABLE ENTRY JR LUP ; ; STORE ENDING 0FFFFH IN CONTROL TABLE ; TERMF: LD (HL),0FFH  DE INC HL LD D,(HL) INC HL LD A,D ;CHECK FOR END (0FFFFH) AND E INC A ;A=0 IF SO JR Z,CTLSVED CALL EXPND ;OUTPUT ADDRESS IN DE AS 4 HEX CHARS LD A,',' ;OUTPUT COMMA CALL WRTFILE LD A,(HL) ;OUTPUT CONTROL MODE CHAR CALL WRTFILE LD A,0DH ;OUTPUT NEW LINE CALL WRTFILE LD A,0AH CALL WRTFILE INC HL ;PT TO NEXT CONTROL TABLE ENTRY JR SVCTL1 ; ; THE CONTROL TABLE HAS BEEN SAVED ; CTLSVED: LD A,1AH ;WRITE EOF CALL WRTFILE CALL NXTRCRD RET ; ; READ IN A CONTROL TA: POP HL ;GET PTR PUSH HL LD A,(HL) ;CHECK FOR ANY TEXT CP 0DH ;IF NONE, OLD COMMENT IS JUST DELETED JP Z,GETCMD LD HL,(COMEND) ;PT TO END OF COMMENT TABLE LD (HL),E ;SAVE NEW ADDRESS OF COMMENT INC HL LD (HL),D INC HL POP DE ;PT TO FIRST CHAR OF COMMENT LD B,0 ;INIT CHAR COUNT TO ZERO PUSH HL ;SAVE ADDRESS TO CHAR COUNT OF COMMENT ; ; SAVE TEXT OF COMMENT ; STRTXT: INC HL ;PT TO POSITION TO STORE AT LD A,(DE) ;GET COMMENT TEXT LD (HL),A ;STORE IT INC DE ;PT TO NEXT UND ; ; PRINT A SYMBOL SINCE IT WAS FOUND; SYMBOL PTED TO BY HL ; CALL IECNT ;INIT ECNT CALL CRLF ;NEW LINE PRNTSYM: LD A,(HL) ;OUTPUT CHARS OF SYMBOL CALL COUT ;... COUNT IN B FROM SYMSCH INC HL DJNZ PRNTSYM LD A,':' ;OUTPUT COLON AFTER SYMBOL CALL COUT ; ; OUTPUT CONTROL TABLE ENTRY ; AHEAD: POP HL ;GET PTR TO CONTROL MODE POP DE ;GET ADDRESS OF ENTRY CALL SPACE ;2 S CALL SPACE EX DE,HL ;ADDRESS IN HL CALL PVALUE ;PRINT VALUE OF ADDRESS LD A,'=' ;PRINT DELIMITEINC HL LD (HL),0FFH RET ; ;COMMAND: ; ; COMMENT ROUTINE. IT ADDS OR LISTS COMMENTS ; CMNT: CALL AREACK ;VERIFY THAT COMMENT TABLE EXISTS LD HL,INBUF+3 ;PT TO CHAR AFTER COMMAND LD A,(HL) ;GET IT CP 0DH ;DONE? JP Z,LSTCMT ;YES, SO LIST COMMENTS CP 'O' ;LOOK FOR 'ON/OFF' SWITCH JR NZ,CMNT1 INC HL LD A,(HL) ;SECOND CHARACTER OF THE COMMENT SBC A,'F' ;CREATE A 0 FOR 'OFF' JR Z,CMNT2 CP 'N'-'F' ;LOOK FOR AN 'N' (FOR 'ON') JP NZ,WHAT CMNT2: LD (XCSW),A ;TURN OFF COMMENBLE ; ISCTL: CALL CTLRD ;READ CONTROL FILE JP STAT ;PRINT STATISTICS ; ; ROUTINE TO READ IN A CONTROL TABLE ; CTLRD: CALL RDOPEN ;OPEN FILE FOR READING LD HL,CTLTBL ;PT TO CONTROL TABLE LUP: CALL READMA ;READ NEXT CHAR LD DE,0 ;SET VALUE = 0 NUMLUP: CP 1AH ;ERROR IF EOF ENCOUNTERED JR Z,TERMF CP ',' ;DONE WITH NUMBER IF COMMA FOUND JR Z,STRDE CP '9'+1 ;CHECK FOR DIGIT JR C,NUM ;PROCESS IF SO SUB 7 ;ADJUST FOR 'A'-'F' NUM: SUB '0' ;CONVERT HEX ASCII TO BINARY EX DE,HL INC B ;INCR CHAR COUNT LD A,(DE) ;CHECK FOR DONE CP 0DH ;DONE IF JR NZ,STRTXT ;CONTINUE IF NOT INC HL ;PT TO ADDRESS AFTER LD (COMEND),HL ;SET PTR TO END OF COMMENT TABLE LD (HL),0FFH ;STORE 0FFFFH AS NEXT ENTRY INC HL LD (HL),0FFH POP HL ;GET PTR TO COMMENT CHAR COUNT LD (HL),B ;SAVE CHAR COUNT JP GETCMD ; ; CHECK FOR A COMMENT AT THE ADDRESS IN DE ; MATCH: CARRY IS OFF (NC CONDITION) ; CMCHK: LD HL,(COMST) ;PT TO START OF COMMENT TABLE CMCHK1: LD A,(HL) ;CRS CALL COUT LD A,' ' CALL COUT EX DE,HL ;RESTORE HL AS PTR TO CONTROL MODE LD A,(HL) ;GET CONTROL MODE LETTER CALL COUT ;PRINT IT CALL SPACE ; OUT CALL SPACE CALL SPCRLF ;OUTPUT NEW LINE OCCASIONALLY INC HL ;PT TO NEXT CONTROL TABLE ENTRY JR CDUMP2 ; ; SAVE THE CONTROL TABLE ON DISK ; SVCTL: CALL SVCTL0 ;USE ROUTINE JP GETCMD ; ; ROUTINE TO SAVE THE CONTROL TABLE ON DISK ; SVCTL0: CALL OPEN ;OPEN FILE LD HL,CTLTBL ;PT TO TABLE SVCTL1: LD E,(HL) ;GET ADDRESS INTS JP GETCMD ; ; PROCESS NEW COMMENT ENTRY ; CMNT1: CALL CNVRT ;GET ADDRESS IN DE INC HL ;PT TO NEXT CHAR CP 0DH ;IF DONE, WE DELETE COMMENT JP Z,ONECMT CP ' ' ; OR ',' SAYS TEXT FOLLOWS JR Z,CMNT0 CP ',' JP NZ,WHAT ;ERROR IF NOT , , OR ',' CMNT0: PUSH HL ;SAVE PTR TO NEXT CHAR CALL CMCHK ;CHECK FOR COMMENT ALREADY AT ADDRESS IN DE JR C,ADDCMT ;IF NOT, JUST ADD COMMENT CALL DELCMT ;IF SO, FIRST DELETE EXISTING COMMENT ; ; ADD COMMENT TO COMMENT TABLE ; ADDCMT  HECK ADDRESS FOR 0FFFFH INC HL AND (HL) DEC HL INC A ;A=0 IF SO SCF ;PREP FOR ERROR RETURN RET Z ;NOT FOUND IF A=0 INC HL ;PT TO ADDRESS HIGH LD A,D ;GET TARGET ADDRESS IN DE CP (HL) ;COMPARE AGAINST THAT STORED DEC HL ;PT TO ADDRESS LOW JR NZ,NXTC ;IF NOT A MATCH, CONTINUE LD A,E ;COMPARE LOW BYTES CP (HL) RET Z ;THERE IS A COMMENT AT THIS ADDRESS, SO CARRY=1 NXTC: INC HL ;PT TO CHAR COUNT INC HL LD A,(HL) ;GET CHAR COUNT CALL SKIP ;SKIP TO NEXT COMMENT INC HL ;PT TO comments table ++',0DH DEFB 0AH,0 JP GETCMD ; ;COMMAND: U ; DEFINE THE COMMENTS AREA ; UAREA: LD HL,INBUF+3 ;CHECK ARGS LD A,(HL) CP 0DH ;ERROR IF JUST JP Z,WHAT CP '.' ;ERROR IF SYMBOL JP Z,WHAT CALL CNVRT ;CONVERT TO NUMBER IN DE EX DE,HL ;... IN HL LD A,H ;CHECK FOR WITHIN RANGE CP (SYMTAB+600H) SHR 8 ;THIS ALLOWS 600H BYTES FOR SYM TBL JR C,UAREA0 ;ERROR IF LESS LD (COMST),HL ;SET START AND END OF TABLE LD (COMEND),HL LD (HL),0FFH ;SET ENDING 0FFFFH IN TABLE HL ;PT TO ADDRESS IN CURRENT COMMENT PUSH DE ;SAVE ADDRESS TO DELETE LD D,H ;SAVE ADDRESS OF CURRENT COMMENT IN DE LD E,L INC HL ;PT TO CHAR COUNT OF CURRENT COMMENT INC HL LD A,(HL) ;GET IT IN A CALL SKIP ;SKIP TO NEXT COMMENT INC HL ;PT TO ITS ADDRESS LD B,0 ;INIT TO NOT DONE FOR LOOP ; ; COPY (HL) TO (DE) UNTIL FFFFH IS ENCOUNTERED ; SHFTCT: LD A,(HL) ;GET CHAR LD (DE),A ;PUT CHAR INC HL ;PT TO NEXT INC DE LD C,A ;DONE IF BC=0FFFFH AND B INC A ;A=0 IF DONE LD B,C ;CONTINUE HSYM1: POP HL RESUME: XOR A ;PRINT ADDRESS OF PC ON CRT LD (WRTENAB),A ;.. BUT NOT INTO THE FILE CALL SPACE ; OVER CALL SPACE LD HL,(PC) ;PRINT PC VALUE CALL PVALUE LD A,1 ;REENABLE WRITE OF MNEMONIC LD (WRTENAB),A CALL TAB ;TAB FOR FOLLOWING MNEMONIC POP HL POP DE RET ; ; BUILD A SYMBOL IN INBUF FOR THE VALUE IN DE ; BLDSYM: LD HL,INBUF ;PT TO INBUF LD (HL),'L' ;STORE LEADING L INC HL ;PT TO NEXT CHAR LD A,D ;GET VALUE IN DE CALL ACCTOASC ;S LOW BYTE OF NEXT COMMENT JP CMCHK1 ; ; DUMP COMMENT TABLE FROM A GIVEN ADDRESS FORWARD ; ONECMT: CALL CMCHK ;FIND COMMENT REFD IN DE JR LSTAGN ; ; DUMP ENTIRE COMMENT TABLE ; LSTCMT: LD HL,(COMST) ;PT TO FIRST COMMENT LSTAGN: CALL BRKCHK ;CHECK FOR ABORT LD E,(HL) ;GET ADDRESS OF COMMENT IN DE INC HL LD D,(HL) INC HL LD A,D ;CHECK FOR 0FFFFH AS END OF TABLE AND E INC A ;A=0 IF SO JP Z,GETCMD ;DONE IF SO EX DE,HL ;VALUE IN HL CALL PVALUE ;PRINT IT EX DE,HL ;VALUE I INC HL LD (HL),0FFH JP GETCMD UAREA0: CALL PSTRNG ;PRINT ERROR MESSAGE DEFB 'NO!! Address is less than ' DEFB 0 LD HL,SYMTAB+600H LD L,0 CALL PVALUE CALL CRLF JP GETCMD ; ; HANDLE SYMBOLS FOR THE DISASSEMBLER; ADDRESS IN PC ; IF A SYMBOL EXISTS AT THIS ADDRESS, PRINT IT ; HSYM: PUSH DE PUSH HL LD A,1 ;ENABLE DISK OUTPUT LD (WRTENAB),A LD HL,(PC) ;GET ADDRESS OF PC EX DE,HL ;... IN DE CALL SYMSCH ;LOOK FOR SYMBOL JP C,RESUME ;GOTO RESUME IF NO SYMBOL LD C,B ;JR NZ,SHFTCT ;CONTINUE UNTIL TWO SUCCESSIVE FF'S FOUND EX DE,HL ;SET END OF COMMENT TABLE DEC HL DEC HL LD (COMEND),HL POP DE RET ; ; CHECK TO SEE THAT AREA FOR COMMENTS WAS DEFINED (START <> 0) AND ; ABORT WITH ERROR MESSAGE IF NOT ; AREACK: LD HL,(COMST) ;HL=START ADDRESS LD A,H OR L RET NZ ;ERROR IF ZERO CALL PSTRNG DEFB '++ COMMAND IGNORED ++',0DH DEFB 0AH,'++ Issue ''UNNNN'' to tell ' DEFB 'DASM to use address ' DEFB 'NNNN',0DH,0AH,'as the start ' DEFB 'of theTORE AS ASCII CHARS IN BUFFER LD A,E CALL ACCTOASC LD HL,INBUF ;PT TO SYMBOL LD B,5 ;SYMBOL IS 5 CHARS LONG ; ; INSERT A SYMBOL ALPHABETICALLY INTO TABLE ; INSERT: CALL PLCSYM ;FIND SYMBOL JR C,NEWSYM ;PROCESS AS NEW IF NOT FOUND LD (HL),E ;IF FOUND, SET NEW ADDRESS FOR IT INC HL LD (HL),D RET ; ; INSERT NEW SYMBOL INTO TABLE; LOCATION TO INSERT AT PTED TO BY HL ; NEWSYM: PUSH HL PUSH DE PUSH BC LD HL,(SYMEND) ;MOVE THE TABLE BY LENGTH+3 LD D,H ;DE PTS TO END OF SYMN DE, PTR TO COMMENT CHAR COUNT IN HL LD A,';' ;PRINT SEMICOLON BEFORE COMMENT CALL COUT LD B,(HL) ;GET CHAR COUNT IN B TEXT: INC HL ;PT TO COMMENT CHAR LD A,(HL) ;GET AND PRINT IT CALL COUT DJNZ TEXT ;CONTINUE UNTIL DONE CALL CRLF ;NEW LINE INC HL ;PT TO ADDRESS OF NEXT COMMENT JR LSTAGN ;CONTINUE ; ; DELETE AN EXISTING COMMENT WHOSE ADDRESS IS IN DE; HL PTS TO CMT TABLE ; DELCMT: LD A,(HL) ;CHECK FOR END OF COMMENT TABLE INC HL AND (HL) INC A ;A=0 IF AT END RET Z DEC GET CHAR COUNT OF SYMBOL INTO C PUSH HL ;SAVE PTR TO IT ; ; CHECK TO SEE THAT SYMBOL CONTAINS NO + OR -; DON'T PRINT IF IT DOES ; HSYM0: LD A,(HL) ;GET CHAR CP '+' ;CHECK IT JR Z,HSYM1 CP '-' JR Z,HSYM1 INC HL ;PT TO NEXT DEC C ;CONTINUE TO END OF SYMBOL JR NZ,HSYM0 POP HL ;PT TO SYMBOL CALL PRNT ;PRINT THE SYMBOL LD A,':' ;.. AND A FOLLOWING COLON CALL COUT CALL TAB ;PRINT THE TAB CALL PDERTN ;PRINT THE ADDRESS AS A COMMENT (ADR IN DE) CALL CRLF ;NEW LINE JR RESUME   BOL TABLE LD E,L LD A,B ;LENGTH OF SYMBOL IN A ADD A,3 ;LENGTH OF SYMBOL + 3 ADD A,L ;PT TO NEW END OF TABLE LD L,A LD A,H ADC A,0 LD H,A LD (SYMEND),HL ;NEW END OF SYMBOL TABLE INC HL ;PT TO LENGTH OF SYMBOL AFTER LAST ONE INC HL LD (HL),0 ;SET THIS TO ZERO TO MARK END OF TABLE DEC HL DEC HL LD B,H ;ADDRESS OF LAST BYTE IN BC LD C,L LD HL,(SYMRKR) ;ADDRESS OF REV DEST TO MOVE TO IN HL ; ; EXPAND THE TABLE UNTIL SPACE IS MADE AT THE NEW SPOT ; LUP3: LD A,E ;AT DESTINSKPOVR: INC HL ;CHECK CHAR COUNT FOR DONE LD A,(HL) ;0 IF DONE OR A SCF ;SET CARRY FOR NO MATCH IF SO RET Z INC HL ;PT TO NEXT SYMBOL ADD A,L LD L,A JR NC,MORE INC H JR MORE ; ; RETURN WITH NO CARRY AND LENGTH IN B IF MATCHED ; FNDSYM: INC HL LD A,(HL) INC HL LD B,A OR A ;MATCH RET NZ SCF ;NO MATCH RET ; ;COMMAND: E ; PLACE A SYMBOL IN THE SYMBOL TABLE ; ENTER: LD HL,INBUF+3 ;CHECK FOR CHARS AFTER THE E CALL CNVRT ;GET VALUE LD A,(HL) ;CHECK FOR ERLL CHKSTG ;COMPARE (DE) TO (HL) JR Z,FOUND JR C,NONE ; ; TARGET SYMBOL GOES BEHIND CURRENT SYMBOL ; LATER: POP HL ;GET ADDRESS OF SYMBOL TABLE SYMBOL LD A,(HL) INC HL CALL SKIP ;SKIP TO NEXT JR ANTHR ; ; MATCH OF SYMBOLS ; FOUND: POP HL DEC HL DEC HL POP DE POP DE OR A ;RET WITH CARRY CLEAR FOR MATCH RET ; ; CHECK SHORTER STRING FOR PARTIAL MATCH ; LESS: LD C,A CALL CHKSTG JR NC,LATER JR NONE NTLESS: LD C,B CALL CHKSTG JR Z,NONE JR NC,LATER ; ; CHECK FOR SYMBOL SPECIFIED LD A,(HL) ;MUST BE '.' CP '.' JP NZ,WHAT CALL LNGTH ;GET LENGTH IN B CALL PLCSYM ;FIND SYMBOL PTED TO BY HL JP C,WHAT ;ERROR IF NOT FOUND CALL KILL0 ;KILL IT JP GETCMD ; ; KILL THE SYMBOL WHOSE VALUE IS PTED TO BY HL ; KILL0: LD B,H ;SAVE PTR IN BC LD C,L INC HL INC HL LD A,(HL) ;GET THE LENGTH OF THE SYMBOL INC HL CALL SKIP ;SKIP TO NEXT EX DE,HL ;DE PTS TO NEXT SYMBOL LD HL,(SYMEND) ;SHIFT THE SYMBOL TABLE DOWN TO DELETE SYM LUP4: LD A,ATION? CP L JR NZ,AHD LD A,D CP H JR Z,STICKAD ;DONE IF SO AHD: DEC DE ;COPY BACKWARDS (DE) TO (BC) DEC BC LD A,(DE) LD (BC),A JR LUP3 ; ; ENTER THE ADDRESS AND LENGTH ; STICKAD: POP BC POP DE LD (HL),E ;STORE ADDRESS OF SYMBOL INC HL LD (HL),D INC HL LD (HL),B ;STORE LENGTH OF SYMBOL POP DE ; ; STORE THE SYMBOL STRING ; STICKSM: INC HL LD A,(DE) LD (HL),A INC DE DJNZ STICKSM RET ; ; FIND SPOT FOR NEW SYMBOL PTED TO BY HL, VALUE IN DE, B=LENGTH ROR CP ' ' ;MUST BE FOLLOWED BY OR ',' JR Z,ENTER0 CP ',' JP NZ,WHAT ; ; GET SYMBOL ; ENTER0: INC HL ;PT TO SYMBOL LD A,(HL) ;GET '.' CP '.' ;MUST BE '.' JP NZ,WHAT PUSH DE ;SAVE THE SYMBOL'S VALUE PUSH HL ;SAVE THE BUFFER PTR CALL SYMSCH ;RETURN WITH C=0 FOR MATCH ;.. B=LENGTH HL=START OF STRING JR C,ENTER1 ;NOTHING TO DELETE PUSH HL CALL CRLF ;PRINT MESSAGE THAT SYMBOL WAS KILLED CALL PRNT CALL PSTRNG DEFB ' was Killed',0DH,0AH,0 POP HL DEC HL  THERE IS NO SYMBOL FOR THIS VALUE, SO THIS VALUE SHOULD GO AT HL ; NONE: POP HL DEC HL DEC HL LD (SYMRKR),HL ;SET MARKER POP HL POP DE SCF ;SET CARRY FOR NO MATCH RET ; ; SEARCH THE SYMBOL TABLE FOR AN ENTRY WHOSE VALUE IS DE ; MATCH: C=0 ; SYMSCH: LD HL,SYMTAB ;PT TO SYMBOL TABLE ; ; (HL) IS START OF SYMBOL; (B) IS LENGTH ; MORE: LD A,(HL) ;GET AND COMPARE SYMBOL TABLE VALUES INC HL CP E JR NZ,SKPOVR LD A,(HL) CP D JR Z,FNDSYM ; ; GOTO NEXT SYMBOL ; E ;SHIFT COMPLETE? CP L JR NZ,AHD1 LD A,D CP H JR Z,DEAD AHD1: LD A,(DE) ;COPY DOWN LD (BC),A INC BC INC DE JR LUP4 ; ; THE SYMBOL IS DEAD -- SET NEW END OF SYMBOL TABLE ; DEAD: LD H,B LD L,C LD (SYMEND),HL ;SET END INC HL INC HL LD (HL),0 ;SET END OF TABLE MARKER RET ; ; SCAN SYMBOL STARTING AT (HL) AND RETURN WITH LENGTH IN B, PTR TO FIRST ; CHAR OF SYMBOL IN HL, AND PTR TO CHAR AFTER LAST CHAR IN SYMBOL IN DE ; LNGTH: INC HL ;PT TO FIRST CHAR LD B,0 ;OF SYMBOL ; RETURN: C=0 FOR MTCH, HL=SYMBOL ; PLCSYM: PUSH DE ;SAVE VALUE PUSH HL ;SAVE ADDRESS OF SYMBOL LD HL,SYMTAB ;PT TO SYMBOL TABLE ANTHR: POP DE ;GET SYMBOL ADDRESS IN DE PUSH DE INC HL ;PT TO SYMBOL CHAR COUNT INC HL PUSH HL LD A,(HL) ;GET CHAR COUNT INC HL ;PT TO FIRST CHAR OR A ;CHECK FOR END OF SYMBOL TABLE JR Z,NONE ;GOTO NONE IF AT END OF TABLE CP B ;COMPARE SYMBOL LENGTHS JR C,LESS ;NO MATCH IF NOT SAME LENGTH JR NZ,NTLESS LD C,A ;SYMBOL LENGTH IN C CADEC HL DEC HL CALL KILL0 ;KILL SYMBOL ENTER1: POP HL PUSH HL CALL LNGTH ;COMPUTE LENGTH OF SYMBOL IN B POP DE LD A,B ;CHECK FOR SYMBOL TOO LONG CP SYMMAX+1 JR C,ENTER2 PUSH HL LD BC,SYMMAX ;SET TO MAX LENGTH LD H,D ;HL=DE LD L,E INC HL ;ADD 1 FOR 1ST CHAR ADD HL,BC LD (HL),0 ;TERMINATE SYMBOL LD B,C ;B=SYMMAX POP HL ENTER2: POP DE CALL INSERT ;INSERT SYMBOL INTO SYMBOL TABLE JP GETCMD ; ;COMMAND: K ; DELETE A SYMBOL FROM THE TABLE ; KILL: LD HL,INBUF+3 ;  INIT LENGTH PUSH HL CHAROK: LD A,(HL) ;GET CHAR INC HL ;PT TO NEXT INC B ;INCR LENGTH CP '+' ;CHECK FOR END OF SYMBOL MARK JR Z,CHAROK CP '-' JR Z,CHAROK CP '0' JR C,ILLSYM CP '9'+1 JR C,CHAROK CP 'A' JR C,ILLSYM CP 'Z'+1 JR C,CHAROK ; ; AN ILLEGAL CHARACTER FOUND IN A SYMBOL SCAN, SO SCAN IS DONE ; ILLSYM: DEC B ;COMPENSATE FOR COUNT JP Z,WHAT ;ERROR IF NO SYMBOL CHARS DEC HL ;BACK UP EX DE,HL ;PTR TO NEXT CHAR IN DE POP HL ;PT TO FIRST CHAR IN HL RET ;  0 LD (FCBNR),A LD DE,FCB ;PT TO FCB LD C,0FH ;OPEN THE FILE CALL BDOS POP HL INC A ;FILE FOUND? RET NZ ;RET IF SO CALL PSTRNG ;ERROR IF NOT DEFB ' File Not Found',0DH,0AH,0 EX (SP),HL ;SAVE HL ON STACK POP HL ;RESTORE HL RET ; JP GETCMD ;OLD ERROR RETURN ; ; READ NEXT BYTE FROM DMA BUFFER AND RETURN IT IN A ; READMA: PUSH HL ;SAVE HL LD HL,(DMAPTR) ;PT TO NEXT BYTE LD A,H ;BEYOND END OF BUFFER? CP 1 ;1 IF SO JR NZ,NOTREAD ;IF NOT, THEN GET THE BYTE PUSH BC D LINE AND CONVERT AND PLACE IN (DE) ; CNVRT: LD A,(HL) ;GET FIRST CHAR CP '.' ;IT IS A SYMBOL IF '.' JR Z,ITSASYM LD DE,0 ;INIT VALUE TO ZERO AGAIN: LD A,(HL) ;GET CHAR CP '0' ;IN RANGE? RET C ;DONE IF NOT CP '9'+1 ;RANGE? JR C,NUMER ;OK IF SO CP 'A' ;RANGE? RET C ;DONE IF NOT CP 'F'+1 ;RANGE? RET NC ;DONE IF NOT SUB 7 ;CONVERT FOR 'A'-'F' NUMER: SUB '0' ;CONVERT FROM ASCII TO BINARY EX DE,HL ;HL=VALUE ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,HL ;*8 ADD HL,HL ;*16 ADS OR A ;ERROR? JR NZ,WRTERR LD DE,FCB ;CLOSE THE FILE LD C,10H CALL BDOS INC A ;ERROR IN CLOSING? RET NZ CALL PSTRNG ;SAY SO IF SO DEFB '++ Close Error ++',0DH,0AH,0 JP GETCMD ; ; AN ERROR OCCURRED DURING A WRITE RECORD ATTEMPT ; WRTERR: CALL PSTRNG DEFB '++ Write Error ++',0DH,0AH,0 ; ; WRITE INTO THE DMA BUFFER AND WRITE TO DISK WHEN IT FILLS ; CHAR TO WRITE PASSED IN A ; WRTFILE: PUSH HL LD HL,(DMAPTR) ;GET PTR LD (HL),A ;STORE NEXT CHAR INC L ;PT TO NEXT L; CONVERT THE ACCUMULATOR TO HEX ASCII IN MEMORY PTED TO BY HL (2 BYTES) ; ACCTOASC: PUSH AF CALL HINIB ;CONVERT HIGH NYBBLE LD (HL),A ;STORE IT INC HL ;PT TO NEXT POP AF CALL LONIB ;CONVERT LOW NYBBLE LD (HL),A ;STORE IT INC HL ;PT TO NEXT RET ; ; CONVERT THE HIGH NIBBLE OF A TO ASCII CHAR ; HINIB: RRA ;ROTATE HIGH NYBBLE TO LOW NYBBLE RRA RRA RRA ; ; CONVERT THE LOW NYBBLE OF A TO ASCII CHAR ; LONIB: AND 0FH ;MASK OUT NEW HIGH NYBBLE CP 10 ;CHECK FOR DIGIT JR ;SAVE BC, DE PUSH DE LD DE,FCB ;PT TO FCB LD C,14H ;READ RECORD INTO DMA ADDRESS CALL BDOS OR A ;SET FLAG FOR ERROR POP DE ;RESTORE REGS POP BC LD HL,RECLEN ;PT TO FIRST BYTE OF BUFFER JR NZ,ERROR ;ERROR IF EOF ENCOUNTERED NOTREAD: LD A,(HL) ;GET NEXT CHAR IN A INC HL ;PT TO CHAR AFTER LD (DMAPTR),HL ;SET PTR FOR LATER USE POP HL ;RESTORE HL RET ERROR: CP 3 JR C,RDDMA0 CALL PSTRNG DEFB '++ Unexpected EOF ++',0DH,0AH DEFB 0 JP GETCMD ; ; AT EOF ... SET ^Z AS RESPD A,L ;ADD IN NEW NYBBLE LD L,A EX DE,HL ;DE=VALUE INC HL ;PT TO NEXT CHAR JR AGAIN ;CONTINUE ; ; EVALUATE THE SYMBOL IN MEMORY AND RETURN WITH VALUE IN DE ; ITSASYM: CALL LNGTH ;DETERMINE LENGTH OF SYMBOL PUSH DE CALL PLCSYM ;FIND IT IN TABLE JP C,WHAT ;ERROR IF NOT FOUND LD E,(HL) ;PUT ITS VALUE IN DE INC HL LD D,(HL) POP HL LD A,(HL) RET ; ; OPEN A FILE FOR READING ; RDOPEN: PUSH HL LD HL,0100H ;SET DMA TO 100H LD (DMAPTR),HL XOR A ;SET NEXT RECORD FIELD TOD (DMAPTR),HL ;SET NEXT DMA POP HL RET NZ ;IF L REACHED ZERO, BUFFER WAS FULL; RET IF NZ PUSH BC ;WRITE RECORD TO DISK AND REINIT DMA PTR PUSH DE PUSH HL LD DE,FCB ;DO THE WRITE LD C,15H CALL BDOS OR A ;ERROR? JR NZ,WRTERR LD HL,RECLEN ;RESET DMA PTR LD (DMAPTR),HL POP HL POP DE POP BC RET ; ; PRINT COMMENT IF PTED TO BY XCPTR ; DCRLF: LD HL,(XCPTR) LD A,H OR L ;LOOK FOR A COMMENT ADDRESS JR Z,DCRLF3 CALL TAB ;TABULATE COMMENT LD B,(HL) ;GET CHAR COUNT XORC,AHD2 ;SKIP IF SO ADD A,7 ;ADD OFFSET OF 7 FOR '9' TO 'A' AHD2: ADD A,'0' ;CONVERT TO ASCII IN A RET ; ; PRINT THE HEX CHARACTERS FOR THE VALUE IN A ; PHEX: PUSH AF CALL HINIB ;PRINT HIGH NYBBLE CALL COUT POP AF CALL LONIB ;PRINT LOW NYBBLE JP COUT ; ; PRINT THE 4 HEX CHARACTERS FOR CONTENTS OF HL ; PVALUE: LD A,H ;PRINT HIGH BYTE CALL PHEX LD A,L ;PRINT LOW BYTE CALL PHEX ; ; PRINT A ; SPACE: LD A,' ' ;PRINT JP COUT ; ; READ HEX ASCII FROM COMMANONSE CHAR FROM READ ; RDDMA0: LD A,1AH LD (HL),A JR NOTREAD ; ; OPEN FILE PTED TO BY FCB FOR OUTPUT ; OPEN: PUSH HL LD DE,FCB ;ERASE IT FIRST LD C,13H CALL BDOS LD DE,FCB ;NOW CREATE IT LD C,16H CALL BDOS INC A ;ERROR IN CREATING IT? JP Z,WHAT ;SAY SO (NO ROOM IN DIR) XOR A ;SET RECORD FIELD TO ZERO LD (FCBNR),A LD HL,RECLEN ;SET DMA ADDRESS LD (DMAPTR),HL POP HL RET ; ; WRITE THE NEXT RECORD TO OPEN FILE ; NXTRCRD: LD DE,FCB ;WRITE IT LD C,15H CALL BDO   A ;CHECK FOR NO COMMENT OR B JR Z,DCRLF2 DCRLF1: INC HL ;OUTPUT COMMENT LD A,(HL) CALL COUT DJNZ DCRLF1 DCRLF2: LD HL,0 ;SET NO COMMENT NOW LD (XCPTR),HL DCRLF3: LD (RPLPTR),HL ;SET RPLPTR=0 ; ; OUTPUT ; CRLF: LD A,0DH CALL COUT LD A,0AH JP COUT ; ; PRINT THE PROMPT ; PRTSTAR: LD A,'*' ; ; PRINT THE CHARACTER IN A ON CON: AND/OR DISK ; THE FOLLOWING FLAGS TAKE EFFECT: ; HUSH (QUIET MODE) -- IF =0, CON: OUTPUT, ELSE NO CON: OUTPUT ; FOPEN (FILE OPE,IBUFLEN ;SIZE OF INPUT LINE BUFFER LD (INBUF),A LD A,INITDLEN-1 ;INITIAL SIZE OF MEMORY DUMP LD (DMPLEN),A LD A,INITLCNT ;INITIAL SIZE OF LIST DISPLAY LD (NLINES),A LD (LCTR),A LD HL,BLNGTH ;INITIAL CTL PTR LD (NXTCTL),HL LD HL,INITPC ;INITIAL VALUE OF PC LD (DMPSTRT),HL LD (DMPEND),HL LD (PC),HL LD HL,INITOFF ;INITIAL OFFSET LD (OFFSET),HL LD HL,INITELST ;INITIAL END OF LISTING VALUE LD (ENDLST),HL LD HL,COMTBL ;INITIAL POSITION OF COMMENTS LD (COMST),HL LD (COMEND),HT BUFFER SIZE LD (DE),A LD C,10 ;READ INTO BUFFER FCT CALL BDOS LD HL,INBUF+1 ;PT TO CHAR COUNT READ LD E,(HL) ;GET IT IN DE LD D,0 ADD HL,DE ;PT TO AFTER LAST CHAR IN BUFFER INC HL LD (HL),0DH ;STORE ENDING LD HL,INBUF+1 ;PT TO CHAR COUNT OF BUFFER ; ; CONVERT TO UPPER CASE ; UPPR: INC HL ;PT TO NEXT CHAR LD A,(HL) ;GET IT CP 0DH ;DONE? JP Z,CRLF CP 61H ;SMALL A? JR C,UPPR ;OK IF LESS CP 7BH ;SMALL Z + 1? JR NC,UPPR ;OK IF MORE AND 5FH ;CAPITALIZE LD (HL),ABDOS OR A ;NONE IF ZERO JR Z,AHD3 LD C,1 ;GET NEW CHAR CALL BDOS CP 3 ;CHECK FOR ^C JR Z,ABORT ;ABORT IF SO CALL CRLF ;ELSE NEW LINE JP GETCMD ABORT: CALL PSTRNG ;PROMPT USER DEFB 0DH,0AH,'Abort (Y/N)? ',0 CALL CHIN CP 'Y' JP Z,WBOOT JP GETCMD AHD3: POP HL POP DE POP BC RET ; ; CHECK FOR AN ASCII CHARACTER IN A ; RETURN WITH ZERO TRUE AND NO CARRY FOR , ; RETURN WITH NO CARRY IF PRINTABLE ASCII ; ISITASC: CP 0DH RET Z ;NO CARRY CP 0AH RET N) AND WRTENAB (WRITE ENABLE) -- IF BOTH <>0, DISK ; OUTPUT ; CNTENAB (COUNT ENABLE) -- IF <>0, ENABLE COUNT (LCTR) ; COUT: PUSH AF ;SAVE REGS PUSH BC PUSH DE PUSH HL LD E,A ;CHAR IN E PUSH DE ;PREP TO PRINT CHAR LD C,2 ;USE BDOS OUTPUT LD A,(HUSH) ;QUIET MODE? OR A ;0=YES CALL Z,BDOS ;PRINT THE CHAR IF NOT QUIET MODE POP DE LD A,(FOPEN) ;GET FILE OPEN FLAG LD HL,WRTENAB ;PT TO FILE WRITE ENABLED FLAG AND (HL) ;IF BOTH ENABLED, WRITE CHAR TO DISK ALSO LD A,E ;CHAR IL RET ; ; INITIALIZE SYMBOL TABLE, CONTROL TABLE, AND COMMENTS TABLE ; SET EOL ; INIT: XOR A ;A=0 LD (SYMTAB+2),A ;CLEAR SYMBOL TABLE BY SET CHAR COUNT OF LD HL,SYMTAB ;... FIRST ENTRY TO ZERO LD (SYMEND),HL ;SET END ADDRESS OF SYMBOL TABLE LD A,0DH ;SET END OF INPUT LINE LD (INBUF+3),A LD HL,0FFFFH ;SET NO ENTRIES IN CONTROL TABLE LD (CTLTBL),HL LD A,'I' ;SET FOR INSTRUCTION MODE INITIALLY LD (CTLTBL-1),A ;"PREVIOUS" CONTROL TABLE ENTRY IS SET TO 'I' LD HL,COMTBL ;SET ADDRE ;PUT CHAR JR UPPR ;CONTINUE ; ; PRINT THE STRING: ADDR AT TOP OF STACK, TERMINATED BY 0 ; PSTRNG: XOR A ;DISABLE QUIET MODE AND DISK OUTPUT LD (WRTENAB),A LD (HUSH),A PSTG: EX (SP),HL ;PT TO STRING IN HL AND SAVE OLD HL LUP5: LD A,(HL) ;OUTPUT CHARS CALL COUT INC HL ;PT TO NEXT LD A,(HL) ;GET NEXT CHAR OR A ;DONE? JR NZ,LUP5 INC HL ;PT TO AFTER STRING EX (SP),HL ;RESTORE HL AND SET NEW RET ADR RET ; ; INITIALIZE SPECIAL CONSTANTS SO CODE IS REENTRANT ; INIT0: LD AZ ;NO CARRY CP ' ' RET C ;CARRY IF < CP 7FH CCF ;CARRY IF > 7FH RET ; ; FILE TYPES ; TPALL: DEFB 'ALL' ;FILE TYPE FOR ALL (CTL, SYM, DOC, COM, AND ASM) FILES TPASM: DEFB 'ASM' ;ASM FILE TYPE TPCOM: DEFB 'COM' ;COM FILE TYPE TPCTL: DEFB 'CTL' ;CTL FILE TYPE TPSYM: DEFB 'SYM' ;SYM FILE TYPE TPDOC: DEFB 'DOC' ;DOC FILE TYPE DEFB '.' ; ; BUFFERS ; RELEND: DEFS 2 ;RELATIVE END ADDRESS OF COM FILE DMPSTRT: DEFS 2 ;STARTING ADDRESS OF DUMP (CURRENT ADDR ALSO) DMPEN A, NOT ZERO FLAG = DISK OUTPUT CALL NZ,WRTFILE ;WRITE TO DISK IF OK LD A,E ;CHECK FOR CP 0AH JR NZ,COUT1 LD A,(CNTENAB) ;DECREMENT THE LINE COUNT IF A WAS SENT OR A ;CHECK IF COUNTING ENABLED JR Z,COUT1 LD HL,LCTR ;PT TO LINE COUNT DEC (HL) ;DECREMENT IT COUT1: POP HL ;RESTORE REGS AND EXIT POP DE POP BC POP AF RET ; ; PROMPT AND READ A COMMAND LINE FROM THE KEYBOARD ; PROMPT: CALL PRTSTAR ;PRINT PROMPT LD DE,INBUF ;PT TO INPUT LINE BUFFER LD A,80 ;SESS OF COMMENT TABLE LD (COMST),HL ;START ADDRESS LD (COMEND),HL ;END ADDRESS LD (HL),0FFH ;CLEAR FIRST ENTRY TO NO COMMENT INC HL LD (HL),0FFH RET ; ; RETURN WITH ZERO IF STRINGS (DE) AND (HL) MATCH; LENGTH IS (C) ; CHKSTG: LD A,(DE) ;GET CHAR CP (HL) ;COMPARE RET NZ ;NO MATCH INC DE ;PT TO NEXT INC HL DEC C ;COUNT DOWN JR NZ,CHKSTG RET ; ; WATCH THE CONSOLE FOR A BREAK KEY AND ABORT IF SO ; BRKCHK: PUSH BC PUSH DE PUSH HL LD C,0BH ;CHECK FOR KEY PRESS CALL   ND: DEFS 2 ;ENDING ADDRESS OF DUMP DMPLEN: DEFS 2 ;NUMBER OF BYTES TO DUMP AT ONE TIME - 1 OFFSET: DEFS 2 ;OFFSET VALUE SYMEND: DEFS 2 ;END OF SYMBOL TABLE PC: DEFS 2 ;CURRENT VALUE OF PC ENDLST: DEFS 2 ;END OF LISTING PTR BIASED: DEFS 2 ;BIASED OFFSET COMST: DEFS 2 ;START ADDRESS OF COMMENTS COMEND: DEFS 2 ;END ADDRESS OF COMMENTS ADB: DEFS 1 ;FLAG FOR DB BUILD (0=HEX, <>0=ASCII AND HEX) FNDPC: DEFS 2 ;TEMP PC FOR FIND FUNCTION FNDADD: DEFS 2 ;TEMP ADDRESS FOR FIND FUNCTI DASM: CALL HSYM ;WRITE A SYMBOL IF IT EXISTS ;.. AND PUT PC ON THE CRT LD HL,(RPLPTR) ;SEE IF THIS LINE IS REPLACED LD A,H OR L JR Z,DASM1 LD B,(HL) INC HL ;SKIP THE '*' DEC B CALL NWLN0 ;PRINT THE REPLACING LINE AS A COMMENT DASM1: LD HL,(PC) EX DE,HL LD HL,(OFFSET) ADD HL,DE ;HL IS NOW THE BIASED PC LD (BIASED),HL EX DE,HL ;DE IS NOW THE BIASED PC INC HL LD (PC),HL ;THE NEW PC (NEXT BYTE) EX DE,HL ;DE IS THE BYTE AFTER THE INSTRUCTION LD B,(HL) LD HL,OPG $/100H*100H+100H ENDALL EQU $ END UT TYPEOC: INC HL ;TYPE THE OPCODE THAT HL IS POINTING TO LD A,(HL) OR A JR Z,TYPEOC JP P,TOC2 LD HL,(PC) LD A,(OPCTP) RET ; JMPTBL: DEFW T0 ;SIMPLE 1 BYTE INSTRUCTIONS DEFW T1 ;8 BIT, REGISTER ARITHMETIC & LOGICAL DEFW T2 ;DEC & INC DEFW T3 ;DOUBLE REGISTER SINGLE BYTE ARITHMETIC DEFW T4 ;8 BIT LOAD FROM MEMORY DEFW T5 ;8 BIT LOAD TO MEMORY DEFW T6 ;POP's AND PUSH's DEFW T7 ;CONDITIONAL RETURNS DEFW T8 ;THE RST INSTRUCTIONS DEFW T9 ;REGISTER TO REGISTER LOON ECNT: DEFS 1 ;TEMP LINE COUNTER NLINES: DEFS 1 ;NUMBER OF LINES FOR LIST LCTR: DEFS 1 ;COUNTER FOR LINES CNTENAB: DEFS 1 ;ENABLE LINE COUNT IF <> 0, ELSE DISABLE LINE CNT WRTENAB: DEFS 1 ;OUTPUT TO FILE IS ENABLED IF <> 0, NOT IF 0 RPLPTR: DEFS 2 ;MISC PTR XCPTR: DEFS 2 ;MISC PTR XCSW: DEFS 1 ;MISC PTR FOPEN: DEFS 1 ;FILE IS OPEN IF <> 0, NOT OPEN IF 0 HUSH: DEFS 1 ;DON'T PRINT COMMAND RESULT (QUIET MODE) IF 0 NXTCTL: DEFS 2 ;PTR TO NEXT CTL ENTRY BLNGTH: DEFS 1 ;BUFFEC-4 CALL GTCD CALL TYPEOC CP 0AH ;TYPES 0 THRU 9 ARE 1 BYTE JR C,OLDPC ; .. SO DON'T CHANGE THE PC LD HL,(PC) INC HL CP 10H ;TYPES 0A THRU 0FH ARE 2-BYTERS JR C,NEWPC CP 16H ;TYPES 10H THRU 15H ARE 3 BYTES JR NC,NEWPC INC HL NEWPC: LD (PC),HL OLDPC: PUSH DE ;SAVE THE 'E' REGISTER (MAY BE 'X' OR 'Y') LD E,A LD D,0 LD HL,JMPTBL ADD HL,DE ;ADD 2*OPCODE TYPE TO JMPTBL TO GET ADD HL,DE ;.. ROUTINE ADDRESS LD E,(HL) INC HL LD D,(HL) EX DE,HL ;HL NOW CONTAINS T; ;DASMZLG.MAC from DASM.ZLG (ver. >= 3.0) ;This routine is the ZILOG mnemonic disassembler module for DASM.MAC. ;It is included into DASM during assembly under M80. ; IF1 .PRINTX /DASM with ZILOG-Standard Mnemonics/ ENDIF ; ; This is the Header to be printed for this module ; HEADER: DEFB 'DASM for ZILOG-Standard Mnemonics',0dh,0ah DEFB ' Derived from ZZSOURCE/RESOURCE',0dh,0ah DEFB '$',0 ; ; This is the Disassembler Module -- Instruction to be disassembled ; is pted to by PC ;ADS ;2 BYTE INSTRUCTIONS DEFW TA ;8 BIT LOAD IMMEDIATES DEFW TB ;8 BIT IMMEDIATE ARITH. & LOGICAL DEFW TC ;IN A,(n) DEFW TD ;OUT (n),A DEFW TE ;CONDITIONAL, RELATIVE JUMPS DEFW TF ;OTHER RELATIVE JUMPS ;3 BYTE INSTRUCTIONS DEFW T10 ;16 BIT LOADS DEFW T11 ;JUMPS & CALLS DEFW T12 ;DIRECT LOADS DEFW T13 ;DIRECT STORES DEFW T14 ;LD (nn),A DEFW T15 ;CONDITIONAL JUMPS & CALLS ;MULTI-BYTE OPCODES DEFW T16 ;THE 'CB' SERIES {1, 1A, 2A} DEFW T17 ;THE 'DD' SERIES {1B thru 2R LENGTH SYMRKR: DEFS 2 ;SYMBOL MARKER DMAPTR: DEFS 2 ;PT TO DMA ADDRESS ASCBLD: DEFS 1 ;FLAG FOR A COMMAND (0=NOT A) BUILD: DEFS 1 ;FLAG FOR B COMMAND (0=NOT B) OPCTP: DEFS 3 ; ; INPUT LINE BUFFER ; INBUF: DEFS 1 ;SIZE OF BUFFER DEFS IBUFLEN+1 ;SIZE OF INPUT LINE AND BUFFER CONTENTS ; ; STACK AREA ; DEFS 40 ;STACK SPACE OLDST: DEFS 2 ;OLD STACK PTR ; DEFS 1 ;1 BYTE FOR INITIAL 'I' IN CONTROL TABLE ; ; NEXT PAGE AFTER PROGRAM MARKS BEGINNING OF BUFFER AREAS ; ORHE ROUTINE ADDRESS POP DE PUSH HL LD HL,(BIASED) RET ;'RETURN' TO THE ROUTINE ; GTCD: LD DE,4 NXTCD: ADD HL,DE NXTCD1: LD A,(HL) OR A ;SEE IF WE'RE AT THE NEXT MASK YET INC HL JP P,NXTCD1 ;JUMP IF NOT AND B ;MASK OUT VARIABLES IN THE INSTRUCTION CP (HL) ;CHECK THE GENERIC INSTRUCTION TYPE JR NZ,NXTCD INC HL LD A,(HL) ;AFTER A MATCH, GET THE OPCODE TYPE LD (OPCTP),A RET ; TOC2: CP 20H ;CONVERT SPACES IN THE TABLE TO TABS JR NZ,TOC1 LD A,9 TOC1: CALL CO  5 & 2A} DEFW T18 ;THE 'FD' SERIES {1B thru 25 & 2A} DEFW T19 ;THE 'ED' SERIES {0, 2, 3, 26 thru 2A} ;1 BYTE DEFW T1A ;THE BIT, RES & SET FOR 'CB' DEFW T1B ;INDEX REGISTER LOADS DEFW T1C ;JUMP INDIRECT INDEX REGISTER DEFW T1D ;INDEX REGISTER ADD ;2 BYTE DEFW T1E ;INDEX REGISTER ARITH. AND LOGICAL DEFW T1F ;INDEXED LOAD TO REGISTER DEFW T20 ;INDEXED REGISTER STORE ;3 BYTES AFTER 'DD' OR 'FE' DEFW T21 ;LD xx,nn DEFW T22 ;LD (nn),n DEFW T23 ;LD xx,(nn) DEFW T24 ;LD (xx+E,HL CALL PRNTDE CALL C,PDERTN JP DCRLF ; ;THREE BYTE INSTRUCTIONS ;16 BIT LOADS ; T10: CALL PXSREG CALL COMMA LD HL,(BIASED) ;JUMPS AND CALLS T11: CALL PRNN CALL C,PDERTN JP DCRLF ; ;LOAD DIRECT ; T12: CALL DRADR CALL C,PDERTN JP DCRLF DRADR: CALL LPAR ;PRINT THE VALUE FOR DE IN PARENTHESIS CALL PRNN PUSH AF CALL RPAR POP AF RET ; ;STORE DIRECT ; T13: CALL DRADR PUSH AF CALL COMMA LD A,'H' CALL COUT LD A,'L' CALL COUT POP AF CALL C,PDE LD HL,(BIASED) CALL PSREG JP DCRLF ; ;TWO BYTE INSTRUCTIONS ; 8 BIT IMMEDIATE LOADS ; TA: CALL PDREG CALL COMMA LD HL,(BIASED) ;ARITHMETIC & LOGICAL IMMEDIATES TB: INC HL DTABYT: LD A,(HL) CP ' ' JR C,NOTASC CP 5BH JR NC,NOTASC CALL PASCII LD A,'''' CALL COUT LD A,(XCSW) ;WANT SYMBOL COMMENTS? OR A JP Z,DCRLF CALL TAB CALL SEMI NOTASC: LD A,(HL) CP 0AH JR C,NTSC0 CALL PASHEX LD A,'H' CALL COUT JP DCRLF NTSC0: ADD A,'0' CALL COUT JP DCRLFCALL COMMA CALL PSREG JP DCRLF ; ;INDEX REGISTER MOVES ; T1B: CALL PRXX ;TO TYPE EITHER 'IX' OR 'IY' JP DCRLF ; ;JUMP INDIRECT TO INDEX REGISTER ; T1C: CALL LPAR CALL PRXX CALL RPAR JP DCRLF ; ;INDEX REGISTER ADDITION ; T1D: CALL PRXX CALL COMMA LD A,E CP 'X' LD A,(HL) LD HL,IXREGS JR Z,T1D0 LD HL,IYREGS T1D0: CALL PXREG JP DCRLF ; ;INDEX REGISTER ARITHMETIC AND LOGICAL ; T1E: INC HL CALL PDISP ;PRINT '(IX(Y)+d) JP DCRLF ; ;INDEXED LOAD TO REGISd),n DEFW T25 ;THE 'CB' EXTENSIONS TO 'DD' OR 'FD' ;1 BYTE AFTER 'ED' DEFW T26 ;IN r,(C) DEFW T27 ;BLOCK MOVES ;3 BYTES AFTER 'ED' DEFW T28 ;LD (nn),dd DEFW T29 ;LD dd,(nn) ;WHATEVER IS LEFT DEFW T2A ;INDEFINED OPCODES ; ;ONE BYTE INSTRUCTIONS, SIMPLE ; T0: JP DCRLF ; ;ARITHMETIC & LOGICAL, 8 BIT, REGISTER ; T1: CALL PSREG ;PRINT THE SOURCE REGISTER JP DCRLF ; ;DEC AND INC INSTRUCTIONS ; T2: CALL PDREG ;PRINT THE DESTINATION REGISTER JP DCRLF ; ;DOUBLE REGISTERTN JP DCRLF ; ;STORE ACCUMULATOR DIRECT ; T14: CALL DRADR PUSH AF CALL PCMAA POP AF CALL C,PDERTN JP DCRLF ; ;CONDITIONAL JUMPS & CALLS ; T15: CALL PRCND CALL COMMA LD HL,(BIASED) CALL PRNN CALL C,PDERTN JP DCRLF ; ;THE 'CB' SERIES LEAD IN ; T16: INC HL LD B,(HL) ;THE SECOND BYTE OF THE INSTRUCTION LD (BIASED),HL LD HL,OPC2-4 CALL GTCD ;FIND THE TYPE OF THE 'CB' INSTRUCTION CALL TYPEOC JP OLDPC ; ;THE 'DD' SERIES LEAD IN ; T17: LD E,'X' ;FOR THE  ; ;IN ; TC: CALL LPAR ;FOR 'IN A,(C)' INC HL LD A,(HL) CALL PASHEX LD A,'H' CALL COUT CALL RPAR JP DCRLF ;OUT TD: CALL LPAR INC HL LD A,(HL) CALL PASHEX LD A,'H' CALL COUT CALL RPAR CALL COMMA LD A,'A' CALL COUT JP DCRLF ; ;CONDITIONAL RELATIVE JUMPS ; TE: CALL PRCND1 ;THE SPECIAL CC LIST LD HL,(BIASED) CALL COMMA ;OTHER RELATIVE INSTRUCTIONS TF: INC HL LD A,(HL) LD E,A LD D,0 LD HL,(PC) OR A JP P,PSTV DEC D PSTV: ADD HL,DE EX DTER ; T1F: CALL PDREG CALL COMMA LD HL,(BIASED) INC HL CALL PDISP JP DCRLF ; ;INDEXED REGISTER STORE ; T20: INC HL CALL PDISP CALL COMMA LD HL,(BIASED) CALL PSREG JP DCRLF ; ; LD xx,nn ; T21: CALL PRXX CALL COMMA CALL PRNN CALL C,PDERTN JP DCRLF ; ; LD (nn),xx ; T22: CALL LPAR PUSH DE CALL PRNN EX DE,HL ;HL NOW CONTAINS THE NUMBER POP DE ;RECOVER THE 'E' REG. ('X' OR 'Y') PUSH AF ;SAVE THE CARRY FOR A LATER 'PEDRTN' CALL RPAR CALL COMMA R SINGLE BYTE ; T3: CALL PXSREG ;PRINT HL, DE, BC, OR SP JP DCRLF T4: CALL LPAR ; LD A,(BC or DE) CALL PXSREG CALL RPAR JP DCRLF T5: CALL LPAR ; LD (BC or DE),A CALL PXSREG CALL RPAR CALL PCMAA JP DCRLF ; ;POP AND PUSH ; T6: CALL PXQREG ;PRINT HL, DE, BC, OR AF JP DCRLF ; ;CONDITIONAL RETURNS ; T7: CALL PRCND JP DCRLF ; ;THE RST INSTRUCTIONS ; T8: LD A,(HL) AND 38H CALL PRST JP DCRLF ; ;REGISTER TO REGISTER LOADS ; T9: CALL PDREG CALL COMMA'IX' INSTRUCTIONS T170: PUSH DE INC HL LD (BIASED),HL LD B,(HL) LD HL,OPC3-4 CALL GTCD CALL TYPEOC POP DE CP 1EH JP C,OLDPC CP 2AH JP Z,OLDPC CP 21H INC HL JP C,NEWPC INC HL JP NEWPC ; ;THE 'FD' SERIES LEAD IN ; T18: LD E,'Y' JR T170 ; ;THE 'ED' SERIES LEAD IN ; T19: INC HL LD (BIASED),HL LD B,(HL) LD HL,OPC4-4 CALL GTCD CALL TYPEOC CP 28H JP C,OLDPC CP 2AH JP Z,OLDPC INC HL INC HL JP NEWPC ; ;BIT, RES AND SET ; T1A: CALL PBIT    CALL PRXX POP AF ;THE CARRY FLAG IS RESTORED EX DE,HL ;DE AGAIN CONTAINS THE VALUE FOR nn CALL C,PDERTN JP DCRLF ; ; LD xx,(nn) ; T23: CALL PRXX CALL COMMA CALL LPAR CALL PRNN PUSH AF ;SAVE Cy VALUE CALL RPAR POP AF CALL C,PDERTN JP DCRLF ; ; LD (xx+d),n ; T24: INC HL CALL PDISP CALL COMMA JP TB ; ;THE 'CB' EXTENSIONS TO 'DD' OR 'FD' ; T25: INC HL INC HL LD B,(HL) LD HL,OPC2-4 PUSH DE ;SAVE 'X' OR 'Y' CALL GTCD CALL TYPEOC POP DE LD A,B ;RA RRA JP PREG ; ; ADVANCE H&L BY (A) ; SKIP: ADD A,L LD L,A RET NC INC H RET REGTAB: DEFB 'BCDEHLMA' ;'M' IS NEVER PRINTED - '(HL)' IS INSTEAD ; ; PRINT A DOUBLE REGISTER PAIR ; PXSREG: LD A,(HL) LD HL,DREGS JR PXREG PXQREG: LD A,(HL) LD HL,DREGQ PXREG: RRA RRA RRA AND 6 CALL SKIP LD A,(HL) CALL COUT INC HL LD A,(HL) JP COUT DREGS: DEFB 'BCDEHLSP' DREGQ: DEFB 'BCDEHLAF' IXREGS: DEFB 'BCDEIXSP' IYREGS: DEFB 'BCDEIYSP' ; PBIT: LE FOR A 'DB VALUE' TREATMENT ; T2A: LD HL,(PC) DEC HL LD (PC),HL LD HL,(BIASED) DEC HL CALL PSTG DEFB 'DB',9,0 JP DTABYT ; ; VARIOUS CHARACTERS TO PRINT ; COMMA: LD A,',' JP COUT TAB: LD A,9 JP COUT SEMI: LD A,';' JP COUT LPAR: LD A,'(' JP COUT RPAR: LD A,')' JP COUT PCMAA: CALL COMMA LD A,'A' JP COUT ; ; PRINT THE CONDITION CODE LETTERS FOR THIS INSTRUCTION. ; PRCND: LD A,(HL) AND 38H ;FOR A FULL SET OF CONDITION CODES PRC: RRCA RRCA A SYMBOL? OR A POP DE JR Z,NOBLD ;JUST PRINT THE HEX VALUE PUSH DE CALL BLDSYM POP DE JR NOBLD PDERTN: LD A,(XCSW) OR A RET Z ;DON'T PRINT THE SYMBOL AS A COMMENT CALL TAB ;WE'LL PRINT A VALUE AS A COMMENT CALL SEMI NOBLD: LD A,D OR E LD A,'0' JR Z,NOBLD1 LD A,D OR A JR Z,NOBLD2 CALL PASHEX ;PRINT THE HIGH ORDER BYTE LD A,E CALL PHEX NOBLD0: LD A,'H' NOBLD1: CALL COUT OR A ;CLEAR THE CARRY RET NOBLD2: LD A,E PRST: CP 0AH JR C,NOBLD3 CALGET THE O.C. AND 7 CP 6 JR NZ,ILLEG LD A,(OPCTP) LD HL,(BIASED) CP 1AH JP C,T1E JR Z,DD12 ILLEG: LD HL,(PC) DEC HL DEC HL LD (PC),HL JP T2A DD12: INC HL INC HL CALL PBIT CALL COMMA DEC HL DEC HL JP T1E ; ; IN r,(C) ; T26: CALL PDREG CALL COMMA CALL LPAR LD A,'C' CALL COUT CALL RPAR JP DCRLF ; ;THE BLOCK MOVES AND I/O ; T27: LD A,(HL) AND 8 LD A,'I' ;AN INCREMENTING TYPE OF INSTRUCTION? JP Z,T270 LD A,'D' ;NO, IT WAS DECREMENTING T2D A,(HL) RRA RRA RRA AND 7 ADD A,'0' JP COUT PRXX: LD A,'I' CALL COUT LD A,E JP COUT ; ;PRINT A LEADING QUOTE AND THEN THE ASCII ;.. (PRINT '' FOR '). ; PASCII: PUSH AF LD A,'''' CALL COUT POP AF CP '''' JP NZ,COUT PUSH AF CALL COUT POP AF JP COUT ;PRINT THE VALUE IN A AS HEX ; WITH A LEADING ZERO IF NECESSARY PASHEX: CP 0A0H JP C,PHEX PUSH AF LD A,'0' CALL COUT POP AF JP PHEX ;PRINT THE STRING AT (HL) FOR (B) CHARACTERS. PRNT: LD A,(HL)LD HL,CNDTAB CALL SKIP LD A,(HL) CALL COUT INC HL LD A,(HL) CP '.' CALL NZ,COUT RET PRCND1: LD A,(HL) AND 18H JR PRC CNDTAB: DEFB 'NZZ.NCC.POPEP.M.' ; ; PRINT THE SOURCE REGISTER FOR A BYTE ; PSREG: LD A,(HL) PREG: LD HL,REGTAB AND 7 CP 6 ;MUST CATCH THE (HL) REFERENCES JP Z,PHLREG CALL SKIP LD A,(HL) JP COUT PHLREG: CALL LPAR LD A,'H' CALL COUT LD A,'L' CALL COUT JP RPAR PDREG: LD A,(HL) ;PRINT THE DESTINATION REGISTER FOR A BYTE RRA RL PASHEX JR NOBLD0 NOBLD3: ADD A,'0' JR NOBLD1 ; ; OPCODE TABLES ; OPC: DEFB 0FFH,0EBH,0,'EX DE,HL' DEFB 0FFH,008H,0,'EX AF,AF''' DEFB 0FFH,0D9H,0,'EXX' DEFB 0FFH,0E3H,0,'EX (SP),HL' DEFB 0FFH,027H,0,'DAA' DEFB 0FFH,0F3H,0,'DI' DEFB 0FFH,0FBH,0,'EI' DEFB 0FFH,076H,0,'HALT' DEFB 0FFH,02FH,0,'CPL' DEFB 0FFH,03FH,0,'CCF' DEFB 0FFH,000H,0,'NOP' DEFB 0FFH,037H,0,'SCF' DEFB 0FFH,0E9H,0,'JP (HL)' DEFB 0FFH,007H,0,'RLCA' DEFB 0FFH,017H,0,'RLA' DEFB 0FFH,00FH,0,'RRCA' DE70: CALL COUT LD A,(HL) AND 10H JP Z,DCRLF LD A,'R' ;A REPEATING INSTRUCTION TYPE CALL COUT JP DCRLF ; ; LD (nn),dd ; T28: CALL LPAR CALL PRNN PUSH AF ;SAVE Cy VALUE PUSH DE ;SAVE THE 'NN' VALUE CALL RPAR CALL COMMA LD HL,(BIASED) CALL PXSREG POP DE POP AF CALL C,PDERTN JP DCRLF ; ; LD dd,(nn) ; T29: CALL PXSREG CALL COMMA LD HL,(BIASED) CALL LPAR CALL PRNN PUSH AF CALL RPAR POP AF CALL C,PDERTN JP DCRLF ; ;ALL UNDEFINED OPCODES COME HER CALL COUT INC HL DEC B JP NZ,PRNT RET ; ;PRINT A DISPLACEMENT IN THE FORM '(IX+d)' PDISP: CALL LPAR CALL PRXX LD A,'+' CALL COUT LD A,(HL) CALL PASHEX LD A,'H' CALL COUT JP RPAR ; ;PRINT THE NEXT 2 BYTES AS A SYMBOL (AND RETURN Cy=1) IF POSSIBLE ; PRNN: INC HL LD E,(HL) INC HL LD D,(HL) PRNTDE: PUSH DE CALL SYMSCH JP C,NOMTCH CALL PRNT ;GOT ONE, SO PRINT IT POP DE SCF ;INDICATE THAT A SYMBOL WAS PRINTED RET NOMTCH: LD A,(BUILD) ;DO WE BUILD   FB 0FFH,01FH,0,'RRA' DEFB 0FFH,0C9H,0,'RET' DEFB 0FFH,0F9H,0,'LD SP,HL' DEFB 0F8H,088H,1,'ADC A,' DEFB 0F8H,080H,1,'ADD A,' DEFB 0F8H,0A0H,1,'AND ' DEFB 0F8H,0B8H,1,'CP ' DEFB 0F8H,0B0H,1,'OR ' DEFB 0F8H,098H,1,'SBC A,' DEFB 0F8H,090H,1,'SUB ' DEFB 0F8H,0A8H,1,'XOR ' DEFB 0C7H,005H,2,'DEC ' DEFB 0C7H,004H,2,'INC ' DEFB 0CFH,009H,3,'ADD HL,' DEFB 0CFH,00BH,3,'DEC ' DEFB 0CFH,003H,3,'INC ' DEFB 0EFH,00AH,4,'LD A,' DEFB 0EFH,002H,5,'LD ' DEFB 0CFH,0C1H,6,'POP ' DEFB 0CFH,0,00H,'IM 1' DEFB 0FFH,05EH,00H,'IM 2' DEFB 0FFH,047H,00H,'LD I,A' DEFB 0FFH,04DH,00H,'RETI' DEFB 0FFH,04FH,00H,'LD R,A' DEFB 0FFH,057H,00H,'LD A,I' DEFB 0FFH,05FH,00H,'LD A,R' DEFB 0FFH,067H,00H,'RRD' DEFB 0FFH,06FH,00H,'RLD' DEFB 0CFH,042H,03H,'SBC HL,' DEFB 0CFH,04AH,03H,'ADC HL,' DEFB 0C7H,040H,26H,'IN ' DEFB 0C7H,041H,02H,'OUT (C),' DEFB 0E7H,0A0H,27H,'LD' DEFB 0E7H,0A1H,27H,'CP' DEFB 0E7H,0A2H,27H,'IN' DEFB 0F7H,0A3H,27H,'OUT' DEFB 0F7H,0B3H,27H,'OT' DEFB 0CFH,043H,201H,'SRL ' DEFB 0C0H,040H,1AH,'BIT ' DEFB 0C0H,080H,1AH,'RES ' DEFB 0C0H,0C0H,1AH,'SET ' DEFB 080H,000H,2AH OPC3: DEFB 0FFH,0E3H,1BH,'EX (SP),' DEFB 0FFH,0E9H,1CH,'JP ' DEFB 0FFH,0F9H,1BH,'LD SP,' DEFB 0FFH,0E1H,1BH,'POP ' DEFB 0FFH,0E5H,1BH,'PUSH ' DEFB 0CFH,009H,1DH,'ADD ' DEFB 0FFH,023H,1BH,'INC ' DEFB 0FFH,02BH,1BH,'DEC ' DEFB 0FFH,034H,1EH,'INC ' DEFB 0FFH,035H,1EH,'DEC ' DEFB 0FFH,086H,1EH,'ADD A,' DEFB 0FFH,08EH,1EH,'ADC A,' DEFB 0FFH,096H,1EH,'SUB ' DEFB 0FFH,09E Dissassembly of a .COM file using DASM.COM Everybody needs or wants to disassemble a program some time, usually just to modify a small section of it for an application that the program was not originally intended. At Micro Cornucopia we get a lot of programs with no source code that "almost" work on the Kaypro. This is where DASM is invaluable. ZZSOURCE (on user disk K2) was a good program but hard to use the first time. This often caused a block for some people that they could never get paC5H,6,'PUSH ' DEFB 0C7H,0C0H,7,'RET ' DEFB 0C7H,0C7H,8,'RST ' DEFB 0C0H,040H,9,'LD ' DEFB 0C7H,006H,0AH,'LD ' DEFB 0FFH,0C6H,0BH,'ADD A,' DEFB 0FFH,0CEH,0BH,'ADC A,' DEFB 0FFH,0E6H,0BH,'AND ' DEFB 0FFH,0FEH,0BH,'CP ' DEFB 0FFH,0F6H,0BH,'OR ' DEFB 0FFH,0D6H,0BH,'SUB ' DEFB 0FFH,0DEH,0BH,'SBC A,' DEFB 0FFH,0EEH,0BH,'XOR ' DEFB 0FFH,0DBH,0CH,'IN A,' DEFB 0FFH,0D3H,0DH,'OUT ' DEFB 0E7H,020H,0EH,'JR ' DEFB 0FFH,010H,0FH,'DJNZ ' DEFB 0FFH,018H,0FH,'JR ' DEFB 0CFH,001H,10H,'LD '8H,'LD ' DEFB 0CFH,04BH,29H,'LD ' DEFB 080H,000H,2AH,0,0 DEFB 080H,080H,2AH ; ; END OF OPCODE TABLE ; H,1EH,'SBC A,' DEFB 0FFH,0A6H,1EH,'AND ' DEFB 0FFH,0AEH,1EH,'XOR ' DEFB 0FFH,0B6H,1EH,'OR ' DEFB 0FFH,0BEH,1EH,'CP ' DEFB 0C7H,046H,1FH,'LD ' DEFB 0F8H,070H,20H,'LD ' DEFB 0FFH,021H,21H,'LD ' DEFB 0FFH,022H,22H,'LD ' DEFB 0FFH,02AH,23H,'LD ' DEFB 0FFH,036H,24H,'LD ' DEFB 0FFH,0CBH,25H,0,0 DEFB 080H,000H,2AH,0,0 DEFB 080H,080H,2AH OPC4: DEFB 0FEH,070H,2AH,0,0;PREVENTS 'IN (HL),(C)' DEFB 0FFH,044H,00H,'NEG' DEFB 0FFH,045H,00H,'RETN' DEFB 0FFH,046H,00H,'IM 0' DEFB 0FFH,056Hst. DASM is a re-write of ZZSOURCE that makes it much easier to use, the first time and again and again. The built in help screen in itself is a major improvement but there is more to this version than that. This documentation is designed for the beginning disassembler though for most it is all they need know. A good text editor can do wonders for a file that is only partially disassembled with DASM and this is how I usually use DASM. For an example, lets disassemble the file on this disk CRC.CO DEFB 0FFH,0C3H,11H,'JP ' DEFB 0FFH,0CDH,11H,'CALL ' DEFB 0FFH,03AH,12H,'LD A,' DEFB 0FFH,02AH,12H,'LD HL,' DEFB 0FFH,022H,13H,'LD ' DEFB 0FFH,032H,14H,'LD ' DEFB 0C7H,0C4H,15H,'CALL ' DEFB 0C7H,0C2H,15H,'JP ' DEFB 0FFH,0CBH,16H,0,0 DEFB 0FFH,0DDH,17H,0,0 DEFB 0FFH,0FDH,18H,0,0 DEFB 0FFH,0EDH,19H OPC2: DEFB 0F8H,000H,01H,'RLC ' DEFB 0F8H,008H,01H,'RRC ' DEFB 0F8H,010H,01H,'RL ' DEFB 0F8H,018H,01H,'RR ' DEFB 0F8H,020H,01H,'SLA ' DEFB 0F8H,028H,01H,'SRA ' DEFB 0F8H,038H,  M. Enter DASM by entering: DASM DASM will sign on and give you a prompt (*). It also will tell you how to get the help screen and stats. The help screen is a list of all the commands that DASM will except. Display it by entering: H The first thing we need to do is read the file we want to disassemble into memory. Since DASM sets up an offset automatically we only need to enter: RCRC.COM DASM will tell us where the file resides: Last Block Rehe program needs an end but we have already done that. We will want equates for the labels that DASM created. To get these and an origin statement at the beginning of our .ASM file enter: P100,FFF Then write the rest of the file to disk by entering: L100,FFF Then exit DASM by entering a ^C. We will still need to fiddle with the file to get it to assemble again. If you are using the M80 assembler you will need to add ASEG and .Z80 lines to the beginning of the program and change the anyway. Now we can enter the end of file mark by entering: CBFF,E Where BFF is the HEX address of the end of the program that we found. Now DASM will stop when it reaches this point because we told it that the program ends here. The next thing to do is to look for DB's in the program. DASM will do this for us. Enter: A100,FFF Notice that we entered a range that exceeds the length of our program but that DASM will stop at BFF since we told it that this is the end of the program. The files named .CPM are actually .COM files for CP/M. If you copy the files to a CP/M system without using 22DISK, just rename all *.CPM to .COM ad into Memory at 5800 Last Block Ends at Relative 0C00 The second address is of the most interest to us. The file actually resides in high memory but the disassembler makes it seem as if it is at 100H. It also makes it seem as if it ends at 0C00. We only need to worry about the relative addresses and DASM will do the offset for us. If we enter: L100 DASM will disassemble the first 20 lines of the program CRC.COM as if it were at 100H (where .COM files are loaded by CP/M). The next thingextent to .MAC . The CROWECPM assembler will require that you change the DB's to DEFM's and change the extent to .Z80 . Then try to assemble it. There will probably be a few errors since DASM does not always find all the labels when building an equate table. Add these in to the source file with a text editor. Since DASM names the labels by their address with an L in front of it this is easily done. For example an equate for L0100 would look like this: L0100 EQU 0100H Once you have found thTake a look at the program with the L command to see what DASM has done. Now we should build labels. Enter: B100,FFF DASM will create labels starting with L and ending with a hex address. Then it places these labels in the jump and move instructions etc. Examine our program with the L command to see what it looks like now. We almost have a workable source file out of the .COM file. It is time to get it out to disk. To begin this process enter: SCRC.ASM DASM will remind you that t to do is to define the end of the program. It is unlikely that a program will fill an entire block to the last byte. We can find the actual end by dumping memory (relative) until we find what seems to be the end of the program. To do this enter: DB80 This dumps memory up to BFFH. It appears that CRC.COM ends a little before 0C00 but not to much farther before. We can end the program at BFFH just to be sure we have it all. The trailing 0's will disassemble as NOP's which won't bother us much e undefined labels the program should reassemble. You can verify that the .COM files are identical with CRC.COM or COMPARE.COM ( on disks K2 and K16 ). For more information on DASM see DASM.DOC.   j1B͉͖1! !  !  ! l!K ʙ!t ʨ! ʳ!  !I~ ( (1#> 1*N~ ( ( (I;(!'  (1# (-;(# ):B0= ( 8> > 1>2B:C=2C>.͞> 2C:D=2D͕><2D~1#~ ( 1#!~ (% (!;~:(% (, ((;($ ( 1# ͮ:(<#1~ (8~E(e( >2)>:1>2)y8:)( > 1> 1> 1~; "GIͷ"N<~(I <Ð ~ ( (1#> 1ACI ADC SBI SBC IN IN LDA LD LDAX LD LHLD LD 8MOV LD QPCHL JP rRST RST {SHLD LD SPHL LD STA LD OUT OUT STAX LD XCHG EX XTHL EX IFC IF EICL *INCLLLST LIST SMAC MACROZXLATE2 -- 8080-to-Z80 Translator, Version 1.2 XLATE2 translates 8080 assembly language source code into Zilog-Standard Z80 assembly language source code. It is invoked by a command of the following form: XLATE2 d:SRCFILE.typ d:destfile.typ All #N#~( y"< #Ʌo#> bk *Pw :B= :B<2B#:R= Ss!S>"P2ReÇ:R(>12E2F!P[&:( *=c*2(S&!(4w (P ( 8# +:E 7:F X; >2E:F( ' 2F ' >2F#6 #6S&:* >;2xP> 1> 1Öa{_̀!͕͕͕͕,͕͕͕͞_ANI AND CMA CPL CMC CCF CPI CP HLT HALT JMP JP ORI OR RAL RLA RAR/MXLATE2 Processing Complete The following pseudo-ops have been used in your source and have not been fully translated. You must complete the translation using an editor. Original: Must Be Translated To: #ENDIF ENDIF ICL *INCLUDE LST LIST MAC <$parameters> MACRO <#parameters> [ ... ] MEND #macro-call macro-call ASMMAC*N~M“#!Ó(HL)*N~B(!D("H(#P (#~S "#~W ##!` !c!f!i#ÓAFBCDEHL:J!E(!N( !L(!~2J#~2KZ NZC NC!ÐRET ! CALL !>,1ÐJP :J1:K 1 N#F!HL,! A,!6A,(*N~B(D( Ó!*!1A,(BC)A,(DE)!L>)1ÓHL,(*N~M !#~1#1! ! 8*>(1!"),HL!fSP,HL>(1!Ó),A*N~B(D(Ó!!*N#Ó(BC),A(DE),A! Dcharacters in lower case are optional, and, if omitted, the following values are assumed: . The Source File will have a type of ASM . The Destination File will have the same name as the Source File . The Destination File will have a type of MAC Type to Continue - The following are examples of its use: XLATE2 DEMO1 <-- Translates DEMO1.ASM to DEMO1.MAC XLATE2 DEMO1 DEMO2 <-- DEMO1.ASM to DEMO2.MAC XLATE2 DEMO1.TXT DEMO2.GGG <-- DEMO1.TXT to DEMO2.GGG  RRA RLC RLCA RRC RRCA STC SCF SUI SUB XRI XOR DB DEFB DS DEFS DW DEFW SET DEFL ENT ENTRYNAM NAME RAM DATA ROG REL ANA AND CMP CP DCR DEC INR INC MVI LD ORA OR SUB SUB XRA XOR DCX DEC INX INC LXI LD POP POP PUSH PUSH REQ RNE RLT RGE CEQ CNE CLT CGE JEQ JNE JLT JGE RC RNC RZ RNZ RP RM RPE RPO CC CNC CZ CNZ CP CM CPE CPO JC JNC JZ JNZ JP JM JPE JPO DAD ADD ADD ADD ADC ADC SBB SBC ADI ADD E,HL!Ð(SP),HL*N~;( (#+~ ( (#*Nz {~1#> 2> 2 > 2> 2,> 2!Ð:]/ ͕# ͕)͕ ͕> 2C><2D>2B>V!V~(1#:m 2 2a 2 !\ ~ (!m~+ !\ !u~ (1͕!?͕!͕~@͞>:͞#6>.͞6~#͞(>2(Ç &(>2R!S"PÇ͕XY‡͕#H'~ ( #!~,:+-/* ); H F The following functions are also performed by XLATE2: . The M80 Pseudo-Ops .Z80 and ASEG will be inserted at the front of the MAC File . The text in the Destination File will be capitalized . All comment lines beginning with an asterisk will begin with a semicolon instead Source File: Destination File: .Z80 ASEG Output File Write Error No Source File Found No Directory Space Output File Already Exists -- Delete It and Continue (Y/N)? XLATE2 Aborting to CP   XLATE2 Documentation XLATE2.COM is a program that translates 8080 assembly language files into Z80 assembly language in a form suitable for Microsoft's M80 assembler. Since Z80 mnemonics are easier to read and the M80 assembler is so popular, this program is a valuable addition to any assembly language programmers library. When we first tried this program there were some problems with the file created for M80 that M80 would not tolerate. The translator wanted to place a colon behind every lactives ".Z80" and "ASEG" (near the beginning of the file). 3. Modify the lines containing DEFB assignments. M80 will allow you to mix DEFB's and ascii in single quotes if seperated by commas. CROWECPM requires that DEFB assignments to be single bytes (either labels or numbers) and that ascii assignments be DEFM assignments. For example, the following line is acceptable syntax for M80: DEFB 'this is ascii',0DH,0AH The same line modified for the CROWECPM assembler would look like this:  CODE SET 1 LD BC,10 ;10 CHARS/DUAL ENTRY (OLD OP = 5, NEW OP = 5) CALL CMPOP ;SCAN FOR MATCH IN INLN BUFFER JP Z,DOOCS1 ;PROCESS IF FOUND ; LD HL,OCS2 ;PROCESS OP CODE SET 2 LD BC,10 ;10 CHARS/DUAL ENTRY CALL CMPOP ;SCAN FOR MATCH JP Z,DOOCS2 ;PROCESS ; LD HL,OCS3 ;PROCESS OP CODE SET 3 LD BC,10 ;10 CHARS/DUAL ENTRY CALL CMPOP ;SCAN FOR MATCH JP Z,DOOCS3 ;PROCESS ; LD HL,OCS4 ;PROCESS (EXTENDED RET) OP CODE SET 4 LD BC,5 ;5 CHARS/SINGLE ENTRY CALL CMPOP ;SCAN FOR MATCH CALLbel. This is not allowed in an equate. We fixed this problem so that for most files one only needs to run XLATE2 and assemble the resulting .MAC file. There are still a few statements that will cause the translator problems. The addition of a colon is only supressed for an EQU statement line but a DEFL statement line will still receive a colon behind the label. The best way to procede is to run XLATE2 and then try to assemble. Take note of the assembly errors (if any) and correct them with your te; ; Program: XLATE2 ; Author: Richard Conn ; Derivation: Disassembled XLATE.COM of Cromemco's CDOS and Modified ; into XLATE2; XLATE.COM was Version 2.40 ; Version: 1.2 ; Date: 29 December 83 Patched by Dana Cotant ; Previous Versions: 1.0 (3 May 82) ; 1.1 (21 July 82) ; ; XLATE2 inputs an Intel-Standard 8080 Assembly Language Source File ; and converts it into a Zilog-Standard Z80 Assembly Language Source File. ; VERS EQU 12 ;VERSION NUMBER ; ; USE ZILOG MNEMONICS AN DEFM 'this is ascii' DEFB 0DH DEFB 0AH Also don't forget that DEFM assignments must be limited to less than 32 characters!  Z,DOOCS4 ;CONVERT INTO STANDARD RET FORMS IF MATCH ; LD HL,RETS ;PROCESS (NORMAL RET) OP CODE SET 5 LD BC,5 ;5 CHARS/SINGLE ENTRY CALL CMPOP ;SCAN FOR MATCH JP Z,DORETS ;PROCESS ; LD HL,CALLS ;PROCESS (CALL) OP CODE SET 6 LD BC,5 ;5 CHARS/SINGLE ENTRY CALL CMPOP ;SCAN FOR MATCH JP Z,DOCALLS ;PROCESS ; LD HL,JMPS ;PROCESS (JMP) OP CODE SET 7 LD BC,5 ;5 CHARS/SINGLE ENTRY CALL CMPOP ;SCAN FOR MATCH JP Z,DOJMPS ;PROCESS ; LD HL,OCS8 ;PROCESS OP CODE SET 8 LD BC,12 ;12 CHARS/DUAxt editor. XLATE2 has a built in HELP file which is displayed by entering: XLATE2 / _______________________________________________________________________ ** Using XLATE2 to Create a Source File for the CROWECPM Assembler ** _______________________________________________________________________ The output file must be modified to work with the CROWECPM assembler. 1. Rename the file so it will have the extent .Z80 2. Edit the file to remove the 2 lines which contain the M80 direD ABSOLUTE SEGMENTS ; .Z80 ASEG ; ; CP/M CONSTANTS ; WBOOT EQU 0 BDOS EQU 5 DEFFCB EQU 5CH FCB2 EQU 6CH ; ; START OF PROGRAM ; ORG 100H CALL HCHECK ;CHECK FOR HELP REQUEST LD SP,OBUFLPOS ;INIT STACK PTR CALL INIT ;INIT THE PROGRAM LOOP: CALL BUILDLINE ;BUILD THE NEXT INPUT LINE CALL PROCESSOPS ;CONVERT THE OP CODES JR LOOP ; ; MAIN PROCESSING MODULE ; PROCESSOPS: CALL GETOP ;EXTRACT THE NEXT OP CODE JP Z,FLUSHLINE ;IF NONE, FLUSH ; LD HL,OCS1 ;PROCESS OP  L ENTRY CALL CMPOP ;SCAN FOR MATCH JP Z,DOOCS8 ;PROCESS ; ; NO MATCH IN OP CODE SETS -- PASS TARGET OP CODE AS IS ; LD B,5 ;5 CHARS IN TARGET LD HL,TARGOP ;POINT TO TARGET POPS1: LD A,(HL) ;GET CHAR CP ' ' ;END OF OP? JR Z,POPS2 ;OUTPUT TAB CHAR IF SO CP 9 ;END OF OP? JR Z,POPS2 ;OUTPUT TAB CHAR IF SO CALL DOUTCHAR ;OUTPUT OP CHAR INC HL ;PT TO NEXT DJNZ POPS1 ;CONTINUE FOR 5 CHARS MAX POPS2: LD A,9 ;END OP WITH CALL DOUTCHAR ;OUTPUT TO DISK ; ; COPY REST OF INPUT L DOUTCHAR ;OUTPUT CHAR IN A TO DISK INC HL ;PT TO NEXT CHAR JR OUTWHITE ;CONTINUE ; ; EXTRACT OP CODE FOR INPUT LINE AND PLACE IN BUFFER ; GETOP: LD HL,INLN ;PT TO INPUT LINE LD A,(HL) ;GET 1ST CHAR IN LINE CP ' ' ;NO LABEL? JR Z,GOP3 ;SKIP TO OP CODE CP 9 ;NO LABEL? JR Z,GOP3 ;SKIP TO OP CODE CP ';' ;COMMENT? RET Z ;DONE IF SO ; ; LINE BEGINS WITH A LABEL -- PROCESS IT ; GOP1: LD C,0 ;SET LABEL CHAR CNT GOP2: LD A,(HL) ;GET NEXT CHAR OF LABEL CP ':' ;END OF LABEL? JR CP B JR Z,FLUSHLINE JR C,CARGS7 LD A,' ' JR CARGS8 CARGS7: LD A,9 CARGS8: CALL DOUTCHAR JR CARGS6 ; ; WRITE REST OF INLN TO DISK ; FLUSHLINE: CALL OUTSTR LD A,1 ;RESET POSITION COUNTER LD (OBUFLPOS),A RET ; ; PRINT PDOT FOR EVERY TEN LINES ; PDOT: LD A,(LCOUNT) ;GET LINE COUNT DEC A ;COUNT DOWN LD (LCOUNT),A ;PUT LINE COUNT RET NZ ;DONE IF NOT ZERO LD A,'.' ;PRINT PDOT CALL PCHAR LD A,10 ;RESET COUNT LD (LCOUNT),A LD A,(NLCOUNT) ;NEW LINE? DEC A LD (on a long label that JR Z,NOCOLO ; precedes an equate ; These things made M80 throw up LD A,0 ; Not an equate so store a 0 LD (EQUFLG),A ; in EQUFLG LD A,':' ;OUTPUT THE ':' ; Original Code CALL DOUTCHAR ; Original Code NOCOLO: LD A,0FFH ; Remember that this is an equate LD (EQUFLG),A ; End of Patch ** DmC 12/29/83 ** ; ; SEE IF LABEL IS LESS THAN 7 CHARS LONG ; IF <7, THEN TERMINATE WITH ; IF >6, THEN NEW LINE AND ; GOP6: LD A,C ;GET LABEL CHAR CNT CP 7LINE AS-IS ; COPYARGS: LD HL,(INLNPTR) ;PT TO NEXT CHAR CARGS1: LD C,0 CARGS2: LD A,(HL) ;GET CHAR CP ' ' ;END OF OPERANDS? JR Z,CARGS4 ;SKIP WHITE SPACE AND OUTPUT REST IF SO CP 9 ;END OF OPERANDS? JR Z,CARGS4 ;SKIP WHITE SPACE AND OUTPUT REST IF SO CP 0DH ;END OF LINE? JR Z,FLUSHLINE ;FLUSH IF SO CP ';' ;BEGINNING OF COMMENT = END OF OPERANDS? JR Z,CARGS5 ;COPY REST IF SO CP '''' ;SINGLE QUOTE? JR NZ,CARGS3 DEC C JR Z,CARGS3 LD C,1 CARGS3: CALL DOUTCHAR ;OUTPUT CHAR  Z,GOP4 CP 9 ;END OF LABEL? JR Z,GOP5 CP 0DH ;END OF LABEL AND NO FURTHER PROCESSING? JR Z,GOP5 CP ';' ;END OF LABEL AND NO FURTHER PROCESSING? JR Z,GOP5 CP ' ' ;END OF LABEL? JR Z,GOP5 CALL DOUTCHAR ;OUTPUT LABEL CHAR TO DISK INC HL ;PT TO NEXT CHAR INC C ;INCR LABEL CHAR CNT JR GOP2 ; ; NO LABEL -- SKIP TO OP CODE ; GOP3: CALL SKIPWHITE ;SKIP OVER WHITE SPACE PUSH HL CALL FTODLM CP ':' POP HL JR Z,GOP1 JR GOP7 ; ; END OF LABEL BY ':' CHAR ; GOP4: INC HL ;SNLCOUNT),A RET NZ LD DE,CRLFSTR ;PRINT NEW LINE CALL PMSG LD A,60 ;RESET COUNTER LD (NLCOUNT),A RET ; ; OUTPUT STRING PTED TO BY HL TO DISK (STRING ENDS IN 0) ; OUTSTR: LD A,(HL) ;GET CHAR AND A ;DONE? RET Z ;RET IF SO CALL DOUTCHAR INC HL ;PT TO NEXT CHAR JR OUTSTR ; ; OUTPUT ALL AND CHARS FOUND UNTIL A NON- AND NON- ; ENCOUNTERED ; OUTWHITE: LD A,(HL) ;GET CHAR CP ' ' ;? JR Z,OW1 ;OUTPUT IT CP 9 ;? RET NZ ;DONE IF NOT OW1: CAL ;LESS THAN 7? JR C,GOP7 ;JUST TAB IF LESS THAN 7 LD A,(EQUFLG) ;DmC check for equate (no newline if so) CP 0FFH ; is FF is this is equate JR Z,GOP7 ; if equate just do TAB 12/29/83 LD A,0DH ; CALL DOUTCHAR LD A,0AH ; CALL DOUTCHAR ; ; OUTPUT AFTER LABEL TO DISK ; GOP7: LD A,9 ; CALL DOUTCHAR ; ; SKIP TO OP CODE FIELD AND EXTRACT IT IF PRESENT ; GOP8: CALL SKIPWHITE ;SKIP TO OP CODE FIELD LD A,(HL) ;GET FIRST NON-WHITE CHAR CP ';' ;NO OP CODE IF COMIN A TO DISK INC HL ;PT TO NEXT JR CARGS2 CARGS4: PUSH HL CALL SKIPWHITE ;SKIP TO NEXT NON-WHITE CHAR POP HL CP 0DH ;END OF LINE? JR Z,FLUSHLINE ;FLUSH IF SO CP ';' ;COMMENT? JR Z,CARGS5 ;PROCESS COMMENT IF SO CALL OUTWHITE ;OUTPUT A TAB JR CARGS2 ;RESTART PROCESSING CARGS5: DEC C INC C JR NZ,CARGS3 CALL SKIPWHITE LD B,41 CARGS6: LD A,(OBUFLPOS) ;CHECK POSITION IN OUTPUT LINE CP B JR NC,FLUSHLINE DEC A ;BACK UP IN OUTPUT LINE AND 0F8H ;ARTIFICALLY TAB ADD A,9 KIP ':' CALL DOUTCHAR ;OUTPUT THE ':' LD A,(HL) ;CHECK FOR EOL CP 0DH ;DON'T DOUBLE NEW LINE (SKIP NEW LINE AFTER GOP6) JR Z,GOP8 ;JUST CONTINUE PROCESSING WITH NO TAB JR GOP6 ;NOT NEW LINE, SO PROCESS FOR NEW LINE IF LONG LABEL ; ; OUTPUT ':' AT END OF LABEL ; GOP5: ; Patched by Dana Cotant of CALL SKIPWHITE ; Micro Cornucopia to supress LD A,(HL) ; output of a colon if the label CP 'E' ; precedes an equate JR Z,NOCOLO ; Also fix so a newline is not CP 'e' ; generated !  MENT RET Z ;DONE IF COMMENT CP 0DH ;NO OP CODE IF EOL RET Z ;DONE IF EOL LD (ILTOP),HL ;SAVE PTR TO TARGET OP CODE LD B,5 ;5 CHARS MAX IN OP CODE LD DE,TARGOP ;COPY TO TARGOP BUFFER CALL COPYTODELIM ;COPY UNTIL DELIMITER ENCOUNTERED CALL SKIPWHITE ;SKIP OVER WHITE SPACE WHICH FOLLOWS LD (INLNPTR),HL ;SAVE PTR SUB A INC A ;A=1 AND NZ RET ; ; COMPARE OP CODE PTED TO BY HL WITH TARGET OP CODE; RET WITH Z SET IF ; MATCH, NZ IF NO MATCH ; CMPOP: LD A,(HL) ;NO OP CODE TO COMPARE CP 'P' ;FOR PSW? JR NZ,L0309 ;OUTPUT WHATEVER'S THERE IF NOT INC HL ;MAKE SURE IT IS 'PSW' LD A,(HL) CP 'S' JR NZ,L0309 ;OUTPUT WHAT'S THERE IF NOT INC HL LD A,(HL) CP 'W' JR NZ,L0309 ;OUTPUT WHAT'S THERE IF NOT POP HL ;IT IS 'PSW', SO CLEAR STACK AND PT INC HL ; ... TO CHAR AFTER 'PSW' INC HL PUSH HL LD HL,AFSTR ;PRINT 'AF' JR PRREGPAIR ;DO PRINT PRBC: LD HL,BCSTR ;PRINT 'BC' JR PRREGPAIR PRDE: LD HL,DESTR ;PRINT 'DE' JR PRREGPAIR PRHL: LD HL,HLSTR ;PRINT 'HL' ;OUTPUT TO DISK ; ; PROCESS OP CODES IN SET 2 - OPERAND IS 1 REG OR '(HL)' ; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK ; DOOCS2: CALL OUTNEWOP5CH ;OUTPUT NEW 5-CHAR-MAX OP CODE LD HL,(INLNPTR) ;PT TO OPERAND FIELD ATHLCHECK: LD A,(HL) ;CHECK FOR '(HL)' REFERENCE CP 'M' ;TAKES THE FORM OF 'M' IN 8080 MNEMONICS JP NZ,CARGS1 ;OUTPUT NORMALLY IF NOT INC HL ;PT TO CHAR AFTER PUSH HL ;SAVE PTR LD HL,ATHL ;OUTPUT '(HL)' CALL OUTSTR ;OUTPUT TO DISK POP HLDB 'NC' ; ; PROCESS OP CODE SET 5 -- RETURN FORMS ; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK ; DORETS: LD HL,RETSTR ;PT TO STR TO COPY CALL COPY5 ;COPY WITH OPTIONAL COND JP COPYARGS ;COPY REST OF OPERAND FIELD AND COMMENTS AS-IS RETSTR: DB 'RET ',0 DOCALLS: LD HL,CALLSTR JR CP5WITHCOMMA ;COPY AND FOLLOW WITH COMMA CALLSTR: DB 'CALL ',0 DOJMPS: LD HL,JPSTR ;FALL THRU TO DO JP FORMS ; ; COPY STRING AT HL FOLLOWED BY CONDITION CODE, A COMMA, AND ? AND A ;A=0 IF SO JR Z,CMPOP1 ;FAILURE IF SO PUSH BC LD B,5 ;COMPARE 5 BYTES LD DE,TARGOP ;PT TO TARGET OP CODE CALL COMPHLDE ;COMPARE POP BC RET Z ;DONE IF MATCH ADD HL,BC ;PT TO NEXT OP CODE IN TABLE JR CMPOP CMPOP1: INC A ;A=1 AND NZ RET ; ; PROCESS OP CODES IN SET 1 -- OPERAND AND COMMENTS FIELDS ARE UNCHANGED ; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK ; DOOCS1: CALL OUTNEWOP5CH ;OUTPUT NEW OP CODE JP COPYARGS ;COPY OPERAND AND COMMEN PRREGPAIR: CALL OUTSTR ;PRINT STRING PTED TO BY HL AND MAKE HL ON STACK POP HL ; ... PT TO NEXT CHAR INC HL PUSH HL L0309: POP HL ;PRINT WHATEVER OTHER OPERAND IT IS JP CARGS1 ;PRINT THE OPERAND AFSTR: DB 'AF',0 BCSTR: DB 'BC',0 DESTR: DB 'DE',0 HLSTR: DB 'HL',0 ; ; PROCESS OP CODE SET 4 - EQ, NE, LT, GE RETS, CALLS, AND JMPS ; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK ; DOOCS4: LD A,(TARGOP+1) ;LOOK AT 2ND LETTER OF TARGET OP LD HL,ZFLG  ;GET PTR JP CARGS1 ;PROCESS REST OF LINE NORMALLY ATHL: DB '(HL)',0 ; ; PROCESS OP CODES IN SET 3 - OPERAND IS BC, DE, HL, OR PSW REG PAIR ; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK ; DOOCS3: CALL OUTNEWOP5CH ;OUTPUT NEW OP CODE RPCHECK: LD HL,(INLNPTR) ;PT TO OPERAND FIELD PUSH HL ;SAVE PTR LD A,(HL) ;GET OPERAND CP 'B' ;FOR BC? JR Z,PRBC ;OUTPUT BC IF SO CP 'D' ;FOR DE? JR Z,PRDE ;OUTPUT DE IF SO CP 'H' ;FOR HL? JR Z,PRHL ;OUTPUT HL IF SO REST OF ; OPERAND FIELD ; CP5WITHCOMMA: CALL COPY5 LD A,',' CALL DOUTCHAR ;OUTPUT COMMA TO DISK JP COPYARGS ;COPY REST OF OPERAND FIELD JPSTR: DB 'JP ',0 ; ; COPY 5-CHAR-MAX STRING PTED TO BY HL FOLLOWED BY AND 2-CHAR COND ; COPY5: CALL ONO5C0 ;COPY 5-CHAR-MAX STRING PTED TO BY HL LD A,(TARGOP+1) ;OUTPUT FIRST CHAR OF COND CALL DOUTCHAR LD A,(TARGOP+2) ;OUTPUT 2ND CHAR OF COND IF NOT CP ' ' RET Z JP DOUTCHAR ; ; PROCESS OP CODE SET 8 - THIS TABLE CONTAINS T FIELDS AS-IS ; ; OUTPUT 2ND 5-CHAR-MAX OP CODE FIELD PTED TO BY HL TO DISK AND END IN ; OUTNEWOP5CH: LD BC,5 ;SKIP FIRST 5 CHARS ADD HL,BC ;PT TO 2ND 5-CHAR FIELD ; ; ENTRY PT TO COPY 5-CHAR-MAX FIELD PTED TO BY HL ; ONO5C0: LD B,5 ONO5C1: LD A,(HL) ;GET NEXT CHAR CP ' ' ;? JR Z,ONO5C2 ;DONE IF SO CP 9 ;? JR Z,ONO5C2 ;DONE IF SO CALL DOUTCHAR ;OUTPUT CHAR TO DISK INC HL ;PT TO NEXT DJNZ ONO5C1 ;COUNT DOWN ONO5C2: LD A,9 ;OUTPUT TO DISK JP DOUTCHAR;PREP FOR ZERO CP 'E' ;IF 'E', THEN FORM IS 'EQ' JR Z,ZCPUT ;CHANGE FORM TO 'XZ ', WHERE X=R,C,J LD HL,NZFLG ;PREP FOR NOT ZERO CP 'N' ;IF 'N', THEN FORM IS 'NE' JR Z,ZCPUT LD HL,CFLG ;PREP FOR CARRY CP 'L' ;IF 'L', THEN FORM IS 'LT' JR Z,ZCPUT LD HL,NCFLG ;FORM MUST BE 'GE', SO NO CARRY ZCPUT: LD A,(HL) ;GET FIRST CHAR LD (TARGOP+1),A ;STORE IT INC HL ;PT TO 2ND CHAR LD A,(HL) ;GET IT LD (TARGOP+2),A ;STORE IT RET ZFLG: DB 'Z ' NZFLG: DB 'NZ' CFLG: DB 'C ' NCFLG: "  THE SERVICE ROUTINE ADR ; EMBEDDED IN IT AFTER EACH OP CODE PAIR; ; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK ; DOOCS8: PUSH HL ;SAVE PTR TO OLD (1ST) OP LD BC,10 ;PT TO ADR OF SERVICE ROUTINE ADD HL,BC LD C,(HL) ;BC=ROUTINE ADDRESS INC HL LD B,(HL) POP HL ;PT TO OLD (1ST) OP PUSH BC ;ROUTINE ADDRESS ON STACK RET ;JMP TO ROUTINE ; ; THIS CONVERTS 'DAD ' TO 'ADD HL,' ; DO81: CALL OUTNEWOP5CH ;OUTPUT 'ADD' LD HL,DO81S ;OUTPUT 'HLDO8F1 DO89S: DB '8*',0 ;MULTIPLY RESTART NUMBER BY 8 FOR Z80 ; ; THIS CONVERTS 'SHLD ' TO 'LD (),HL' ; DO8A: CALL OUTNEWOP5CH LD A,'(' ;OUTPUT OPENING '(' CALL DOUTCHAR CALL OUTOPER ;OUTPUT OPERAND PUSH HL LD HL,DO8AS ;OUTPUT '),HL' JR DO8C2 DO8AS: DB '),HL',0 ; ; THIS CONVERTS 'SPHL' TO 'LD SP,HL' ; DO8B: CALL OUTNEWOP5CH LD HL,DO8BS JR DO8F1 DO8BS: DB 'SP,HL',0 ; ; THIS CONVERTS 'STA ' TO 'LD (),A' ; AND 'OUT ' TO 'OUT (),A' ; D, OUTPUTS THE REST OF THE OPERAND ; FIELD, OUTPUTS A CLOSING ')', AND OUTPUTS THE REST OF THE INPUT LINE ; OUTCLP: CALL OUTSTR ;01F9H CALL OUTOPER ;04D5H LD A,')' ;29H CALL DOUTCHAR ;0631H JP CARGS1 ;0198H DO85S: DB 'HL,(',0 ; ; THIS CONVERTS 'MOV R,R' TO 'LD R,R' ; DO86: CALL OUTNEWOP5CH LD HL,(INLNPTR) ;PT TO 1ST CHAR OF OPERAND FIELD LD A,(HL) ;GET IT CP 'M' ;CONVERT 'M' TO '(HL)'? JR NZ,DO862 ;NO CONVERSION NECESSARY PUSH HL LD HL,ATHL ;OUTPUT '(HL)' CALL OUTSTR O8F1: CALL OUTSTR ;01F9H JP COPYARGS ;0195H DO8FS: DB '(SP),HL',0 ; ; OUTPUT REST OF OPERAND FIELD UP TO WHITE SPACE BEFORE ENDING COMMENT ; OR END OF LINE ; OUTOPER: LD HL,(INLNPTR) ;PT TO NEXT CHAR IN INPUT LINE BUFFER OOL1: LD A,(HL) ;GET NEXT CHAR CP ';' ;BEGINNING OF COMMENT? JR Z,OOL2 ;CHECK FOR REST OF OPERAND CP 0DH ;END OF LINE? JR Z,OOL2 ;CHECK FOR REST OF OPERAND INC HL ;CONTINUE UNTIL EITHER COMMENT OR EOL FOUND JR OOL1 OOL2: DEC HL ;BACK UP (OVER WHITE SPACE?,' CALL OUTSTR JP RPCHECK ;OUTPUT DO81S: DB 'HL,',0 ; ; THIS CONVERTS 'ADD R' TO 'ADD A,R' ; AND 'ADC R' TO 'ADC A,R' ; AND 'SBC R' TO 'SBC A,R' ; DO82: CALL OUTNEWOP5CH ;OUTPUT THE 'IN' LD HL,DO82S ;OUTPUT 'A,' JP DO8F1 ;04C7H DO82S: DB 'A,',0 ; ; THIS CONVERTS 'LDA ' TO 'LD A,()' ; AND 'IN ' TO 'IN A,()' ; DO83: CALL OUTNEWOP5CH LD HL,DO83S JR OUTCLP DO83S: DB 'A,(',0 ; ; THIS CONVERTS 'LDAX ' TO 'LD A,()' ; DOO8C: CALL OUTNEWOP5CH LD A,'(' ;OUTPUT '(' ; ; THIS OUTPUTS '),A' ; DO8C1: CALL DOUTCHAR ;OUTPUT CHAR IN A CALL OUTOPER ;OUTPUT OPERAND FIELD PUSH HL LD HL,DO8CS ;OUTPUT '),A' DO8C2: CALL OUTSTR ;OUTPUT STRING PTED TO BY HL POP HL ;CLEAR STACK JP CARGS1 ;OUTPUT REST OF INPUT LINE DO8CS: DB '),A',0 ; ; THIS CONVERTS 'STAX ' TO 'LD (),A' ; DO8D: CALL OUTNEWOP5CH LD HL,(INLNPTR) ;PT TO 1ST CHAR OF OPERAND LD A,(HL) ;GET IT CP 'B' ;BC REG PAIR? JR Z,DO8 POP HL ; ; OUTPUT ',' FOLLOWED BY '(HL)' OR 'R' ; DO861: INC HL ;OUTPUT COMMA AND THEN 2ND R LD A,(HL) ;GET COMMA CALL DOUTCHAR INC HL ;PT TO 2ND R JP ATHLCHECK ;OUTPUT '(HL)' OR R ; ; OUTPUT 'R,' FOLLOWED BY '(HL)' OR 'R' ; DO862: CALL DOUTCHAR ;OUTPUT 'R' JR DO861 ;OUTPUT REST ; ; THIS CONVERTS 'PCHL' TO 'JP(HL)' ; DO88: CALL OUTNEWOP5CH LD HL,ATHL ;OUTPUT THE '(HL)' JP DO8F1 ; ; THIS CONVERTS 'RST N' TO 'RST NNH' ; DO89: CALL OUTNEWOP5CH LD HL,DO89S JP ) LD A,(HL) ;GET CHAR CP ' ' ;WHITE? JR Z,OOL2 ;CONTINUE BACKING CP 9 ;WHITE? JR Z,OOL2 ;CONTINUE BACKING INC HL ;PT TO FIRST WHITE CHAR EX DE,HL ;SAVE PTR IN DE LD HL,(INLNPTR) ;PT TO START OF SCAN OOL3: LD A,D ;ALL OF OPERAND FIELD FLUSHED? CP H ;CHECK FOR PTR MATCH JR NZ,OOL4 ;NO MATCH, SO FLUSH NEXT CHAR LD A,E ;REST OF MATCH? CP L RET Z ;DONE IF ALL MATCH OOL4: LD A,(HL) ;OUTPUT OPERAND CHAR TO DISK CALL DOUTCHAR INC HL ;PT TO NEXT OPERAND CHAR JR OOL3 ;CONTINUE UN84: CALL OUTNEWOP5CH ;OUTPUT OP CODE LD HL,(INLNPTR) ;PT TO OPERAND LD A,(HL) ;GET 1ST CHAR OF OPERAND CP 'B' ;BC REG PAIR? JR Z,DO841 ;PROCESS IT CP 'D' ;DE REG PAIR? JR Z,DO842 ;PROCESS IT JP CARGS1 ;SOMETHING FUNNY -- PROCESS NORMALLY DO841: LD HL,DO841S JP DO8D3 DO842: LD HL,DO842S JP DO8D3 DO841S: DB 'A,(BC)',0 DO842S: DB 'A,(DE)',0 ; ; THIS CONVERTS 'LHLD ' TO 'LD HL,()' ; DO85: CALL OUTNEWOP5CH LD HL,DO85S ; ; THIS OUTPUTS THE STRING PTED TO BY HLD1 ;OUTPUT IT IF SO CP 'D' ;DE REG PAIR? JR Z,DO8D2 ;OUTPUT IT IF SO JP CARGS1 ;ELSE, OUTPUT WHAT'S THERE DO8D1: LD HL,DO8D1S JR DO8D3 DO8D2: LD HL,DO8D2S DO8D3: CALL OUTSTR LD HL,(INLNPTR) ;PT TO AFTER 'B' OR 'D' INC HL JP CARGS1 DO8D1S: DB '(BC),A',0 DO8D2S: DB '(DE),A',0 ; ; THIS CONVERTS 'XCHG' TO 'EX DE,HL' ; DO8E: CALL OUTNEWOP5CH LD HL,DO8ES JR DO8F1 DO8ES: DB 'DE,HL',0 ; ; THIS CONVERTS 'XTHL' TO 'EX (SP),HL' ; DO8F: CALL OUTNEWOP5CH LD HL,DO8FS D#  TIL OPERAND ALL OUT ; ; THE FOLLOWING TURNS ON VARIOUS MESSAGES FOR MANUAL TRANSLATION ; DO91: LD A,9 ;ENDIFS LD (XLT1ON),A ;STORE TO ENABLE JR DO941 DO92: LD A,9 ;INCLUDES LD (XLT2ON),A JR DO941 DO93: LD A,9 ;LISTS LD (XLT3ON),A JR DO941 DO94: LD A,9 ;MACROS LD (XLT4ON),A DO941: CALL OUTNEWOP5CH ;OUTPUT NEW CODE LD A,0DH ;TURN ON PRINTED ERR MESSAGE LD (ERR5ON),A ;TURN ON FLAG BY STARTING WITH JP COPYARGS ;COPY REST OF CODE ; ; THE FOLLOWING CHECKS FOR T PART 1 OF FILE NAME MESSAGE CALL PMSG LD HL,FCBASM ;PRINT NAME OF SOURCE FILE CALL PRFNAME LD DE,PRFNM2 ;PRINT PART 2 OF FILE NAME MESSAGE CALL PMSG LD HL,FCBZ80 ;PRINT NAME OF DESTINATION FILE CALL PRFNAME LD DE,CRLFSTR ;END LINE CALL PMSG RET ; ; PRINT FILE NAME MESSAGE ; PRFNAME: LD A,(HL) ;GET DISK NUMBER ADD A,'@' ;ADD IN ASCII BIAS CALL PCHAR LD A,':' ;PRINT COLON CALL PCHAR INC HL ;PT TO FIRST CHAR OF FILE NAME LD B,8 ;8 CHARS CALL PRFNC LD A,'.' ;DOT) ;2ND FILE NAME PRESENT? CP ' ' ; IF NOT RET NZ ;DONE IF SO XOR A ;A=0 LD (OCS4),A ;TURN OFF WEIRD OP CODE SCAN (REQ, ETC) LD (NOXLT),A ;TURN OFF SCAN FOR ENT, NAME, RAM, ROG LD (NOXLT2),A ;TURN OFF SCAN FOR IFC, ICL, MAC, LST RET ; ; SET UP FILE NAMES ; MAKEFNS: LD HL,DEFFCB ;COPY INPUT FILE NAME FROM COMMAND LD DE,FCBASM ;INTO THIS FCB FOR USE LD BC,9 ;9 BYTES LDIR ;COPY LD A,(HL) ;FILE TYPE SPECIFIED? CP ' ' ;NONE IF JR Z,MFN1 LD BC,3 ;3 MORE BYTES OR OOERR2: LD DE,ERR4 ;ATTEMPT TO OVERWRITE EXISTING FILE CALL PMSG LD C,1 ;GET RESPONSE CALL BDOS CALL CAPS ;CAPITALIZE CP 'Y' ;CONTINUE IF YES LD DE,ERR4A ;PREP FOR ABORT JP NZ,ENDERR ;ABORT ERROR LD DE,CRLFSTR ;NEW LINE CALL PMSG LD DE,FCBZ80 ;DELETE OLD FILE LD C,19 ;BDOS DELETE FILE CALL BDOS JR OPENO1 ;CREATE NEW FILE AND CONTINUE ; ; CHECK TO SEE IF CHAR PTED TO BY HL IS A DELIMITER AND FLUSH CHARS UNTIL ; IT IS; RET WITH ZERO FLAG SET WHEN DONE ; FTODLM: ;FHE SPECIFICATION OF A HELP OPTION AND ; PRINTS THE HELP MESSAGE IF SO ; HCHECK: LD A,(DEFFCB+1) ;GET FIRST CHAR OF FILE NAME CP '/' ;OPTION? RET NZ ;NO HELP REQUESTED IF NOT OPTION LD DE,HEADER ;PRINT PROGRAM BANNER CALL PMSG LD DE,HMSG1 ;PRINT HELP MESSAGE CALL PMSG LD C,1 ;GET ANY CHAR CALL BDOS LD DE,HMSG2 ;PRINT REST OF HELP MESSAGE CALL PMSG POP DE ;CLEAR STACK RET ;RETURN TO CP/M ; ; THE FOLLOWING INITIALIZES THE PROGRAM FOR EXECUTION ; INIT: LD DE,HEADER ; CALL PCHAR LD B,3 ;3 CHARS CALL PRFNC RET PRFNC: LD A,(HL) ;GET NEXT CHAR INC HL ;PT TO NEXT CALL PCHAR ;PRINT CHAR DJNZ PRFNC RET ; ; OPEN INPUT FILE FOR PROCESSING ; OPENIN: LD DE,FCBASM ;OPEN FILE FOR INPUT LD C,0FH CALL BDOS CP 0FFH ;ERROR? JR Z,OIERR ;ABORT WITH ERROR MESSAGE IF SO LD A,80H ;INIT CHAR COUNT FOR BUFFER LD (IBUFCNT),A RET OIERR: LD DE,ERR2 ;INPUT FILE ERROR MESSAGE JP ENDERR ;ABORT ; ; OPEN FILE FOR OUTPUT ; OPENOUT: LD DE,FLDIR MFN1: LD HL,FCB2+1 ;2ND FILE SPECIFIED? LD A,(HL) ;GET FIRST BYTE OF FILE NAME DEC HL ;PT TO FIRST BYTE OF FCB CP ' ' ;NO 2ND FILE NAME? JR NZ,MFN2 ;SKIP RELOAD OF HL IF THERE IS A 2ND FILE NAME LD HL,DEFFCB ;COPY FILE NAME INTO OUTPUT FCB MFN2: LD DE,FCBZ80 ;OUTPUT FCB LD BC,9 ;9 BYTES LDIR ;COPY LD HL,FCB2+9 ;PT TO FILE TYPE LD A,(HL) ;CHECK FOR A FILE TYPE CP ' ' ;NONE IF JR Z,MFN3 LD BC,3 ;THERE IS ONE, SO COPY IT OVER LDIR MFN3: LD DE,PRFNM1 ;PRINTlush TO DeLiMiter PUSH BC CALL DLIMSCAN ;DO SCAN POP BC RET Z ;MATCH, SO ABORT INC HL ;PT TO NEXT CHAR JR FTODLM ;CONTINUE SCAN ; ; COPY (HL) TO (DE) FOR B BYTES OR UNTIL A DELIMITER IS ENCOUNTERED ; COPYTODELIM: LD C,B ;LET BC=OLD B (FOR LDI INSTR) LD B,0 PUSH BC ;SAVE REGS PUSH DE PUSH HL CALL SPFILL ;FILL DESTINATION BUFFER WITH SPACES (PTED TO BY DE) POP HL ; ... AND C BYTES LONG POP DE POP BC CTD1: PUSH BC ;SAVE COUNT CALL DLIMSCAN ;SCAN FOR DELIMITER IF ENCOUPRINT PROGRAM BANNER CALL PMSG LD A,10 ;INIT PDOT PRINT (LINE) COUNT LD (LCOUNT),A LD A,60 ;INIT NEW LINE PRINT COUNT LD (NLCOUNT),A LD A,1 ;INITIALIZE OUTPUT BUFFER LINE POSITION LD (OBUFLPOS),A CALL MAKEFNS ;SET UP FILE NAMES CALL OPENIN ;OPEN INPUT FILE CALL OPENOUT ;OPEN OUTPUT FILE LD HL,FHDR ;OUTPUT '.Z80' AND 'ASEG' TO MAC FILE INIT1: LD A,(HL) ;GET CHAR OR A ;DONE? JR Z,INIT2 CALL DOUTCHAR ;OUTPUT TO DISK INC HL ;PT TO NEXT JR INIT1 INIT2: LD A,(FCB2+1CBZ80 ;OPEN OUTPUT FILE LD C,0FH CALL BDOS CP 0FFH ;ERROR? JR NZ,OOERR2 ;ABORT IF NO ERROR (OVERWRITE OLD FILE) OPENO1: LD DE,FCBZ80 ;ELSE CREATE OUTPUT FILE LD C,16H CALL BDOS CP 0FFH ;ERROR? JR Z,OOERR1 LD DE,FCBZ80 ;NOW OPEN OUTPUT FILE (REDUNDANT WITH MAKE) LD C,0FH CALL BDOS LD A,80H ;INIT COUNT OF BYTES REMAINING LD (OBUFBACKCNT),A ;SET COUNT LD HL,OBUF ;INIT ADDRESS OF NEXT BYTE LD (OBUFPTR),HL ;SET PTR RET OOERR1: LD DE,ERR3 ;DISK FULL JP ENDERR ;ABORT ERR$  NTERED POP BC RET Z ;DONE IF SO LDI ;COPY NEXT CHAR INTO DESTINATION BUFFER JP PO,DLIMSCAN ;FINAL DELIMITER SCAN IF DONE JR CTD1 ; ; ADVANCE BUFFER POINTER HL UNTIL NON-WHITE (NON-, NON-) ; ENCOUNTERED ; SKIPWHITE: LD A,(HL) ;GET CHAR CP ' ' ;? JR Z,SKPWH1 ;SKIP IF SO CP 9 ;? RET NZ ;DONE IF NOT SKPWH1: INC HL ;PT TO NEXT CHAR JR SKIPWHITE ; ; CHECK TO SEE IF CHAR PTED TO BY HL IS A DELIMITER ; DLIMSCAN: PUSH DE EX DE,HL ;PT TO CHAR WITH DE LD LL MEMORY PTED TO BY DE WITH SPACES FOR BC BYTES ; SPFILL: LD A,' ' ; LD (DE),A ;STORE FIRST LD H,D ;MAKE HL PT TO 1ST LD L,E INC DE ;DE PTS TO NEXT BYTE DEC BC ;BC IS 1 BYTE LESS LDIR ;COPY USING LDIR RET ; ; OUTPUT CHAR IN A TO DISK FILE ; DOUTCHAR: PUSH HL ;SAVE REGS PUSH DE PUSH BC PUSH AF LD HL,(OBUFPTR) ;GET ADDRESS OF NEXT CHAR POS IN OUT BUFFER LD (HL),A ;STORE CHAR INTO OUT BUFFER CP 9 ;CHECK FOR TAB JR NZ,NOTABOUT ;NOT TAB -- DON'T UPDATE CODS IN A BINARY 0 ; SPCHSCAN: LD B,(HL) ;B=NUMBER OF BYTES TO SCAN INC HL LD C,(HL) ;C=NUMBER OF BYTES TO SKIP ON FAILURE INC HL ;PT TO FIRST VALID BYTE IN TABLE ; ; MAIN SCANNING LOOP ; SPCH1: LD A,(HL) ;CHECK FOR END OF TABLE AND A ;ZERO? JR Z,SPCH2 ;DONE IF SO CALL COMPHLDE ;DO COMPARE RET Z ;RETURN IF MATCH LD A,C ;POINT TO NEXT TABLE ENTRY CALL ADDHLA ;HL=HL+(SIZE OF TABLE ENTRY) JR SPCH1 ; ; NO MATCH -- RETURN NZ ; SPCH2: INC A ;A=1 AND NZ RET ; ; COMPARE CHARPRINT ERROR MESSAGE AND ABORT JP ENDERR ; ; FILL LAST BLOCK WITH ^Z AND CLOSE OUTPUT FILE ; CTRLZFILL: LD A,(OBUFBACKCNT) ;GET REMAINING COUNT CP 80H ;FULL? JR Z,CLOSEOUT ;CLOSE FILE THEN LD A,1AH ;ELSE WRITE ^Z CALL DOUTCHAR JR CTRLZFILL ; ; CLOSE OUTPUT FILE ; CLOSEOUT: LD DE,FCBZ80 ;OUTPUT FCB LD C,10H ;CLOSE FILE JP BDOS ; ; EXTRACT NEXT INPUT LINE FOR DISK FILE AND PLACE IT AS A 0-TERMINATED ; STRING IN BUFFER 'INLN' ; BUILDLINE: CALL PDOT ;PRINT ACTIVITY DOT HL,DLIMS ;PT TO TABLE OF DELIMITERS CALL DELIMCHS ;DO SCAN IN GENERAL EX DE,HL ;PT TO CHAR WITH HL LD A,(HL) ;GET CHAR IN A POP DE RET ; ; TABLE OF VALID DELIMITERS ; DLIMS: DB 1,1 ;SCAN 1 BYTE AT A TIME, AND SKIP 1 BYTE IF NO MATCH DB ',' ;DELIMITERS ... DB ':' DB '+' DB '-' DB '/' DB '*' DB ' ' DB ')' DB ';' DB 0DH DB 9 ; ... TO HERE DB 0 ;END OF TABLE ; ; SCAN FOR DELIMITER -- RETURN WITH NZ IF NOT FOUND OR PT TO DELIMITER ; WITH Z IF FOUND; ON INPUT, TABLEUNT LD A,(OBUFLPOS) ;TAB -- UPDATE LOCATION IN LINE DEC A ;A=OUT BUFFER LINE POSITION - 1 AND 0F8H ;MASK FOR TAB ADD A,9 ;AND ADD 9 JR DOUT1 ; NOT A TAB -- JUST INCR POSITION COUNT NOTABOUT: LD A,(OBUFLPOS) ;GET ADDRESS OF NEXT CHAR POS IN OUT BUFFER INC A ;ADD 1 TO IT DOUT1: LD (OBUFLPOS),A ;UPDATE OUT BUFFER LINE POSITION INC HL ;INCREMENT BUFFER PTR LD A,(OBUFBACKCNT) ;GET BUFFER BYTE COUNT DEC A ;BUFFER NOW FULL? JR NZ,DOUT2 ;CONTINUE IF NOT LD DE,OBUF ;WRITE BUFFER S PTED TO BY DE WITH THAT PTED TO BY HL FOR B BYTES ; RET WITH ZERO FLAG SET IF COMPLETE MATCH, NZ IF NO MATCH; ; HL, DE, BC NOT AFFECTED ; COMPHLDE: PUSH HL ;SAVE REGS PUSH DE PUSH BC CMPHD1: LD A,(DE) ;GET DE CHAR CP (HL) ;COMPARE TO HL CHAR JR NZ,CMPHD2 ;NO MATCH INC HL ;PT TO NEXT INC DE DJNZ CMPHD1 ;COUNT DOWN -- ZERO FLAG SET ON END CMPHD2: POP BC ;RESTORE REGS POP DE POP HL RET ; ; HL=HL+A ; ADDHLA: ADD A,L ;DO IT LD L,A RET NC INC HL RET ; ; FI XOR A ;A=FALSE OR 0 LD (INCMT),A ;TURN IN COMMENT FLAG OFF LD (INQUOTE),A ;TURN IN QUOTE FLAG OFF LD HL,INLN ;PT TO INLN BUFFER LD B,80 ;80 CHARS MAX ; ; MAIN BUILD LOOP ; NXTLCHAR: LD DE,(IBUFPTR) ;PT TO NEXT CHAR IN FILE LD A,(IBUFCNT) ;CHECK TO SEE IF BUFFER EMPTY CP 80H ;80H IF SO JR NZ,PUTCHAR ;NOT EMPTY, SO PLACE CHAR IN LINE EXX ;SAVE REGS LD DE,IBUFFER ;READ NEXT BLOCK FROM INPUT FILE LD C,1AH ;SET DMA ADDRESS CALL BDOS LD DE,FCBASM ;READ THE BLOCK LD C,14H C PTED TO BY HL WITH 1ST 2 BYTES ; GIVING NUMBER OF BYTES TO CHECK AND NUMBER OF BYTES TO SKIP, RESP, ; ON EACH PARTIAL SCAN ; DELIMCHS: CALL SPCHSCAN ;DO SCAN OF TABLE RET NZ ;NOT FOUND LD C,B ;CHAR OFFSET COUNT IN BC LD B,0 ADD HL,BC ;PT TO CHAR SUB A ;SET ZERO FLAG RET ; ; SCAN SPECIAL CHAR TABLE PTED TO BY HL FOR STRING PTED TO BY DE; ; NUMBER OF SIGNIFICANT BYTES TO SCAN AS FIRST ENTRY IN TABLE, ; NUMBER OF BYTES TO SKIP ON FAILURE AS 2ND ENTRY IN TABLE; ; TABLE ENTO DISK IF SO LD C,1AH ;SET DMA ADDRESS CALL BDOS LD DE,FCBZ80 ;WRITE BLOCK CALL WRITEBLK LD HL,OBUF ;RESET OUTPUT BUFFER PTR TO 1ST BYTE LD A,80H ;RESET BUFFER BYTE COUNT DOUT2: LD (OBUFPTR),HL ;UPDATE OUTPUT BUFFER PTR LD (OBUFBACKCNT),A ;UPDATE BUFFER BYTE COUNT POP AF ;RESTORE REGS POP BC POP DE POP HL RET ; ; WRITE BLOCK WHOSE FCB IS PTED TO BY DE TO DISK ; WRITEBLK: LD C,15H ;CP/M BDOS WRITE BLOCK CALL BDOS AND A ;ERROR? RET Z ;OK IF NONE LD DE,ERR1 ;ELSE %  ALL BDOS DEC A ;ERROR? JP Z,ENDALL ;DONE IF SO (ASSUME EOF) EXX ;GET REGS BACK LD DE,IBUFFER ;SET PTR TO 1ST BYTE OF BLOCK SUB A ;CHAR COUNT = 0 ; ; PLACE CHAR PTED TO BE DE INTO INLN ; PUTCHAR: LD (IBUFCNT),A ;SAVE CHAR COUNT LD A,(DE) ;GET CHAR INC DE ;PT TO NEXT LD (IBUFPTR),DE ;SAVE PTR PUSH HL LD HL,IBUFCNT ;INCR CHAR COUNT INC (HL) POP HL CALL PCAPS ;CAPITALIZE CHAR OPTIONALLY LD (HL),A ;SAVE CHAR FROM FILE INTO INLN CP 0DH ;END OF LINE? JR Z,ENDBLINE ;DMSB CP 61H ;DO NOTHING IF LESS THAN SMALL A RET C CP 7AH+1 ;CAP IF BETWEEN SMALL A AND Z, RESP RET NC AND 5FH ;CAPITALIZE RET ; ; END OF PROCESSING ; ENDALL: CALL CTRLZFILL ;FILL BUFFER WITH ^Z LD DE,ERR5ON ;OPTIONALLY PRINT EACH ERROR MESSAGE IF SET CALL PMSG LD DE,XLT1ON CALL PMSG LD DE,XLT2ON CALL PMSG LD DE,XLT3ON CALL PMSG LD DE,XLT4ON CALL PMSG LD DE,MSG2 ; ; PRINT MESSAGE PTED TO BY DE WITH PRECEEDING AND FINISH UP ; ENDERR: PUSH DE ;SAVE PTR JR NZ,PCAPS5 XOR A ;A=0 LD (INQUOTE),A ;YES, SO SET NOT IN QUOTE JR PCAPS5 PCAPS4: POP AF ;GET CHAR PUSH AF ;SAVE CHAR ONE LAST TIME CP '''' ;COMING INTO A QUOTE? JR NZ,PCAPS5 LD A,0FFH ;SET INQUOTE FLAG LD (INQUOTE),A PCAPS5: POP AF ;GET CHAR RET ;DONE ; ; STORE ENDING AND ; ENDBLINE: INC HL ;PT TO NEXT POSITION LD (HL),0AH ;STORE INC HL LD (HL),0 ;STORE LD (IBUFPTR),DE ;SAVE INPUT FILE PTR ; ; IF LINE STARTS WITH AN ASTERISK (COMMENT LIN FOR OCS 1 OCS2: DB 'ANA AND ' DB 'CMP CP ' DB 'DCR DEC ' DB 'INR INC ' DB 'MVI LD ' DB 'ORA OR ' DB 'SUB SUB ' DB 'XRA XOR ' DB 0 ;END OF TABLE FOR OCS 2 OCS3: DB 'DCX DEC ' DB 'INX INC ' DB 'LXI LD ' DB 'POP POP ' DB 'PUSH PUSH ' DB 0 ;END OF TABLE FOR OCS 3 OCS4: DB 'REQ RNE RLT RGE CEQ ' DB ' CNE CLT CGE JEQ JNE ' DB ' JLT JGE ' DB 0 ;END OF TABLE FOR OCS 4 RETS: DB 'RC RNC RZ RNZ RP ' DB ' RM RPE RPO ' DONE IF SO CP 9 ;TAB EXPAND? JR Z,CONTBLINE ;PROCESS AS NORMAL CHAR IF SO CP ' ' ;LESS THAN ? JR C,NXTLCHAR ;DON'T PROCESS IF SO CONTBLINE: DEC B ;IS BUFFER FULL? INC HL ;PT TO NEXT CHAR IN INLN BUFFER JR NZ,NXTLCHAR ;CONTINUE PROCESSING IF NOT FULL INC B ;WRITE OVER LAST CHAR FOR REST OF LINE DEC HL JR NXTLCHAR ;CONTINUE ; ; OPTIONALLY CAPITALIZE CHAR IN A ; PCAPS: PUSH AF ;SAVE CHAR LD A,(INCMT) ;IN A COMMENT? OR A ;0=NO JR NZ,PCAPS5 ;DONE IF SO AND DON'T CAPITALIZE  LD DE,CRLFSTR ;PRINT CALL PMSG POP DE CALL PMSG ;PRINT MESSAGE JP WBOOT ;DONE ; ; PRINT STRING PTED TO BY DE AND ENDING IN 0 ; PMSG: LD A,(DE) ;GET CHAR AND A ;ENDING 0? RET Z ;DONE IF SO CALL PCHAR ;OUTPUT CHAR IN A INC DE ;PT TO NEXT CHAR JR PMSG ;CONTINUE ; ; PRINT CHAR IN A ON CON: ; PCHAR: PUSH AF ;SAVE REGS PUSH BC PUSH DE PUSH HL LD E,A ;CHAR IN E LD C,2 ;CON: OUTPUT CALL BDOS POP HL ;RESTORE REGS POP DE POP BC POP AF RET ; ; **** OPE), MAKE IT START WITH A ; SEMICOLON ; LD A,(INLN) ;LOOK AT FIRST CHAR CP '*' ;ASTERISK? JR NZ,ENDBL1 LD A,';' ;REPLACE WITH SEMICOLON LD (INLN),A ; ; CHECK FOR EMPTY LINE AND JUST OUTPUT NEW LINE IF SO; ELSE RETURN ; ENDBL1: LD A,B ;LINE EMPTY? SUB 80 ;START OVER IF SO RET NZ ;DONE IF NOT EMPTY LD A,0DH ;OUTPUT TO FILE FOR EMPTY LINE CALL DOUTCHAR LD A,0AH CALL DOUTCHAR JP BUILDLINE ;DO NEXT LINE ; ; CAPITALIZE CHAR IN A ; CAPS: AND 7FH ;MASK OUT B 0 ;END OF TABLE FOR RETS CALLS: DB 'CC CNC CZ CNZ CP ' DB ' CM CPE CPO ' DB 0 ;END OF TABLE FOR CALLS JMPS: DB 'JC JNC JZ JNZ JP ' DB ' JM JPE JPO ' DB 0 ;END OF TABLE FOR JMPS OCS8: DB 'DAD ADD ' DW DO81 DB 'ADD ADD ' DW DO82 DB 'ADC ADC ' DW DO82 DB 'SBB SBC ' DW DO82 DB 'ADI ADD ' DW DO82 DB 'ACI ADC ' DW DO82 DB 'SBI SBC ' DW DO82 DB 'IN IN ' DW DO83 DB 'LDA LD ' DW DO83 DB 'LDAX LD ' DW DO84 DB 'L LD A,(INQUOTE) ;IN A QUOTE? OR A ;0=NO JR NZ,PCAPS1 ;DON'T CAPITALIZE IF SO POP AF ;NOT IN COMMENT OR QUOTE, SO CAPITALIZE CALL CAPS JR PCAPS2 PCAPS1: POP AF ;GET CHAR PCAPS2: CP ';' ;COMING INTO A COMMENT? JR NZ,PCAPS3 PUSH AF ;SAVE CHAR LD A,0FFH ;SET INCMT FLAG LD (INCMT),A JR PCAPS5 ;DONE PCAPS3: PUSH AF ;SAVE CHAR LD A,(INQUOTE) ;IN A QUOTE? OR A ;0=NO JR Z,PCAPS4 POP AF ;GET CHAR -- WE ARE IN A QUOTE PUSH AF ;SAVE IT AGAIN CP '''' ;ARE WE LEAVING THE QUOTE?  CODE TABLE, MESSAGE, AND BUFFER AREA **** ; ; ; OP CODE TABLES ; OCS1: DB 'ANI AND ' DB 'CMA CPL ' DB 'CMC CCF ' DB 'CPI CP ' DB 'HLT HALT ' DB 'JMP JP ' DB 'ORI OR ' DB 'RAL RLA ' DB 'RAR RRA ' DB 'RLC RLCA ' DB 'RRC RRCA ' DB 'STC SCF ' DB 'SUI SUB ' DB 'XRI XOR ' POPS: DB 'DB DEFB ' DB 'DS DEFS ' DB 'DW DEFW ' DB 'SET DEFL ' NOXLT: DB 'ENT ENTRY' DB 'NAM NAME ' DB 'RAM DATA ' DB 'ROG REL ' DB 0 ;END OF TABLE&  HLD LD ' DW DO85 DB 'MOV LD ' DW DO86 DB 'PCHL JP ' DW DO88 DB 'RST RST ' DW DO89 DB 'SHLD LD ' DW DO8A DB 'SPHL LD ' DW DO8B DB 'STA LD ' DW DO8C DB 'OUT OUT ' DW DO8C DB 'STAX LD ' DW DO8D DB 'XCHG EX ' DW DO8E DB 'XTHL EX ' DW DO8F NOXLT2: DB 'IFC IF ' DW DO91 DB 'ICL *INCL' DW DO92 DB 'LST LIST ' DW DO93 DB 'MAC MACRO' DW DO94 DB 0 ;END OF TABLE FOR OCS8 AND NOXLT2 ; ; VARIOUS MESSAGES AND PROGRAM HEADER ; H: DB 'XLATE2 Aborting to CP/M',0 MSG2: DB 'XLATE2 Processing Complete',0 CRLFSTR: DB 0DH,0AH,0 ; ; VARIOUS ERROR MESSAGES ; ERR5ON: DB 0 ;THIS BYTE IS SET TO IF STRING ENABLED ERR5: DB 0AH DB 'The following pseudo-ops ' DB 'have been used in your source ' DB 'and have not',0DH,0AH DB 'been ' DB 'fully translated. You must ' DB 'complete the translation ' DB 'using an editor.',0DH,0AH DB 9,'Original:',9,9,'Must Be Translated To:',0DH,0AH DB 0 ;END OF STRING XLT1ON: EMO1 DEMO2 <-- DEMO1.ASM to DEMO2.MAC' DB 0DH,0AH DB ' XLATE2 DEMO1.TXT DEMO2.GGG <-- DEMO1.TXT to DEMO2.GGG' DB 0DH,0AH,0AH DB 'The following functions are also performed by XLATE2:' DB 0DH,0AH,0AH DB ' . The M80 Pseudo-Ops .Z80 and ASEG will be inserted ' DB 'at the front',0DH,0AH DB ' of the MAC File',0DH,0AH DB ' . The text in the Destination File will be ' DB 'capitalized',0DH,0AH DB ' . All comment lines beginning with an asterisk will ' DB 'begin with',0DH,0AH NCMT: DS 1 ; IN QUOTE FLAG -- 0 MEANS NOT INQUOTE: DS 1 ; PTR TO TARGET OP CODE IN INPUT LINE ILTOP: DS 2 ; OP CODE TO MATCH AGAINST TARGOP: DS 5 ; PTR TO CURRENT POSITION IN CURRENT INPUT LINE INLNPTR: DS 2 ; PTR TO CURRENT POSITION IN OUTPUT BUFFER (BLOCK) OBUFPTR: DS 2 ; COUNT OF CHARS REMAINING IN OUTPUT BUFFER OBUFBACKCNT: DS 1 ; OUTPUT BUFFER (BLOCK) OBUF: DS 128 ; CURRENT INPUT LINE BUFFER INLN: DS 80 ;80 CHARS IN LINE DS 3 ;3 EXTRA FOR ; EADER: DB 'XLATE2 -- 8080-to-Z80 Translator, Version ' DB VERS/10+'0','.',(VERS MOD 10)+'0' DB 0DH,0AH,0 ; HELP MESSAGES HMSG1: DB 0DH,0AH,0AH DB ' XLATE2 translates 8080 assembly language source',0DH,0AH DB 'code into Zilog-Standard Z80 assembly language',0DH,0AH DB 'source code. It is invoked by a command of the',0DH,0AH DB 'following form:',0DH,0AH,0AH DB ' XLATE2 d:SRCFILE.typ d:destfile.typ',0DH,0AH,0AH DB ' All characters in lower case are optional, and,',0DH,0AH DB  DB 0 ;THIS BYTE IS SET TO IF STRING ENABLED XLT1: DB '#ENDIF',9,9,9,'ENDIF',0DH,0AH,0 XLT2ON: DB 0 ;THIS BYTE IS SET TO IF STRINGENABLED XLT2: DB 'ICL',9,9,9,'*INCLUDE',0DH,0AH,0 XLT3ON: DB 0 ;THIS BYTE IS SET TO IF STRING ENABLED XLT3: DB 'LST ',9,9,'LIST ' DB 0DH,0AH,0 XLT4ON: DB 0 ;THIS BYTE IS SET TO IF STRING ENABLED XLT4: DB 'MAC <$parameters>',9,'MACRO <#parameters>',0DH,0AH DB 9,'[ ... ]',9,9,9,'MEND',0DH,0AH DB 9,' DB ' a semicolon instead',0DH,0AH,0AH DB 0 ; FILE NAME MESSAGES PRFNM1: DB 'Source File: ',0 PRFNM2: DB ' Destination File: ',0 ; FIRST TWO LINES OF MAC FILE FHDR: DB 9,'.Z80',0DH,0AH ;USE ZILOG MNEMONICS DB 9,'ASEG',0DH,0AH ;USE ABSOLUTE SEGMENTS DB 0 ERR1: DB 'Output File Write Error',0DH,0AH,7,0 ERR2: DB 'No Source File Found',0DH,0AH,7,0 ERR3: DB 'No Directory Space',0DH,0AH,7,0 ERR4: DB 'Output File Already Exists -- Delete It and Continue (Y/N)? ' DB 0 ERR4A PTR TO CURRENT POSITION IN INPUT BUFFER IBUFPTR: DS 2 ; COUNT OF NUMBER OF CHARS LEFT IN INPUT BUFFER IBUFCNT: DS 1 ; SPACE FOR EQUATE FLAG EQUFLG: DS 1 ; INPUT BUFFER (BLOCK) IBUFFER: DS 128 END 'if omitted, the following values are assumed:',0DH,0AH,0AH DB ' . The Source File will have a type of ASM',0DH,0AH DB ' . The Destination File will have the same name',0DH,0AH DB ' as the Source File',0DH,0AH DB ' . The Destination File will have a type of MAC',0DH,0AH,0AH DB 'Type to Continue - ',0 HMSG2: DB 0DH,0AH,0AH DB 'The following are examples of its use:',0DH,0AH,0AH DB ' XLATE2 DEMO1 <-- Translates DEMO1.ASM to DEMO1.MAC' DB 0DH,0AH DB ' XLATE2 D#macro-call',9,9,'macro-call',0DH,0AH,0 ; ; INPUT FILE FCB ; FCBASM: DB 0,0,0,0,0,0,0,0,0,'ASM',0 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0 ; ; OUTPUT FILE FCB ; FCBZ80: DB 0,0,0,0,0,0,0,0,0,'MAC',0 DB 0,0,0,0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0 ; ; BUFFERS ; ; STACK AREA DS 128 ; CURRENT POSITION IN LINE OF OUTPUT BUFFER OBUFLPOS: DS 1 ; COUNTER FOR EVERY 10 LINES LCOUNT: DS 1 ; COUNTER FOR EVERY 60*10 LINES NLCOUNT: DS 1 ; IN COMMENT FLAG -- 0 MEANS NOT I'