; ------------------------------------------------------------ ; LOHD.ASM is a revision of Digital Research's LOAD.COM, which ; is evidently a PL/M program. The revision has reduced its ; volume by 2/3, but its execution is disk-bound to the point ; that the speed difference is not outwardly apparent. Other ; changes include: ; 1. An origin below 0100H - CP/M's transient origin - no ; longer produces an error condition if it is 0000H. Thus a ; file assembled to origin 0000 can be passed from .HEX to ; .COM, such as if it were the code for a self-relocating ; program such as DDT. ; 2. The .COM buffer is zeroed before each use, so that ; gaps in the code sequence, the result of a or of an ; , are filled with zeroes rather than being left to ; gather whatever trash is in the buffer as they are found. ; The .COM code is passed through a one-page window, so that ; any origin redefined below that range will draw an error ; message, as in LOAD.COM. ; ; [Harold V. McIntosh, 22 September 1983] ; ------------------------------------------------------------ BDOS equ 0005H TFCB equ 005CH TSIZ equ 0080H TORG equ 0100H CSIZ equ 0100H ;size of .COM buffer HSIZ equ 0400H ;size of hexfile buffer LF equ 0AH CR equ 0DH ; ------------- org 0100H ; ------------- begn: lxi h,0000 dad sp shld stak ;save sp lxi sp,stak ;stackend lxi h,CSIZ shld cinx ;.COM index call cbuz ;clear CBUF lxi h,HSIZ shld hinx ;hexfile index lda TFCB+1 cpi ' ' jnz nnul lxi d,logo call mssg lxi d,tuto call mssg jmp gbye ;normal exit nnul: mvi c,021H ;count lxi d,TFCB ;source lxi h,HFCB ;.HEX FCB = destination call miuc mvi c,4 ;count lxi d,X01F7 ;'hex' = source lxi h,HFCB+9;.HEX ext = destination call miuc lxi d,HFCB ;.HEX FCB mvi c,15 ;(0F) open file call BDOS cpi 0FFH lxi d,X01FB ;'can''t open source' jz tema ;type err mess w/addr mvi c,3 ;count lxi d,X020E ;'COM' = source lxi h,TFCB+9;destination call miuc lxi d,TFCB mvi c,19 ;(13) delete file call BDOS lxi d,TFCB mvi c,22 ;(16) create file call BDOS lxi d,TFCB mvi c,15 ;(0F) open file call BDOS cpi 0FFH lxi d,X0211 ;'no more directory' jz tema ;type err mess w/addr call hefi ;process the .HEX file lxi d,TFCB mvi c,16 ;(10) close file call BDOS cpi 0FFH lxi d,X0229 ;'can''t close file' jz tema ;type err mess w/addr fini: call crlf ;CR,LF gbye: lhld stak ;save sp sphl ret ; Type CR, LF. crlf: mvi a,CR call cona ;console from A mvi a,LF jmp cona ;console from A word: mov a,h call byte ;type A as two nibbles mov a,l byte: push psw rar rar rar rar call nibl ;type A as hex pop psw nibl: ani 0FH adi 90H daa aci 40H daa cona: push h push d mov e,a mvi c,2 ;(02) write console call BDOS pop d pop h ret ; Type message at (DE). mssg: call crlf ;CR,LF mess: mvi c,9 ;(09) type buffer jmp BDOS ; Type error message with address. tema: push d lxi d,X0129 ;'error' call mssg ;type CRLF, mssg pop d call mess ;type mess at (DE) lxi d,X0131 ;'load address' call mess ;type mess at (DE) lhld cinx ;.COM index call word ;type HL in four nibbles jmp gbye ;normal exit ; Block move. miuc: ldax d mov m,a inx h inx d dcr c jnz miuc ret ; Get next hexfile element. nxhx: lhld hinx ;hexfile index inx h lxi d,HSIZ mov a,l sub e mov a,h sbb d jc nxhv ;byte available lxi h,0000 nxhy: shld hinx ;hexfile index lxi d,HSIZ mov a,l sub e mov a,h sbb d jnc nxhu ;reset hexfile, read 1st element lxi d,HBUF dad d xchg mvi c,26 ;(1A) set DMA address call BDOS lxi d,HFCB ;.HEX FCB mvi c,20 ;(14) read one record call BDOS cpi 000H jz nxhz ;add record to hexfile cpi 001H lxi d,X0141 ;'disk read' jnz tema ;type err mess w/addr lhld hinx ;hexfile index lxi d,HBUF ;hexfile buffer dad d mvi m,01AH ;^Z lxi h,HSIZ-1 shld hinx ;hexfile index nxhz: lhld hinx ;hexfile index lxi d,TSIZ dad d jmp nxhy ;no more refills nxhu: lxi h,0000 nxhv: shld hinx ;hexfile index lxi d,HBUF ;hexfile buffer dad d mov a,m ret ; Start reading the .HEX file, and keep going. hefi: lxi h,0FFFFH shld mina ;minimum address lxi h,0000 shld maxa ;maximum address shld byco ;byte counter xra a sta reco ;record counter lxi h,TORG shld ladr ;load address shld rbrk ;record breakpoint shld cinx ;.COM index lxi h,HBUF ;hexfile buffer mvi m,01AH ;^Z inhx: call nxhx ;next hexfile element sui ':' jnz inhx ;advance to ":" mov d,a ;checksum in D call hexb ;assemble byte, augment checksum mov e,a ;bytecount in E cpi 00H jnz nlin ;this isn't "end" line lhld cinx ;.COM index xchg elin: lhld rbrk ;record breakpoint mov a,l ;cmp(HL,DE) sub e mov a,h sbb d jnc stat ;type statistics xra a call comb ;insert byte in .COM buffer jmp elin ;fill out buffer with zeroes nlin: lhld byco ;byte counter push d mvi d,00 dad d pop d shld byco ;byte counter call hexb ;assemble byte, augment checksum push psw call hexb ;assemble byte, augment checksum pop h mov l,a ora h jnz horg ;high (non-zero) origin shld rbrk ;record breakpoint horg: shld ladr ;load address shld cinx ;.COM index lhld mina ;minimum address inx h mov a,h ora l jnz nmin lhld cinx ;.COM index shld mina ;minimum address nmin: call hexb ;assemble byte, augment checksum ihli: call hexb ;assemble byte, augment checksum call comb ;insert byte in .COM buffer dcr e jnz ihli push d lhld maxa ;maximum address xchg lhld cinx ;.COM index mov a,e sub l mov a,d sbb h jnc nmax dcx h shld maxa ;maximum address nmax: pop d call hexb ;assemble byte, augment checksum mov a,d cpi 00H jz inhx ;on to next line lxi d,X01A8 ;'check sum error' call mssg ;type CRLF, mssg jmp erst ;type error statistics ; Type summary of statistics. stat: lxi d,X01B9 ;'first address' call mssg ;type CRLF, mssg lhld mina ;minimum address call word ;type HL in four nibbles lxi d,X01C8 ;'last address' call mssg ;type CRLF, mssg lhld maxa ;maximum address call word ;type HL in four nibbles lxi d,X01D7 ;'bytes read' call mssg ;type CRLF, mssg lhld byco ;byte counter call word ;type HL in four nibbles lxi d,X01E6 ;'records written' call mssg ;type CRLF, mssg lda reco ;record counter call byte ;type A as two nibbles jmp crlf ;CR,LF ; Insert byte in .COM buffer. comb: push d push psw lhld rbrk ;record breakpoint xchg lhld cinx ;.COM index mov a,l ;cmp(HL,DE) sub e mov a,h sbb d lxi d,X014B ;'inverted load address' jc tema ;type err mess w/addr lxi d,CSIZ ;nc means 'rbrk .le. index' lhld rbrk ;record breakpoint dad d xchg lhld cinx ;.COM index mov a,l ;cmp(HL,DE) sub e mov a,h sbb d cnc budi ;send CBUF to disk lxi d,CBUF ;.COM buffer mvi h,00 dad d pop psw mov m,a lhld cinx ;.COM index inx h shld cinx ;.COM index pop d ret ; Send CBUF to disk. budi: push h call budj pop h ret budj: mvi c,26 ;(1A) set DMA address lxi d,CBUF call BDOS call budk ;record to disk lxi d,CBUF+TSIZ mvi c,26 ;(1A) set DMA address call BDOS call budk ;record to disk ; Fill CBUF with zeroes. cbuz: xra a mvi b,2 ;CBUF holds 2 records lxi h,CBUF cbuy: mvi c,TSIZ cbux: mov m,a inx h dcr c jnz cbux dcr b jnz cbuy ret budk: lhld rbrk ;record breakpoint lxi d,TSIZ dad d shld rbrk ;record breakpoint lxi h,reco ;record counter inr m lxi d,TFCB mvi c,21 ;(15) write one record call BDOS cpi 00H lxi d,X0161 ;'disk write' jnz tema ;type err mess w/addr ret ; Type error statistics. erst: lxi d,X016C ;'load address' call mssg ;type CRLF, mssg lhld ladr ;load address call word ;type HL in four nibbles lxi d,X017B ;'error address' call mssg ;type CRLF, mssg lhld cinx ;.COM index call word ;type HL in four nibbles lxi d,X018A ;'bytes read' call mssg ;type CRLF, mssg call tyla ;type load address: ersu: lhld cinx ;.COM index xchg lhld ladr ;load address mov a,l sub e mov a,h sbb d jnc fini ;CR,LF,exit lhld ladr ;load address mov a,l ani 00FH cpi 000H jnz ersv call tyla ;type load address: ersv: lhld rbrk ;record breakpoint xchg lhld ladr ;load address mov a,l sub e mov l,a mov a,h sbb d mov h,a lxi b,CBUF ;.COM buffer dad b mov a,m call byte ;type A as two nibbles lhld ladr ;load address inx h shld ladr ;load address mvi a,' ' call cona ;console from A jmp ersu ; Type :. tyla: call crlf ;CR,LF lhld ladr ;load address call word ;type HL in four nibbles mvi a,':' call cona ;console from A mvi a,' ' jmp cona ;console from A ; Make up general hexdigit. hexn: call nxhx ;next hexfile element sui '0' cpi 10 ;ten rc sui 7 ;seven cpi 10 ;ten jc nhex cpi 16 ;sixteen rc nhex: lxi d,X0196 ;'invalid hex digit' call mssg ;type CRLF, mssg jmp erst ;type error statistics ; Join hexinhx nibbles to form byte. hexb: push b push h push d call hexn ;general hexdigit add a add a add a add a push psw call hexn ;general hexdigit pop b ora b mov b,a pop d add d mov d,a mov a,b pop h pop b ret logo: db ' LOHD/ICUAP',CR,LF db 'Universidad Autonoma de Puebla',CR,LF db ' September 22, 1983',CR,LF,'$' tuto: db 'LOHD.ASM is a variant of Digital Research''s LOAD.COM',CR,LF db 'which was reduced to 2/3 its original volume by using',CR,LF db 'machine language rather than PL/M. It accepts 0000H as',CR,LF db 'an origin lower than 0100H, facilitating the generation',CR,LF db 'of the master file for a self-relocating program. Gaps',CR,LF db 'caused by or are filled with zeroes rather',CR,LF db 'than trash from the memory.',CR,LF db CR,LF db ' LOHD [X:]FILE[.QQQ]',CR,LF db CR,LF db 'will read [X:]FILE.HEX to produce [X:]FILE.COM.',CR,LF db '$' X0129: db 'error: $' X0131: db ', load address $' X0141: db 'Disk read$' X014B: db 'Load address cannot be accomodated' X0161: db 'Disk write$' X016C: db 'Load address $' X017B: db 'Error address $' X018A: db 'Bytes read:$' X0196: db 'Invalid hex digit$' X01A8: db 'Check sum error $' X01B9: db 'First address $' X01C8: db 'Last address $' X01D7: db 'Bytes read $' X01E6: db 'Records written $' X01F7: db 'HEX',00 X01FB: db 'Can''t open source$' X020E: db 'COM' X0211: db 'Disk or Directory full$' X0229: db 'Cannot close file$' HFCB: ds 21H ;.HEX FCB HBUF: ds HSIZ+1 ;hexfile buffer (400H) hinx: ds 2 ;hexfile index cinx: ds 2 ;.COM index ladr: ds 2 ;load address mina: ds 2 ;minimum address maxa: ds 2 ;maximum address byco: ds 2 ;byte counter CBUF: ds 100H ;.COM buffer reco: ds 1 ;record counter rbrk: ds 2 ;record breakpoint ds 20H stak: ds 2 ;stackend end