MS-DOS/v1.25/source/HEX2BIN.ASM

214 lines
3.3 KiB
NASM
Raw Normal View History

1982-03-04 00:51:26 +00:00
; HEX2BIN version 1.02
; Converts Intel hex format files to straight binary
FCB: EQU 5CH
READ: EQU 20
SETDMA: EQU 26
OPEN: EQU 15
CLOSE: EQU 16
CREATE: EQU 22
DELETE: EQU 19
BLKWRT: EQU 40
GETSEG: EQU 38
BUFSIZ: EQU 1024
ORG 100H
PUT 100H
HEX2BIN:
MOV DI,FCB+9
CMP B,[DI]," "
JNZ HAVEXT
MOV SI,HEX
MOVB
MOVW
HAVEXT:
;Get load offset (default is -100H)
MOV CL,4 ;Needed for shifts
MOV [OFFSET],-100H
MOV SI,FCB+11H ;Scan second FCB for offset
LODB
CMP AL," " ;Check if offset present
JZ HAVOFF
MOV B,[SIGN],0 ;Assume positive sign for now
CMP AL,"+"
JZ GETOFF ;Get a positive offset
CMP AL,"-"
JNZ GETOFF1 ;If not + or -, then not signed
MOV B,[SIGN],1 ;Flag as negative offset
GETOFF:
LODB ;Eat sign
GETOFF1:
CALL HEXCHK ;Check for valid hex character
JC HAVOFF ;No offset if not valid
XOR BX,BX ;Intialize offset sum to 0
CONVOFF:
SHL BX,CL ;Multiply current sum by 16
OR BL,AL ;Add in current hex digit
LODB ;Get next digit
CALL HEXCHK ;And convert it to binary
JNC CONVOFF ;Loop until all hex digits read
TEST B,[SIGN],-1 ;Check if offset was to be negative
JZ SAVOFF
NEG BX
SAVOFF:
MOV [OFFSET],BX
HAVOFF:
MOV DX,STARTSEG
MOV AX,DS
ADD DX,AX ;Compute load segment
MOV AH,GETSEG
INT 33
MOV ES,DX
SEG ES
MOV CX,[6] ;Get size of segment
MOV [SEGSIZ],CX
XOR AX,AX
MOV DI,AX
MOV BP,AX
SHR CX
REP
STOW ;Fill entire segment with zeros
MOV AH,OPEN
MOV DX,FCB
INT 21H
OR AL,AL
JNZ NOFIL
MOV B,[FCB+32],0
MOV [FCB+14],BUFSIZ ;Set record size to buffer size
MOV DX,BUFFER
MOV AH,SETDMA
INT 33
MOV AH,READ
MOV DX,FCB ;All set up for sequential reads
MOV SI,BUFFER+BUFSIZ ;Flag input buffer as empty
READHEX:
CALL GETCH
CMP AL,":" ;Search for : to start line
JNZ READHEX
CALL GETBYT ;Get byte count
MOV CL,AL
MOV CH,0
JCXZ DONE
CALL GETBYT ;Get high byte of load address
MOV BH,AL
CALL GETBYT ;Get low byte of load address
MOV BL,AL
ADD BX,[OFFSET] ;Add in offset
MOV DI,BX
CALL GETBYT ;Throw away type byte
READLN:
CMP DI,[SEGSIZ]
JAE ADERR
CALL GETBYT ;Get data byte
STOB
CMP DI,BP ;Check if this is the largest address so far
JBE HAVBIG
MOV BP,DI ;Save new largest
HAVBIG:
LOOP READLN
JP READHEX
NOFIL:
MOV DX,NOFILE
QUIT:
MOV AH,9
INT 21H
INT 20H
ADERR:
MOV DX,ADDR
JMP SHOWERR
GETCH:
CMP SI,BUFFER+BUFSIZ
JNZ NOREAD
INT 21H
CMP AL,1
JZ ERROR
MOV SI,BUFFER
NOREAD:
LODB
CMP AL,1AH
JZ DONE
RET
GETBYT:
CALL HEXDIG
MOV BL,AL
CALL HEXDIG
SHL BL
SHL BL
SHL BL
SHL BL
OR AL,BL
RET
HEXCHK:
SUB AL,"0"
JC RET
CMP AL,10
JC CMCRET
SUB AL,"A"-"0"-10
JC RET
CMP AL,16
CMCRET:
CMC
RET
HEXDIG:
CALL GETCH
CALL HEXCHK
JNC RET
ERROR:
MOV DX,ERRMES
SHOWERR:
MOV AH,9
INT 21H
DONE:
MOV [FCB+9],4F00H+"C" ;"CO"
MOV B,[FCB+11],"M"
MOV DX,FCB
MOV AH,CREATE
INT 21H
OR AL,AL
JNZ NOROOM
XOR AX,AX
MOV [FCB+33],AX
MOV [FCB+35],AX ;Set RR field
INC AX
MOV [FCB+14],AX ;Set record size
XOR DX,DX
PUSH DS
PUSH ES
POP DS ;Get load segment
MOV AH,SETDMA
INT 21H
POP DS
MOV CX,BP
MOV AH,BLKWRT
MOV DX,FCB
INT 21H
MOV AH,CLOSE
INT 21H
EXIT:
INT 20H
NOROOM:
MOV DX,DIRFUL
JMP QUIT
HEX: DB "HEX"
ERRMES: DB "Error in HEX file--conversion aborted$"
NOFILE: DB "File not found$"
ADDR: DB "Address out of range--conversion aborted$"
DIRFUL: DB "Disk directory full$"
OFFSET: DS 2
SEGSIZ: DS 2
SIGN: DS 1
BUFFER: DS BUFSIZ
START:
STARTSEG EQU (START+15)/16