home *** CD-ROM | disk | FTP | other *** search
-
- ; hc.asm v1.4 2/10/84
- ; fast hexconverter
- ; Copyright (C) 1984 Martin Smith
- ;
- ; Fixes odd line problem, further optimized.
- ;
- ; Assemble and then use EXE2BIN to make a COM file.
- ;
- ; Convert com/exe/bin to hex or back.
- ; format
- ; 1) hc file.hex file.com
- ; 2) hc file.com file.hex
- ; 3) hc file.hex
- ; program examines file for .exe format, else .com
- ; 4) hc file(.com/.exe/.bin)
- ; program outputs file.hex
- ; 5) hc
- ; program prints doc.
- ; Note: HC does is NOT produce an Intel format HEX file.
- ; Rather it is the modulo 2048 single checksum format
- ; found on many IBM BBS's.
-
- title [[hc]] hexconverter
- page 60,100
-
- TRUE equ -1
- FALSE equ 0
- EOF equ 26 ; Ctrl-Z
- PARAGRAPHS EQU 256 ; adjust for program size, leaving room
- ; for a stack. Generally leave alone.
- BUFSIZE EQU 64 ; for args
-
- ; DOS function calls used
-
- DISPLAYOUT EQU 0200H
- PRINTSTRING EQU 0900H
- GETDOSVERSION EQU 3000H
- CREAT EQU 3C00H
- OPENFILE EQU 3D00H
- CLOSEFILE EQU 3E00H
- READFILE EQU 3F00H
- WRITEFILE EQU 4000H
- DELETEFILE EQU 4100H
- ALLOCATE EQU 4800H
- FREEMEMORY EQU 4900H
- SETBLOCK EQU 4A00H
-
- cseg segment para 'code'
- org 100h ; COM program
- assume cs:cseg,ds:cseg
-
- start proc far
-
- begin:
- mov bp,sp
- mov cs:oldstack,bp
- test ax,0ffffh ; test for invalid drive spec.
- jz begin_ok
- mov ax,15 ; invalid drive
- jmp report_bad
-
- begin_ok:
- mov ax,cs ; better safe than sorry.
- mov ds,ax
- mov es,ax
-
- mov dx,offset himess ; print greeting
- mov ax,PRINTSTRING
- int 21h
- mov si,80h ; get args
- mov di,offset arg1
- mov cl,[si]
- cmp cl,0 ; no args
- jnz ck_for_right_dos
- jmp do_doc ; so print a documentation
-
- ck_for_right_dos:
- push si
- push di
- push cx
- mov ax,GETDOSVERSION
- int 21h
- pop cx
- pop di
- pop si
- cmp al,2 ; dos 2.+ ?
- jnb dos_ok
- mov dx,offset must_be_20
- jmp report_abort
-
- dos_ok:
-
- mov sp,16*PARAGRAPHS-1 ; stack not adjusted by
- mov bp,sp ; SETBLOCK, so must do it here.
- ; adjust PARAGRAPHS in EQUates to
- ; reflect program size.
- mov ch,0
-
- b2:
- inc si ; ignor leading blanks
- mov al,[si]
- cmp al,' '
- jnz b3
- loop b2
- jmp do_doc ; do doc if no args
-
- b3:
- mov [di],al ; else copy first arg to our space
- inc di
- inc si
- mov al,[si]
- cmp al,' '
- jz b4
- cmp al,13
- jz b4
- loop b3
-
- b4:
- dec cx ; got an arg, allow for trailing blanks
- mov al,0 ; keep up with CX to use LOOP instruction
- mov [di],al
- mov byte ptr cs:numargs,1
- cmp cx,0
- jnz b5
- jmp memory_setup
-
- b5:
- mov di,offset arg2 ; after this its arg2
- dec cx ; keep up with CX
- cmp cx,0
- jnz b6
- jmp memory_setup
-
- b6:
- inc si ; ignor leading blanks
- mov al,[si]
- cmp al,' '
- jnz b7
- loop b6
- jmp memory_setup ; go to next if nothing
-
- b7:
- mov [di],al ; else copy input to our space.
- inc di
- inc si
- mov al,[si]
- cmp al,' '
- jz b8
- cmp al,13
- jz b8
- loop b7
-
- b8:
- mov al,0 ; got an arg, put \0 for ASCIZ
- mov [di],al
- mov byte ptr cs:numargs,2
- jmp memory_setup ; ignor any more
-
- start endp
-
- do_doc proc near
-
- mov dx,offset doc ; print until $
- mov ax,PRINTSTRING
- int 21h
- mov dx,offset do_cr
- jmp report_abort ; exit
-
- do_doc endp
-
- report_bad proc near
- ;
- ; use AX error return to point DX to message from
- ; error return table
- ;
- push cs
- pop ds
- shl ax,1
- mov si,offset error
- add si,ax
- mov dx,[si]
-
- report_bad endp
-
- report_abort proc near
- ;
- ; print message from DX, restore regs and abort.
- ; common exit, neatness counts.
- ; plus we've screwed around with the stack.
- ;
- assume ds:cseg
-
- mov bp,cs:oldstack
- mov sp,bp
- mov ax,cs
- mov ds,ax
- mov es,ax
- mov ax,PRINTSTRING
- int 21h
- int 20h ; common exit all routines
-
- report_abort endp
-
- hexbin proc near
- ;
- ; Convert HEX to binary
- ;
- ; Call with DL = first HEX digit
- ; DH = second HEX digit
- ;
- ; Returns with DL = converted byte
- ; Carry flag = 0 valid input
- ; Carry flag = 1 invalid input
- ; Other registers preserved.
- ;
- ; From Dr. Dobbs #74
- ; December 1982 p.14
- ; by Robert Blair
- ;
- push cx
- push bx
- mov bl,dl
- call hexbin_test
- mov bh,bl
- mov bl,dh
- call hexbin_test
- mov cx,4
- shl bh,cl
- and bl,00001111b
- mov dl,bh
- or dl,bl
- clc
- pop bx
- pop cx
- ret
- hexbin_test:
- cmp bl,'0'
- jb hexbin_error
- cmp bl,'9'
- ja $+3
- ret
- ; cmp bl,'f' ; don't swap capitols here
- ; ja hexbin_error
- ; cmp bl,'a' ; lowercase is allright after all.
- ; jb $+6
- ; add bl,9 ; uncomment this if they start up with
- ; ret ; lowercase hex files.
- cmp bl,'A'
- jb hexbin_error
- cmp bl,'F'
- ja hexbin_error
- add bl,9
- ret
- hexbin_error:
- clc
- cmc
- pop bx
- pop bx
- pop cx
- ret
- hexbin endp
-
- binhex proc near
- ;
- ; Convert binary to hex
- ;
- ; Call with DL = byte to convert
- ;
- ; Returns with DL = first HEX digit
- ; DH = second HEX digit
- ; Other registers preserved
- ;
- push cx
- push bx
- mov cx,4
- mov dh,dl
- shr dl,cl
- and dh,00001111b
- sub bh,bh
- mov bl,dl
- mov dl,cs:translate_hex [bx]
- mov bl,dh
- mov dh,cs:translate_hex [bx]
- pop bx
- pop cx
- ret
-
- translate_hex db '0123456789ABCDEF'
-
- binhex endp
-
-
- print proc near
- ;
- ; print string until \0
- ; SI points to first character
- ; All other regs preserved
- ; String in CS
- ;
- push ds
- push ax
- push dx
- mov ax,cs
- mov ds,ax
-
- pr1:
- mov dl,[si]
- cmp dl,0
- jz pr2
- mov ax,DISPLAYOUT
- int 21h
- inc si
- jmp pr1
-
- pr2:
- mov dl,' ' ; insert space for neatness.
- mov ax,DISPLAYOUT
- int 21h
- pop dx
- pop ax
- pop ds
- ret
-
- print endp
-
- crlf proc near
- ; send a carriage return/line feed
- push dx ; to console.
- push ax
- mov ax,DISPLAYOUT
- mov dl,13
- int 21h
- mov ax,DISPLAYOUT
- mov dl,10
- int 21h
- pop ax
- pop dx
- ret
-
- crlf endp
-
- free_memory proc near
-
- push ax ; gives back memory we allocated,
- mov ax,cs:comseg ; preserves AX, which maybe has
- mov es,ax ; error code.
- mov ax,FREEMEMORY
- int 21h
- jc fm_bad
- mov ax,cs:txtseg
- mov es,ax
- mov ax,FREEMEMORY
- int 21h
- jc fm_bad
- pop ax
- ret
-
- fm_bad:
- jmp report_bad
-
- free_memory endp
-
-
- memory_setup proc near
- ;
- ; request 96k, adjust for less
- ;
- assume ds:nothing
- mov bx,PARAGRAPHS ; adjust to actual. Use equ at top
- mov ax,SETBLOCK
- int 21h ; SETBLOCK - shrink us
- jnc msa
- jmp report_bad
-
- msa:
- mov bx,1800h ; ask for 96k
- mov ax,ALLOCATE
- int 21h
- jnc msb
- cmp ax,8 ; insufficient memory
- jz ms1
-
- msb:
- mov bx,1800h ; got our request
- jmp ms2
-
- ms1:
- push bx
- mov ax,ALLOCATE
- int 21h ; so ask for less
- jnc msc
- jmp report_bad ; still fouled up?
-
- msc:
- pop bx
-
- ms2:
- mov cs:txtseg,ax
- mov es,ax ; now have allocated total space
- mov dx,0
- mov ax,bx
- mov cx,3
- div cx ; divide by three
- dec ax ; safety factor
- mov cs:space,ax
- mov bx,ax
- shl bx,1 ; multiply by 2
- mov ax,SETBLOCK ; shrink our total space
- int 21h
- jnc ms2a
- jmp report_bad ; get out if error after all this
-
- ms2a:
- mov bx,cs:space
- mov ax,ALLOCATE ; allocate second block
- int 21h
- jnc ms3
- jmp report_bad
-
- ms3:
- mov cs:comseg,ax
- mov bx,cs:space ; get 1/3 of paragraphs
- mov cl,4
- shl bx,cl ; times 16 = bytes available
- dec bx ; sub 2 for safety
- dec bx
- mov cs:comspace,bx ; com file put here in either
- inc bx ; routine.
- inc bx
- shl bx,1 ; times 2 = text space
- dec bx
- dec bx
- mov cs:txtspace,bx ; hex file always in this one.
- mov ax,cs:txtspace ; [bp-2] structure for easy access
- ; to end of space.
- push ax ; Valid in either routine.
- mov ax,cs:comspace ; [bp-4]
- push ax
- mov ax,cs ; don't use blocks yet, have
- mov ds,ax ; to do file setup.
- mov es,ax
- jmp open_files
-
- memory_setup endp
-
- write_hc proc near
- assume ds:nothing ; universal write to file routine.
- push cx ; Saves registers used in time
- push bx ; critical loops, provides safe
- push ds ; error exits. Most of the errors
- push es ; in this program will come from
- pop ds ; disk, so take care here.
- mov dx,0
- mov cx,di
- mov bx,cs:handle2 ; assume file already open for write
- mov ax,WRITEFILE
- int 21h
- jnc whc1
- push cs
- pop ds
- mov si,offset arg2 ; lots of messages for foul ups
- call print
- call crlf
- shl ax,1
- mov si,offset error
- add si,ax
- mov dx,[si]
- mov ax,PRINTSTRING
- int 21h
- jmp bad_input ; bad_input tidies up mess.
-
- whc1:
- cmp di,ax
- jnz wh_full
- mov ax,0
- add cs:f_size,di
- adc cs:f_size+2,ax
- mov di,0
- pop ds
- pop bx
- pop cx
- ret
-
- wh_full:
- mov si,offset cs:disk_full ; if disk is full,
- call print
- call crlf
- call free_memory
- mov bx,cs:handle2
- mov ax,CLOSEFILE ; close file,
- int 21h
- jnc wh_full2
- jmp report_bad
-
- wh_full2:
- push cs
- pop ds
- mov dx,offset arg2
- mov ax,DELETEFILE ; then delete it from disk.
- int 21h ; save user some time.
- jnc wh_full3
- jmp report_bad
-
- wh_full3:
- mov dx,offset cs:cancelled
- jmp report_abort
-
- write_hc endp
-
- hcread proc near
- ; universal read from file routine.
- push bx ; just slight differences for
- mov cx,cs:txtspace ; com->hex and hex<-com.
- push cx
- jmp read_input
-
- hcread endp
-
- chread proc near
-
- push bx
- mov cx,cs:comspace
- push cx
- jmp read_input
-
- chread endp
-
- read_input proc near
-
- mov bx,cs:handle1
- mov dx,0
- mov ax,READFILE
- int 21h ; read from file
- jnc ri_ok
- push ax ; if we come back with the
- push cs ; carry flag set, things didn't
- pop ds ; go allright, so we had better
- mov si,offset arg1 ; not continue
- call print
- call crlf
- mov bx,cs:handle2
- mov ax,CLOSEFILE ; close 2
- int 21h
- call free_memory
- mov dx,offset arg2
- mov ax,DELETEFILE ; delete
- int 21h
- mov dx,offset cs:cancelled
- mov ax,PRINTSTRING
- int 21h
- pop ax
- jmp report_bad
-
- ri_ok:
-
- cmp ax,0 ; EOF and no checksum?
- jnz ri1 ; special case for HEX file.
- cmp byte ptr cs:com_to_hex,TRUE ; its all right to not have
- jz ri1 ; a checksum, but theres no
- jmp no_hc_checksum ; sense in heading back to
- ; the process loop.
- ri1:
- mov si,ax
- mov byte ptr [si],0ffh ; set last byte to ff for check
- pop cx
- pop bx
- mov si,0
- cmp ax,cx ; all read in?
- jb ri_done
-
- ret
-
- ri_done:
- mov byte ptr cs:all_read,TRUE ; set flag indicating no more
- cmp byte ptr cs:com_to_hex,TRUE ; reading required
- jnz ri_hc
- mov cs:comspace,ax ; store maxbytes all over
- mov [bp-4],ax
- mov cx,ax
- ret
-
- ri_hc:
- mov cs:txtspace,ax
- mov [bp-2],ax
- mov cx,ax
- ret
-
- read_input endp
-
-
- open_files proc near
-
-
- mov ax,cs
- mov ds,ax
- mov cx,BUFSIZE*2 ; make args lowercase
- mov si,offset arg1
-
- of2:
- mov al,[si]
- cmp al,'A'
- jl of3
- cmp al,'Z'
- ja of3
- add al,32
- mov [si],al
-
- of3:
- inc si
- loop of2
-
- cmp byte ptr cs:numargs,2 ; have to find which is hex
- jz of4
- jmp find_files
-
- of4:
- mov si,offset arg1
-
- of4a:
-
- mov al,[si]
- cmp al,'.'
- jz of5
- inc si
- cmp al,0 ; end of arg and no extension
- jnz of4a
- mov byte ptr cs:com_to_hex,TRUE ; better be true
- jmp of10
-
- of5:
- inc si
- mov al,[si]
- cmp al,'h' ; is this hex?
- jz of6
- mov byte ptr cs:com_to_hex,TRUE ; set flag
- jmp of10
-
- of6:
- mov byte ptr cs:com_to_hex,FALSE ; first arg is HEX,
- jmp open ; so its hex_to_com.
-
- of10:
- mov si,offset arg2
-
- of11:
- mov al,[si]
- cmp al,'.' ; look for .
- jz of12
- inc si
- cmp al,0 ; end of arg and no extension
- jnz of11
- call free_memory
- mov dx,offset need_hex ; two args, one has to be hex
- jmp report_abort
-
- of12:
- inc si
- mov al,[si]
- cmp al,'h' ; here this better be HEX
- jz of13
- call free_memory ; otherwise bye bye
- mov dx,offset need_hex
- jmp report_abort
-
- of13:
- jmp open
-
- find_files: ; only one arg supplied, have to find which
- mov si,offset arg1
- mov di,offset arg2
-
- ff1:
- mov al,[si] ; search for extension
- mov [di],al
- cmp al,'.'
- jz ff2
- inc si
- inc di
- cmp al,0 ; no ext means com_to_hex
- jnz ff1
-
- dec di
-
- mov byte ptr cs:com_to_hex,TRUE ; make second arg HEX
- mov al,'.'
- mov [di],al
-
- ff1a:
- mov al,'h'
- inc di
- mov [di],al
- mov al,'e'
- inc di
- mov [di],al
- mov al,'x'
- inc di
- mov [di],al
- mov al,0
- inc di
- mov [di],al
- jmp open
-
- ff2:
- inc si
- inc di
- mov cs:temp,di
- mov al,[si]
- cmp al,'h' ; is it hex?
- jz ff3
-
- mov byte ptr cs:check_exe,FALSE ; no, make second HEX
- mov byte ptr cs:com_to_hex,TRUE
- dec di
- jmp ff1a
-
- ff3:
- mov byte ptr cs:check_exe,TRUE
- mov byte ptr cs:com_to_hex,FALSE
-
- open: ; we now have 2 args, with one possibly waiting
- ; for COM or EXE extension
- assume ds:cseg
- mov ax,cs
- mov ds,ax
- cmp byte ptr cs:com_to_hex,TRUE
- jz openc
- jmp openh
-
- openc:
- mov dx,offset arg1
- mov ax,OPENFILE ; for reading
- clc
- int 21h
- jnc opcok
- mov si,offset arg1
- call print
- call free_memory
- jmp report_bad
-
- opcok:
- mov cs:handle1,ax
-
- mov dx,offset arg2
- mov cx,0 ; normal file attribute
- mov ax,CREAT
- clc
- int 21h
- jnc opcok1
- mov si,offset arg2 ; print which file caused error
- call print
- call free_memory
- jmp report_bad
-
- opcok1:
- mov cs:handle2,ax ; otherwise store handle
- jmp com_hex ; do com->hex
-
- openh:
- mov dx,offset arg1
- mov ax,OPENFILE ; for reading
- clc
- int 21h
- jnc ophok
- mov si,offset arg1
- call print
- jmp report_bad
-
- ophok:
- mov cs:handle1,ax
- cmp byte ptr cs:check_exe,TRUE
- jz opcheck
- jmp ophok1
-
- opcheck:
- assume ds:nothing ; here we read in first block
- mov ax,cs:txtseg ; then look for the MZ
- mov ds,ax ; footprint of an EXE file.
-
- call hcread
-
- opcheck2:
- mov si,0
-
- opchl:
- mov dl,[si] ; ignor all leading stuff until
- cmp dl,13 ; first convertible bytes
- jz opch1
- cmp dl,10
- jz opch1
- cmp dl,' '
- jz opch1
- cmp dl,';'
- jnz opch4
- call op_find
-
- jmp opchl
-
- opch1:
- inc si
- jmp opchl
-
- opch4:
-
- inc si
- mov dh,[si]
- call hexbin ; hexbin comes back with carry set
- jnc opch5 ; if it can't convert input.
- jmp opcom ; can't make sense, so make com
-
- opch5:
- mov al,dl
- inc si
- mov dx,[si]
- call hexbin
- jnc opch6
- jmp opcom
-
- opch6:
- mov dh,dl
- mov dl,al
- push cs
- pop ds
- cmp dx,5a4dh ; MZ are the first two bytes of an EXE file.
- jz opexe ; make ext EXE
- jmp opcom ; make ext COM
-
- op_find:
- inc si ; simple ignor
- mov dl,[si] ; we can convert files downloaded
- cmp dl,13 ; without line feeds.
- jnz op_find
- inc si
- mov dl,[si]
- cmp dl,10
- jnz opf1
- inc si
-
- opf1:
- ret
-
- opexe:
- mov si,cs:temp
- mov al,'e'
- mov [si],al
- inc si
- mov al,'x'
- mov [si],al
- inc si
- mov al,'e'
- mov [si],al
- inc si
- mov al,0
- mov [si],al
- jmp ophok1
-
- opcom:
- mov si,cs:temp
- mov al,'c'
- mov [si],al
- inc si
- mov al,'o'
- mov [si],al
- inc si
- mov al,'m'
- mov [si],al
- inc si
- mov al,0
- mov [si],al
-
- ophok1:
- ; now have second arg for sure
- mov dx,offset arg2
- mov cx,0
- mov ax,CREAT ; CREATE a file
- clc
- int 21h
- jnc ophok2
- mov si,offset arg2
- call print
- call free_memory
- jmp report_bad
-
- ophok2:
- mov cs:handle2,ax
-
- open_files endp
-
- hex_com proc near
-
- mov ax,cs:txtseg ; finally use our memory set-up
- mov ds,ax
- mov ax,cs:comseg ; DS always input, ES always output
- mov es,ax
- ; first check if data already in buffer
-
- mov al,byte ptr cs:check_exe
- cmp al,TRUE
- jnz hc1
- jmp hc_read
-
- hc1:
- call hcread
-
- hc_read:
- mov si,0
- mov di,0
- mov bx,0 ; checksum stored in BX, don't lose it
- mov cx,cs:txtspace
-
- hcloop:
- mov dl,[si] ; most used routine, process stuff till
- cmp dl,13 ; out of space in buffer or EOF
- jz hclcont
- cmp dl,10
- jz hclcont
- cmp dl,' '
- jz hclcont
- cmp dl,';'
- jz hcl8
-
- hcl1:
- cmp dl,0ffh ; if we run out of data,
- jz hcl6
-
- hcl2:
- inc si
-
- hcl3:
- mov dh,[si]
- cmp dh,0ffh
- jz hcl5
- call hexbin ; if nothing else works it must be data
- jc bad_i
-
- hcl4:
- mov es:[di],dl ; store
- xor dh,dh
- add bx,dx ; checksum
- and bx,07ffh
- inc di
- cmp di,[bp-4] ; output buffer size in [bp-4]
- jz hcl7
-
- hclcont:
- inc si
-
- jmp hcloop
-
- hcl5:
- push dx
- call hcread ; if we fall through here, we need more
- pop dx
- jmp hcl3 ; data, then go back for more loop.
-
- hcl6:
- call hcread ; go dig up some more.
- jmp hcloop
-
- hcl7:
- call write_hc ; write buffer when full.
- jmp hclcont
-
- hcl8:
- sub cx,si ; checksum uses cx
- call checksum ; may or may not return to here
- jmp hclcont
- bad_i:
- push cs
- pop ds
- mov si,offset arg1
- call print ; if hexbin comes back invalid
- call crlf ; abort routine and clean up.
- mov dx,offset not_hex
- mov ax,PRINTSTRING
- int 21h
-
- bad_input:
- call free_memory ; restores memory to original,
- mov bx,cs:handle1 ; closes both files,
- mov ax,CLOSEFILE ; then deletes output file.
- int 21h
- jnc bi1
- jmp report_bad
-
- bi1:
- mov bx,cs:handle2
- mov ax,CLOSEFILE
- int 21h
- jnc bi2
- jmp report_bad
-
- bi2:
- push cs
- pop ds
- mov dx,offset cs:arg2
- mov ax,DELETEFILE
- int 21h ; delete output file
- jnc bi3
- jmp report_bad
-
- bi3:
- mov dx,offset cs:cancelled
- jmp report_abort
-
-
- hex_com endp
-
- checksum proc near
- ;
- ; si points to ';'
- ; check for checksum, else read to end of line
- ;
- push es
- push di
- mov ax,cs
- mov es,ax
- cld
- mov dh,0
- inc si
- cmp dl,0ffh ; its possible to hit end of buffer
- jnz ch0 ; during this, so we need to check
- call hcread ; and cope.
-
- ch0:
- mov dl,[si] ; we can convert ;checksum
- cmp dl,'c' ; or ;CHECKSUM
- jnz ch0a
- mov di,offset cs:lchksum+1
- jmp ch1
-
- ch0a:
- cmp dl,'C'
- jnz ch_read_end
- mov di,offset cs:uchksum+1
-
- ch1:
- cmpsb ; compare till the bitter end.
- jnz ch_read_end
- dec cx
- cmp cx,0
- jnz ch2
- call hcread
-
- ch2:
- inc dh
- cmp dh,8
- jnz ch1
- pop di
- pop es ; this is it.
- pop ax ; discard return, no longer need hcloop
- jmp dhc1 ; found checksum word
-
- ch_read_end:
- dec si
-
- cre1:
- mov dl,[si] ; no find, so read till end
- cmp dl,13 ; of line and go back to hcloop
- jz cre_back
- inc si
- dec cx
- cmp cx,0
- jnz cre2
- call hcread
-
- cre2:
- jmp cre1
-
- cre_back:
- pop di
- pop es
- ret
-
- dhc1:
- mov dl,[si] ; ignor leading blanks
- cmp dl,' '
- jnz dhc2
- inc si
- dec cx
- cmp cx,0
- jnz dhc1
- call hcread ; get more text if end of buffer
- jmp dhc1
-
- dhc2:
- push cx ; convert ASCII checksum to binary
- mov ax,0
- mov cx,10
- mov dh,0
-
- dhc3:
- mov dl,[si] ; read numbers until no number
- cmp dl,'0'
- jae dhc4
- jmp dhc_found
-
- dhc4:
- cmp dl,'9'
- jbe dhc5
- jmp dhc_found
-
- dhc5:
- push dx ; the old multiply by ten routine
- mov dx,0 ; to convert ASCII number string
- mul cx ; into binary
- pop dx
- sub dl,'0'
- add ax,dx
- inc si
- pop cx
- dec cx ; CX still has the loop or buffer count
- cmp cx,0
- jnz dhc5a
- call hcread ; oops, ran out of buffer, so fill up again.
-
- dhc5a:
- push cx
- mov cx,10
- jmp dhc3
-
- dhc_found:
- pop cx ; got a checksum.
- cmp bx,ax ; does checksum check out?
- jz dhc_ok
- mov si,offset cs:chk_bad
- call print
- call crlf
- jmp dhc_cont ; report either way.
-
- dhc_ok:
- mov si,offset cs:chk_ok
- call print
- call crlf
- jmp dhc_cont
-
- no_hc_checksum:
- mov si,offset chk_no ; its OK not to have a checksum,
- call print ; but we're more confident if its there
- call crlf
-
- dhc_cont:
- call write_hc ; write final section.
-
- dhcok1:
- mov bx,cs:handle2
- mov ax,CLOSEFILE
- int 21h ; close outfile
- jnc dhcok2
- call free_memory ; hope things don't bomb after all this
- jmp report_bad
-
- dhcok2:
- mov bx,cs:handle1
- mov ax,CLOSEFILE
- int 21h ; close infile
- jnc dhcok3
- call free_memory
- jmp report_bad
-
- dhcok3:
-
- call free_memory ; give back memory
- mov si,offset cs:arg2
- call print
- call crlf
- call print_file_size
- mov dx,offset cs:msuccess ; print a reassuring message
- jmp report_abort ; clean up and go home.
-
- checksum endp
-
- print_file_size proc near
- ; print out file size bytes using
- assume ds:cseg ; bcd table
- push cs
- pop ds
- mov bx,offset cs:bcd0
- mov si,0
- mov ax,cs:f_size
- mov dx,1
-
- pfs1:
- test ax,dx ; test bits
- jz pfs2
- call add_bcd ; add in bcd if so
-
- pfs2:
- add si,5 ; bump pointer
- cmp dx,8000h ; test for end
- jz pfs3
- shl dx,1 ; get next test
- jmp pfs1
-
- pfs3:
- mov ax,cs:f_size+2 ; get hi word
- mov dx,1 ; start again
-
- pfs4:
- test ax,dx
- jz pfs5
- call add_bcd
-
- pfs5:
- add si,5
- cmp dx,0100h ; only need up to 16meg
- jz pfs6
- shl dx,1
- jmp pfs4
-
- pfs6:
- mov si,offset bf_size
- call print_bcd ; print out result
- mov si,offset cs:f_len
- call print ; print 'bytes recorded'
- call crlf
- ret ; back
-
- add_bcd:
- push si
- push ax
- mov di,offset bf_size ; point to bcd storage
- mov cx,5 ; its five bytes long
- clc ; clear carry to start
-
- ab1:
- mov al,[bx+si] ; get byte
- adc al,[di] ; add
- daa ; adjust for bcd
- mov [di],al ; store
- inc si ; bump
- inc di
- dec cx ; check
- jnz ab1 ; leave if done
-
- pop ax
- pop si
- ret
-
- print_bcd:
- add si,4 ; go to end (high byte)
- mov cx,5 ; set up for five total
- mov ax,0 ; AH used to check first zero
-
- pbd1:
- mov dl,[si] ; get byte
- cmp ah,1 ; see if we've started to print
- jz pbd2 ; if so don't skip
- cmp dl,0 ; else check if zero
- jz pbd3 ; and skip if so
-
- pbd2:
- mov dh,dl ; copy
- push cx ; don't lose place
- push ax
- mov cl,4 ; bcd:( 12 hex. = 12 dec. for example)
- shr dl,cl ; shr makes ( 01 )
- cmp ah,1 ; if printing print
- jz pbd2a
- cmp dl,0 ; else see if zero
- jz pbd2c ; and don't print if so
-
- pbd2a:
- add dl,30h ; make ASCII ( '1' )
- push dx
- mov ax,DISPLAYOUT ; print
- int 21h
- pop dx
-
- pbd2c:
- mov dl,dh ; get copy ( 12 )
- and dl,0fh ; mask ( 02 )
- add dl,30h ; make ASCII ( '2' )
- mov ax,DISPLAYOUT ; print
- int 21h
- pop ax
- pop cx
- mov ah,1 ; now set flag to print rest
-
- pbd3:
- dec si
- dec cx
- jnz pbd1 ; loop till done.
- ret
-
- print_file_size endp
-
-
- com_hex proc near
- ; files are open, nothing read in yet.
-
- mov ax,cs:txtseg ; do everything in reverse
- mov es,ax
- mov ax,cs:comseg ; remember in-buffer = DS
- mov ds,ax ; out-buffer = ES
- mov si,0
- mov di,0
- mov bx,0
-
- call chread
- mov ah,0 ; use for line length
- ; need to put crlf every 32(64) bytes.
- chloop:
- mov dl,[si] ; this is much simpler than hex->com
- mov dh,0 ; because there is no extraneous stuff
- add bx,dx ; chloop is time-critical, cause
- and bx,07ffh ; its 90% of routine
- call binhex
- mov es:[di],dx
- inc ah
- cmp ah,32
- jnz ch2a
- inc di
- inc di
- cmp di,[bp-2] ; out of space in text buffer?
- jnz ch1a
- call write_hc ; clean it out.
-
- ch1a:
- mov ax,0a0dh ; crlf
- mov es:[di],ax
- mov ah,0
-
- ch2a:
- inc si
- inc di
- inc di
- cmp di,[bp-2] ; this buffer is an even number so
- jnz ch3 ; we don't need to worry about
- push ax ; odd addresses like in hex->com
- call write_hc ; [bp-2] = always text buffer
- pop ax ; [bp-4] = always com buffer
-
- ch3:
- loop chloop
-
- cmp byte ptr cs:all_read,TRUE ; if its all read in
- jz ch4 ; we are almost done.
- push ax
- call chread ; else read next and continue
- pop ax ; chread will set CX to length of data
- cmp cx,0 ; tried to read past EOF?
- jz ch4 ; then we're finished with loop.
- jmp chloop
-
- ch4:
- push ax
- call write_hc ; clear buffer to make life simpler
- pop ax
- cmp ah,0 ; just did EOL?
- jz ch4a
- mov ax,0a0dh ; skip extra crlf
- mov es:[di],ax
- inc di
- inc di
-
- ch4a:
- mov ax,0a0dh
- mov es:[di],ax
- inc di
- inc di
-
- push cs ; write out ;checksum
- pop ds
- mov si,offset cs:lchksum
- mov cx,10
- cld
-
- rep movsb ; ;checksum
-
- mov ax,bx ; compute ASCII representation of
- mov dx,0 ; checksum and make it neat.
- mov cx,1000
- div cx
- mov ch,0
- cmp ax,0 ; no 1000s?
- jz ch5
- add al,30h ; ASCII 0
- mov es:[di],al
- inc di
- mov ch,1
-
- ch5:
- mov ax,dx ; remainder
- mov cl,100
- div cl
- cmp ch,1
- jz ch5a
- cmp al,0 ; no 100s?
- jz ch6
-
- ch5a:
- add al,30h
- mov es:[di],al
- inc di
- mov ch,1
-
- ch6:
- mov al,ah
- mov ah,0
- mov cl,10
- div cl
- cmp ch,1
- jz ch6a
- cmp al,0 ; no 10s?
- jz ch7
-
- ch6a:
- add al,30h
- mov es:[di],al
- inc di
-
- ch7:
- mov al,ah ; must print at least one number
- add al,30h
- mov es:[di],al
- inc di
- mov ax,0a0dh ; crlf
- mov es:[di],ax
- inc di
- inc di
- mov al,EOF ; Ctrl-Z
- mov es:[di],al
- inc di
-
- call write_hc
- jmp dhcok1 ; close and finish
-
-
- com_hex endp
-
- messages proc near
-
- himess db '[[hc]] MS-DOS 2.+ hexconverter,',13,10
- db ' v1.4 by Marty Smith.',13,10,13,10,'$'
-
-
- need_hex db 'One of files must be .HEX',13,10,'$'
- not_hex db 'Not a hex format file.',13,10,'$'
- lchksum db ';checksum ' ; 10 bytes
- uchksum db ';CHECKSUM '
- msuccess db 'Successfully created!',13,10,'$'
- chk_ok db 'Checksum verified.',0
- chk_bad db 'Checksums different,',13,10
- db 'file possibly bad.',0
- chk_no db 'No checksum found.',0
- disk_full db 'Disk full.',0
- cancelled db 'Please check file.',13,10,'$'
- f_len db ' bytes recorded.',0
- must_be_20 db '** Must be running DOS 2.+ **',13,10,'$'
- do_cr db 13,10,'$'
-
- ; DOS error returns we may encounter, others return 'unknown error'
-
- err0 db 'unknown error.',13,10,'$'
- err1 db 'bad function number.',13,10,'$'
- err2 db 'file not found.',13,10,'$'
- err3 db 'path not found.',13,10,'$'
- err4 db 'too many files.',13,10,'$'
- err5 db 'access denied.',13,10,'$'
- err6 db 'invalid handle.',13,10,'$'
- err7 db 'memory blocks damaged.',13,10,'$'
- err8 db 'insufficient memory.',13,10,'$'
- err9 db 'bad memory block address.',13,10,'$'
- err12 db 'bad access code.',13,10,'$'
- err15 db 'bad drive specified.',13,10,'$'
- err17 db 'not same device.',13,10,'$'
- err18 db 'no more files.',13,10,'$'
-
- error dw err0,err1,err2,err3,err4,err5,err6,err7,err8,err9,err0
- dw err0,err12,err0,err0,err15,err0,err17,err18
-
- f_size dw 0 ; dword file size
- dw 0
- txtseg dw 0 ; memory management
- txtspace dw 0
- comseg dw 0
- comspace dw 0
- space dw 0 ; temp for figuring workspace
- handle1 dw 0 ; file handles
- handle2 dw 0
- temp dw 0 ; scratch
- oldstack dw 0 ; store orig. stack ptr.
-
- numargs db 0 ; command line number of args.
- arg1 db BUFSIZE dup (' ') ; plenty of space for args
- arg2 db BUFSIZE dup (' ') ; and PATHs
- com_to_hex db 0 ; flags
- check_exe db 0
- all_read db 0
-
- bf_size db 5 dup (0) ; bcd file size
-
- bcd0 db 01h,00h,00h,00h,00h ; five byte bcd power of 2
- db 02h,00h,00h,00h,00h ; 2^0 to 2^24
- db 04h,00h,00h,00h,00h ; for showing file size
- db 08h,00h,00h,00h,00h ; up to 16meg MS-DOS limit
- db 16h,00h,00h,00h,00h
- db 32h,00h,00h,00h,00h
- db 64h,00h,00h,00h,00h
- db 28h,01h,00h,00h,00h
- db 56h,02h,00h,00h,00h
- db 12h,05h,00h,00h,00h
- db 24h,10h,00h,00h,00h
- db 48h,20h,00h,00h,00h
- db 96h,40h,00h,00h,00h
- db 92h,81h,00h,00h,00h
- db 84h,63h,01h,00h,00h
- db 68h,27h,03h,00h,00h
- db 36h,55h,06h,00h,00h
- db 72h,10h,13h,00h,00h
- db 44h,21h,26h,00h,00h
- db 88h,42h,52h,00h,00h
- db 76h,85h,04h,01h,00h
- db 52h,71h,09h,02h,00h
- db 04h,43h,19h,04h,00h
- db 08h,86h,38h,08h,00h
- db 16h,72h,77h,16h,00h
-
- ; doc at end so it can be used for stack space.
-
- doc db 'Converts HEX format files to COM,EXE or BIN.',13,10
- db ' or COM,EXE or BIN files to HEX.',13,10,13,10
- db ' Type: >hc in_file [out_file]',13,10,13,10
- db 'If TWO files are entered, ONE of them MUST be HEX,',13,10
- db ' i.e. xxx.HEX xxx.COM = Hex to Com, xxx.EXE xxx.HEX = Exe to Hex.',13,10,13,10
- db 'If ONE file is entered, the following occurs:',13,10
- db ' If the first file has no extension, or it is non-HEX:',13,10
- db ' A second file is made in HEX format, with an extension .HEX.',13,10
- db ' If the first file has a .HEX extension:',13,10
- db ' The program will automatically provide a .COM or .EXE extension,',13,10
- db ' depending on file type.'
- db '$'
-
- messages endp
-
- cseg ends ; that's all folks
- end start
-
-
-
-
- Access: