home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
asmutl
/
unload86.arc
/
UNLOAD86.A86
< prev
next >
Wrap
Text File
|
1988-08-09
|
17KB
|
529 lines
;************************************************************************
;* *
;* UNLOAD86.A86 This is a MS-DOS unload program. See the help *
;* screen at the end of this file for details on its use. *
;* Written by: Mark D. Pickerill for Pro-Log Corp. 9 Aug. 1988 *
;* Assemble with the 2500 A.D. X8086 assembler. *
;* *
;************************************************************************
;
CR: EQU 0DH ; Carriage return
LF: EQU 0AH ; Line feed
EOF: EQU 1AH ; End of file
;
ORG 0100H ; Start of tpa
;
UNLOAD: JMP SHORT START ; Skip data area
;
FILDAT: DB 0FFH ; Data to fill empty space in rom (if selected)
BNPFTYP:DB 'PN' ; Pn for bnpf, hl for bhlf, or 10 for b10f
FTYPE: DB '.HEX',00H ; File type
FTYPE1: DB '.BNP',00H ; File type for bnpf files
OUTTYPE:DB 00H ; 00 for hex, non-zero for bnpf
USEEXT: DB 00H ; 00 for no extended address records
DOFILL: DB 00H ; 00 not to fill to end of rom
ENDSEG: DW 0000H ; Space to store end segment for rom fill
ENDADDR:DW 0000H ; Space to store end address for rom fill
OOD: DB 00H ; Flag 0 for read from disk, ff to use fildat
NOPARMS:JMP HELP ; Extend short jump
;
START: PUSH CS ; Set data segment
POP DS ; It's set
PUSH DS ; Get this segment
POP ES ; And set es as well
CALL ILPRT ; Print signon message
DB CR,LF,'UNLOAD86 ver. 1.0',00H
MOV SI,0080H ; Point to parameter field in psp
MOV CL,[SI] ; Get parameter length
OR CL,CL ; Force flags
JZ NOPARMS ; Print help screen
MOV CH,00H ; Zero ch
LOOP1: INC SI ; Point to start of parameters
MOV AL,[SI] ; Get byte from parameter field
CMP AL,' ' ; Space?
LOOPZ LOOP1 ; Wait until you get a non-space char
JZ NOPARMS ; Just spaces, print help screen
CMP AL,'/' ; Switch char?
JZ NOPARMS ; No filename!, print help screen
LEA DI,INFN ; Point to input filename area
MOV [DI],AL ; Stuff this char
LOOP2: INC SI ; Increment source
INC DI ; And destination
MOV AL,[SI] ; Get byte
CMP AL,' ' ; End?
JZ CONT ; Yes
CMP AL,'/' ; Or switch char?
JZ SWITCH ; Yes
MOV [DI],AL ; Stuff char
LOOP LOOP2 ; Nope
JMP SHORT CONT ; No more
SWITCH: INC SI ; Point to next
MOV AL,[SI] ; Get switch options
AND AL,5FH ; Make upper case as ibm types
; Usualy use lower case!
CMP AL,'B' ; Bnpf option?
JZ SETBNPF ; Yes
CMP AL,'E' ; Use extended address records?
JZ SETEXT ; Yes
CMP AL,'P' ; Set eprom type?
JZ SETROM ; Yes
LOOP SWITCH ; Look for more options
JMP CONT ; No more
;
SETEXT: MOV AL,0FFH ; Indicate use of extended addressing
MOV [USEEXT],AL ; Flag it as such
LOOP SWITCH ; Look for more options
JMP CONT ; No more
;
SETBNPF:MOV AL,0FFH ; Indicate bnpf option
MOV [OUTTYPE],AL ; Set it
;
LOOKMOR:LOOP SWITCH ; If more, look for additional options
JMP CONT ; No more
;
SETROM: INC SI ; Look at next char
DEC CX ; And decrement loop counter
MOV AL,[SI] ; Get char
CMP AL,'0' ; At least a zero?
JC LOOKMOR ; No,ignore
CMP AL,'A' ; At least an a?
JC NUM ; Numeric
AND AL,5FH ; Force upper case
CMP AL,'G' ; More garbage?
JNC LOOKMOR ; Yes, ignore
SUB AL,37H ; Remove alpha bias
JMP SHORT FOUNDIT ; And continue
NUM: CMP AL,3AH ; Above numeric?
JNC LOOKMOR ; Yes, ignore
SUB AL,30H ; Remove numeric bias
FOUNDIT:PUSH AX ; Save our number
CMP AL,0CH ; Big rom?
JC SMALL ; No
MOV AL,0FFH ; Larger than 64k, force extended addressing
MOV [USEEXT],AL ; Do it
SMALL: POP AX ; Recover our number
PUSH SI ; Save pointer
LEA SI,ATABLE ; Point to address table
ADD AL,AL ; Multiply by two
ADD AL,AL ; And by four
XOR AH,AH ; Clear ah
ADD SI,AX ; Add in offset
MOV AX,[SI] ; Get segment address
MOV [ENDSEG],AX ; Stuff it
ADD SI,02H ; Point to offset address
MOV AX,[SI] ; Get offset address
MOV [ENDADDR],AX ; Stuff it
MOV [DOFILL],BYTE PTR 0FFH ; Flag fillrom operation
POP SI ; Restore si
JMP LOOKMOR ; Go look for more options
;
CONT: INC DI ; Point past new filename
MOV [DI],BYTE PTR 00H ; Terminate string
LEA SI,INFN ; Copy input to output fn
LEA DI,OUTFN ; Pointing to output filename
MOV CX,60D ; 64-4 for 'hex0' is 60
LOOP3: MOV AL,[SI] ; Get byte
MOV [DI],AL ; Go ahead & move it
INC SI ; Increment source
INC DI ; And destination
CMP AL,'.' ; Looking for that file extension
JZ DONE ; Found the dot
CMP AL,'0' ; End?
LOOPNZ LOOP3 ; Continue
DONE: DEC DI ; Backup over dot or zero
MOV CX,0005H ; Five bytes to move
MOV AL,[OUTTYPE] ; Hex or bnpf?
OR AL,AL ; Force flags
JZ OHEX ; Hex
LEA SI,FTYPE1 ; Point to file type for bnpf
JMP SHORT ALL ; And continue
OHEX: LEA SI,FTYPE ; Point to file type for hex
ALL: REP MOVSB ; Move the rest
;
MOV AL,00H ; Read access code
MOV AH,3DH ; Open file function
LEA DX,INFN ; Point to input file name
INT 21H ; Open the file
MOV [INHDL],AX ; Save handle
JNC OK ; Ok
CALL ILPRT ; Print this...
DB CR,LF,'Failure to Open Input file',00H
JMP FINIS ; Go to error handler
;
OK: MOV CL,00H ; Normal addributes
MOV AH,3CH ; Create file function
LEA DX,OUTFN ; Point to file name
INT 21H ; Open the file
JNC OK1 ; Ok
CALL ILPRT ; Print this...
DB CR,LF,'Failure to Open output file',00H
JMP FINIS ; Go to error handler
OK1: MOV [OUTHDL],AX ; Save handle
MOV AL,[OUTTYPE] ; Get output format
OR AL,AL ; Force flags
JZ READ ; Don't do start char for bnpf
LEA DX,CNTRLB ; Point to start byte
MOV BX,[OUTHDL] ; Get output handle
MOV AH,40H ; Write function
MOV CX,0003H ; One byte + crlf
INT 21H ; Do it
JNC READ ; Ok
JMP BADWR ; Error
;
READ: LEA DI,INBUF ; Point to input buffer
MOV CX,16D ; Fill entire buffer
MOV AL,[FILDAT] ; Get fill data
MOV AH,AL ; Dup into ah
REP STOSW ; Do it
;
MOV AL,[OOD] ; Already out of data?
OR AL,AL ; Force flags
JNZ FILLIT ; Yup
LEA DX,INBUF ; Point to buffer
MOV CX,32D ; Process 32 bytes at a time
MOV BX,[INHDL] ; Get handle
MOV AH,3FH ; Read function
INT 21H ; Do it
JNC ROK ; Ok
CALL ILPRT ; Print this...
DB CR,LF,'Error Reading Input file',00H
JMP FINIS ; Go to error handler
;
CNTRLB: DB 02H,CR,LF ; Bnpf start
;
ROK: CMP AX,0000H ; Completely finished?
JNZ NOPE ; Nope
MOV AL,[OUTTYPE] ; Check for bnpf
OR AL,AL ; Force flags
JNZ EXIT ; Bnpf ignores all this...
MOV AL,0FFH ; Indicate we're finished reading from disk
MOV [OOD],AL ; Flag it
MOV AL,[DOFILL] ; Check for fillrom function
OR AL,AL ; Force flags
JZ EXIT ; Not selected
FILLIT: MOV AX,[EXTEND] ; Get current segment
SUB AX,1000H ; Compensate to what is in use
CMP [ENDSEG],AX ; Check against selected end segment
JC TOOBIG ; Warn operator that his data won't fit
JNZ NOPE ; Segment hasn't been reached yet, continue
MOV AX,[ADDRESS] ; Get current address
DEC AX ; To last location, not next avail loc
CMP [ENDADDR],AX ; Check against selected end address
JC TOOBIG ; Warn oerator that his data won't fit
JNZ NOPE ; Address hasn't been reached yet
;
EXIT: JMP FINISHUP ; Yes, finish up & terminate
TOOBIG: JMP WARN ; Tell operator
NOPE: MOV AL,[OUTTYPE] ; Get output format
OR AL,AL ; Force flags
JZ HEX ; Do hex
; Drop through to bnpf
LEA SI,INBUF ; Point to input buffer
MOV CX,32D ; 32 bytes to process
BNPF: LEA DI,OUTBUF ; Output buffer
MOV [DI],BYTE PTR 'B' ; The b for begin
INC DI ; Next location
BIGLP: MOV AL,[SI] ; Get byte
PUSH CX ; Save byte loop
MOV CX,0008H ; 8 bits in a byte
BNPFLP: RCL AL,1 ; Rotate through carry
JC P ; High
MOV AH,[BNPFTYP]+1 ; Get the byte for low
MOV [DI],AH ; Put in buffer
INC DI ; Next location
LOOP BNPFLP ; Do entire byte
JMP ONEBYTE ; Complete & write
P: MOV AH,[BNPFTYP] ; Get the byte for high
MOV [DI],AH ; Put in buffer
INC DI ; Next location
LOOP BNPFLP ; Do entire byte
ONEBYTE:MOV [DI],BYTE PTR 'F' ; The f for finish
POP CX ; Recover byte loop
INC SI ; Next byte
INC DI ; Next dest
MOV [DI],BYTE PTR 0DH ; Send a cr
INC DI ; Next
MOV [DI],BYTE PTR 0AH ; Send a lf
INC DI ; Next
PUSH CX ; Save loop counter
PUSH SI ; Save input counter
MOV CX,12D ; Twelve bytes every time
CALL WRITE ; Write byte
POP SI ; Recover input counter
POP CX ; Recover loop counter
LOOP BNPF ; Do next byte
JMP READ ; Read next 32 bytes
;
HEX: XOR BX,BX ; Output counter
MOV CX,32D ; Input counter
XOR DX,DX ; Dl is checksum reg
MOV AX,[ADDRESS] ; Get current load address
OR AX,AX ; Force flags
JNZ NOEXT ; No extended address record needed
CALL EAR ; Do extended addressing if selected
NOEXT: LEA SI,INBUF ; Point to input buffer
LEA DI,OUTBUF ; Point to output buffer
MOV [DI],BYTE PTR ':' ; Stuff that colon
INC DI ; And point to next
INC BX ; And increment counter
MOV AL,20H ; All are 32 byte records
CALL BITE ; Stuff it
MOV AX,[ADDRESS] ; Get load address
XCHG AL,AH ; Do high byte first
CALL BITE ; Send it
XCHG AH,AL ; Now do low byte
CALL BITE ; Send it
MOV AX,[ADDRESS] ; Get load address
ADD AX,20H ; Increment to next
MOV [ADDRESS],AX ; Put back
MOV AL,00H ; Record type 00
CALL BITE ; Send it
LOOP4: MOV AL,[SI] ; Get input
CALL BITE ; Process
INC SI ; Point to next
LOOP LOOP4 ; Until done
MOV AL,DL ; Get checksum
CALL BITE ; Process, [clobbering dl]
MOV [DI], WORD PTR 0A0DH ; Append crlf
ADD BX,02H ; Bump output counter appropiately
MOV CX,BX ; Get count into cx
CALL WRITE ; Write output
JMP READ ; Read more
;
WRITE: LEA DX,OUTBUF ; Point to beginning of output buffer
MOV BX,[OUTHDL] ; Get output handle
MOV AH,40H ; Write function
INT 21H ; Do it
JNC WOK ; Ok
BADWR: CALL ILPRT ; Print this...
DB CR,LF,'Error Writing Output file',00H
JMP FINIS ; Go to error handler
WOK: RET ; Near
;
EAR: PUSH AX ; Save everything
MOV AL,[USEEXT] ; Get extended address flag
OR AL,AL ; Force flags
JNZ GOAHEAD ; Yes, do extended addressing
MOV AX,[EXTEND] ; Get extended address anyway
ADD AX,1000H ; Increment to next 64k block
MOV [EXTEND],AX ; Put back for consistancy
POP AX ; Restore ax
RET ; Go home
GOAHEAD:PUSH DI ;
PUSH CX ;
PUSH DX ;
PUSH SI ;
PUSH BX ;
LEA DI,OUTBUF ; Point to output buffer
MOV [DI],BYTE PTR ':' ; Stuff that colon
INC DI ; And point to next
INC BX ; And increment counter
MOV AL,02H ; Two bytes of data in extended record
CALL BITE ; Stuff it
MOV AX,0000H ; Extended address records have load addr of 0
XCHG AL,AH ; Do high byte first
CALL BITE ; Send it
XCHG AH,AL ; Now do low byte
CALL BITE ; Send it
MOV AL,02H ; Record type 02
CALL BITE ; Send it
MOV AX,[EXTEND] ; Get current extended address
XCHG AL,AH ; Do high byte first
CALL BITE ; Send it
XCHG AH,AL ; Now do low byte
CALL BITE ; Send it
MOV AX,[EXTEND] ; Get extended address again
ADD AX,1000H ; Increment to next 64k block
MOV [EXTEND],AX ; Put back
MOV AL,DL ; Get checksum
CALL BITE ; Process, [clobbering dl]
MOV [DI], WORD PTR 0A0DH ; Append crlf
ADD BX,02H ; Bump output counter appropiately
MOV CX,BX ; Get count into cx
CALL WRITE ; Write output
POP BX ; Recover everything
POP SI ;
POP DX ;
POP CX ;
POP DI ;
POP AX ;
RET ; Go home
;
FINISHUP: ;
CALL ILPRT ; Print this...
DB CR,LF,'Function Complete.',00H
MOV AL,[OUTTYPE] ; Get output format
OR AL,AL ; Force flags
JZ HEXEND ; Do hex
; Drop through to bnpf
;
BNPFEND:LEA DX,CNTRLC ; Point to eof marker
MOV BX,[OUTHDL] ; Get output handle
MOV AH,40H ; Write function
MOV CX,0003H ; One byte
INT 21H ; Do it
JNC WOKK ; Ok
JMP BADWR ; Error
;
WARN: CALL ILPRT ; Print this...
DB CR,LF,LF,'WARNING: Input data file too large for output size'
DB ' selected.',07H,LF,00H ;
JMP FINISHUP ; Terminate
;
CNTRLC: DB 03H,CR,LF ; Termination for bnpf
;
HEXEND: LEA DX,EOFREC ; Point to eof record
MOV BX,[OUTHDL] ; Get output handle
MOV AH,40H ; Write function
MOV CX,0014H ; Fourteen bytes
INT 21H ; Do it
JNC WOKK ; Ok
JMP BADWR ; Error
;
WOKK: MOV AH,3EH ; Close the file now
MOV BX,[OUTHDL] ; Close output
INT 21H ; Close the damn thing
JNC CLOK ; Closed ok
CALL ILPRT ; Print this...
DB CR,LF,'Error Closing Output file!',00H
;
CLOK: MOV AH,3EH ; Close the file now
MOV BX,[INHDL] ; Close input
INT 21H ; Close the damn thing
JNC FINIS ; Closed ok
CALL ILPRT ; Print this...
DB CR,LF,'Error Closing Input file!',00H
;
FINIS: MOV AX,4C00H ; Terminate
INT 21H ; Bye-bye
;
EOFREC: DB ':00000001FF',CR,LF,EOF ; End of file record
;
;************************************************************************
;* *
;* ILPRT: This is an 8088 in-line print routine. It will print *
;* the string following the CALL NEAR instruction until a 00H is *
;* encountered. Accepts: Data string to print in memory following*
;* the CALL NEAR used to invoke this routine. Returns: Nothing. *
;* Calls: CONOUT. Clobbers: ES,SI *
;* *
;************************************************************************
;
ILPRT: PUSH CS ; Get code segment
POP ES ; Into es
POP SI ; Get offset
PUSH AX ; Save ax
PUSH DX ; And dx
ILLP: MOV AL,ES:[SI] ; Get char
OR AL,AL ; Force flags
JZ ILEXIT ; Exit if last
CALL CONOUT ; Send char
INC SI ; Point to next
JMP SHORT ILLP ; Loop til done
ILEXIT: INC SI ; Point to next instruction
POP DX ; Restore dx
POP AX ; And ax
PUSH SI ; And return offset
RET ; Near
;
CONOUT: MOV AH,02H ; Conout call
MOV DL,AL ; Get char
INT 21H ; Do it
RET ; Near
;
BITE: SUB DL,AL ; Generate checksum
PUSH AX ; Save
AND AL,0F0H ; Mask out lower nybble
ROR AL,1 ; Get msn into lower nybble
ROR AL,1 ;
ROR AL,1 ;
ROR AL,1 ; Now it's there
CALL NYB ; Process nybble
MOV [DI],AL ; Save in disk buffer
INC BX ; Increment count
INC DI ; Next location in buffer
POP AX ; Recover byte
AND AL,0FH ; Mask lsn
CALL NYB ; Process nybble
MOV [DI],AL ; Save in disk buffer
INC BX ; Increment count
INC DI ; Next location in buffer
RET ; Near
;
; Converts lower nybble in al to ascii hex
NYB: CMP AL,0AH ; Letter?
JNC NYB1 ; Yes
ADD AL,30H ; Add in numeric bias
RET ; Go home (near)
NYB1: ADD AL,37H ; Add in letter bias
RET ; Go home (near)
;
INHDL: BLKB 2 ; Storage for input file handle
OUTHDL: BLKB 2 ; Storage for output file handle
ADDRESS:DW 0000H ; Current address
EXTEND: DW 0000H ; Current extended address
INFN: BLKB 64D ; Plenty of room for a filename & path
OUTFN: BLKB 64D ; Output filename
INBUF: BLKB 32D ; Thirty two byte input buffer
OUTBUF: EQU $ ; Output buffer
;
HELP: ; Called only if nothing is going to happen
; Otherwise, this routine is overwritten
CALL ILPRT ; Print help screen
DB CR,LF,LF,'Usage: UNLOAD86 FILENAME.TYP[/OPTIONS]'
DB CR,LF,LF,'Where Options are:'
DB CR,LF,' B for BNPF instead of INTeL hex.'
DB '(Overrides all other options!)'
DB CR,LF,' E to use extended addressing in INTeL hex.'
DB CR,LF,' P to fill output file to end of EPROM.'
DB CR,LF,' Uses the following subcommands:'
DB CR,LF,' 0 32 Bytes 1 64 Bytes'
DB CR,LF,' 2 128 Bytes 3 256 Bytes'
DB CR,LF,' 4 512 Bytes 5 1K Bytes'
DB CR,LF,' 6 2K Bytes 7 4K Bytes'
DB CR,LF,' 8 8K Bytes 9 16K Bytes'
DB CR,LF,' A 32K Bytes B 64K Bytes'
DB CR,LF,' C *128K Bytes D *256K Bytes'
DB CR,LF,' E *512K Bytes F *1Meg Bytes'
DB CR,LF,LF,' * Forces extended addressing'
DB CR,LF,LF,'INTeL hex output files are .HEX'
DB CR,LF,'BNPF output files are .BNP'
DB CR,LF,00H ;
JMP FINIS ; Terminate
;
ATABLE: ; Table of rom sizes for fillrom option
DW 0000H ; Segment for 32 byter
DW 001FH ; Address for 32 byter
DW 0000H ; Segment for 64 byter
DW 003FH ; Address for 64 byter
DW 0000H ; Segment for 128 byter
DW 007FH ; Address for 128 byter
DW 0000H ; Segment for 256 byter
DW 00FFH ; Address for 256 byter
DW 0000H ; Segment for 512 byter
DW 01FFH ; Address for 512 byter
DW 0000H ; Segment for 1k byter
DW 03FFH ; Address for 1k byter
DW 0000H ; Segment for 2k byter
DW 07FFH ; Address for 2k byter
DW 0000H ; Segment for 4k byter
DW 0FFFH ; Address for 4k byter
DW 0000H ; Segment for 8k byter
DW 1FFFH ; Address for 8k byter
DW 0000H ; Segment for 16k byter
DW 3FFFH ; Address for 16k byter
DW 0000H ; Segment for 32k byter
DW 7FFFH ; Address for 32k byter
DW 0000H ; Segment for 64k byter
DW 0FFFFH ; Address for 64k byter
DW 1000H ; Segment for 128k byter
DW 0FFFFH ; Address for 128k byter
DW 3000H ; Segment for 256k byter
DW 0FFFFH ; Address for 256k byter
DW 7000H ; Segment for 512k byter
DW 0FFFFH ; Address for 512k byter
DW 0F000H ; Segment for 1m byter
DW 0FFFFH ; Address for 1m byter
;
END ;