home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / filutl / hc.arc / HC.ASM next >
Encoding:
Assembly Source File  |  1984-05-02  |  27.1 KB  |  1,543 lines

  1.  
  2. ; hc.asm v1.4  2/10/84
  3. ; fast hexconverter
  4. ; Copyright (C) 1984 Martin Smith
  5. ;
  6. ; Fixes odd line problem, further optimized.
  7. ;
  8. ; Assemble and then use EXE2BIN to make a COM file.
  9. ;
  10. ; Convert com/exe/bin to hex or back.
  11. ; format
  12. ; 1) hc file.hex file.com
  13. ; 2) hc file.com file.hex
  14. ; 3) hc file.hex
  15. ; program examines file for .exe format, else .com
  16. ; 4) hc file(.com/.exe/.bin)
  17. ; program outputs file.hex
  18. ; 5) hc
  19. ; program prints doc.
  20. ; Note: HC does is NOT produce an Intel format HEX file.
  21. ; Rather it is the modulo 2048 single checksum format
  22. ; found on many IBM BBS's.
  23.  
  24.  title [[hc]] hexconverter
  25.  page 60,100
  26.  
  27. TRUE equ -1
  28. FALSE equ 0
  29. EOF equ 26 ; Ctrl-Z
  30. PARAGRAPHS EQU 256 ; adjust for program size, leaving room
  31.     ; for a stack. Generally leave alone.
  32. BUFSIZE  EQU 64 ; for args
  33.  
  34. ; DOS function calls used
  35.  
  36. DISPLAYOUT EQU 0200H
  37. PRINTSTRING EQU 0900H
  38. GETDOSVERSION EQU 3000H
  39. CREAT  EQU 3C00H
  40. OPENFILE EQU 3D00H
  41. CLOSEFILE EQU 3E00H
  42. READFILE EQU 3F00H
  43. WRITEFILE EQU 4000H
  44. DELETEFILE EQU 4100H
  45. ALLOCATE EQU 4800H
  46. FREEMEMORY EQU 4900H
  47. SETBLOCK EQU 4A00H
  48.  
  49. cseg segment para 'code'
  50.  org 100h   ; COM program
  51.  assume cs:cseg,ds:cseg
  52.  
  53. start proc far
  54.  
  55. begin:
  56.  mov bp,sp
  57.  mov cs:oldstack,bp
  58.  test ax,0ffffh  ; test for invalid drive spec.
  59.  jz begin_ok
  60.  mov ax,15   ; invalid drive
  61.  jmp report_bad
  62.  
  63. begin_ok:
  64.  mov ax,cs   ; better safe than sorry.
  65.  mov ds,ax
  66.  mov es,ax
  67.  
  68.  mov dx,offset himess ; print greeting
  69.  mov ax,PRINTSTRING
  70.  int 21h
  71.  mov si,80h   ; get args
  72.  mov di,offset arg1
  73.  mov cl,[si]
  74.  cmp cl,0   ; no args
  75.  jnz ck_for_right_dos
  76.  jmp do_doc   ; so print a documentation
  77.  
  78. ck_for_right_dos:
  79.  push si
  80.  push di
  81.  push cx
  82.  mov ax,GETDOSVERSION
  83.  int 21h
  84.  pop cx
  85.  pop di
  86.  pop si
  87.  cmp al,2   ; dos 2.+ ?
  88.  jnb dos_ok
  89.  mov dx,offset must_be_20
  90.  jmp report_abort
  91.  
  92. dos_ok:
  93.  
  94.  mov sp,16*PARAGRAPHS-1 ; stack not adjusted by
  95.  mov bp,sp   ; SETBLOCK, so must do it here.
  96.      ; adjust PARAGRAPHS in EQUates to
  97.      ; reflect program size.
  98.  mov ch,0
  99.  
  100. b2:
  101.  inc si   ; ignor leading blanks
  102.  mov al,[si]
  103.  cmp al,' '
  104.  jnz b3
  105.  loop b2
  106.  jmp do_doc   ; do doc if no args
  107.  
  108. b3:
  109.  mov [di],al   ; else copy first arg to our space
  110.  inc di
  111.  inc si
  112.  mov al,[si]
  113.  cmp al,' '
  114.  jz b4
  115.  cmp al,13
  116.  jz b4
  117.  loop b3
  118.  
  119. b4:
  120.  dec cx  ; got an arg, allow for trailing blanks
  121.  mov al,0  ; keep up with CX to use LOOP instruction
  122.  mov [di],al
  123.  mov byte ptr cs:numargs,1
  124.  cmp cx,0
  125.  jnz b5
  126.  jmp memory_setup
  127.  
  128. b5:
  129.  mov di,offset arg2 ; after this its arg2
  130.  dec cx  ; keep up with CX
  131.  cmp cx,0
  132.  jnz b6
  133.  jmp memory_setup
  134.  
  135. b6:
  136.  inc si  ; ignor leading blanks
  137.  mov al,[si]
  138.  cmp al,' '
  139.  jnz b7
  140.  loop b6
  141.  jmp memory_setup ; go to next if nothing
  142.  
  143. b7:
  144.  mov [di],al  ; else copy input to our space.
  145.  inc di
  146.  inc si
  147.  mov al,[si]
  148.  cmp al,' '
  149.  jz b8
  150.  cmp al,13
  151.  jz b8
  152.  loop b7
  153.  
  154. b8:
  155.  mov al,0  ; got an arg, put \0 for ASCIZ
  156.  mov [di],al
  157.  mov byte ptr cs:numargs,2
  158.  jmp memory_setup ; ignor any more
  159.  
  160. start endp
  161.  
  162. do_doc proc near
  163.  
  164.  mov dx,offset doc ; print until $
  165.  mov ax,PRINTSTRING
  166.  int 21h
  167.  mov dx,offset do_cr
  168.  jmp report_abort ; exit
  169.  
  170. do_doc endp
  171.  
  172. report_bad proc near
  173. ;
  174. ; use AX error return to point DX to message from
  175. ; error return table
  176. ;
  177.  push cs
  178.  pop ds
  179.  shl ax,1
  180.  mov si,offset error
  181.  add si,ax
  182.  mov dx,[si]
  183.  
  184. report_bad endp
  185.  
  186. report_abort proc near
  187. ;
  188. ; print message from DX, restore regs and abort.
  189. ; common exit, neatness counts.
  190. ; plus we've screwed around with the stack.
  191. ;
  192.  assume ds:cseg
  193.  
  194.  mov bp,cs:oldstack
  195.  mov sp,bp
  196.  mov ax,cs
  197.  mov ds,ax
  198.  mov es,ax
  199.  mov ax,PRINTSTRING
  200.  int 21h
  201.  int 20h   ; common exit all routines
  202.  
  203. report_abort endp
  204.  
  205. hexbin proc near
  206. ;
  207. ; Convert HEX to binary
  208. ;
  209. ; Call with DL = first HEX digit
  210. ;  DH = second HEX digit
  211. ;
  212. ; Returns with DL = converted byte
  213. ;  Carry flag = 0 valid input
  214. ;  Carry flag = 1 invalid input
  215. ;  Other registers preserved.
  216. ;
  217. ; From Dr. Dobbs #74
  218. ; December 1982  p.14
  219. ; by Robert Blair
  220. ;
  221.  push cx
  222.  push bx
  223.  mov bl,dl
  224.  call hexbin_test
  225.  mov bh,bl
  226.  mov bl,dh
  227.  call hexbin_test
  228.  mov cx,4
  229.  shl bh,cl
  230.  and bl,00001111b
  231.  mov dl,bh
  232.  or dl,bl
  233.  clc
  234.  pop bx
  235.  pop cx
  236.  ret
  237. hexbin_test:
  238.  cmp bl,'0'
  239.  jb hexbin_error
  240.  cmp bl,'9'
  241.  ja $+3
  242.  ret
  243. ; cmp bl,'f'          ; don't swap capitols here
  244. ; ja hexbin_error
  245. ; cmp bl,'a'          ; lowercase is allright after all.
  246. ; jb $+6
  247. ; add bl,9  ; uncomment this if they start up with
  248. ; ret   ; lowercase hex files.
  249.  cmp bl,'A'
  250.  jb hexbin_error
  251.  cmp bl,'F'
  252.  ja hexbin_error
  253.  add bl,9
  254.  ret
  255. hexbin_error:
  256.  clc
  257.  cmc
  258.  pop bx
  259.  pop bx
  260.  pop cx
  261.  ret
  262. hexbin endp
  263.  
  264. binhex proc near
  265. ;
  266. ; Convert binary to hex
  267. ;
  268. ; Call with DL = byte to convert
  269. ;
  270. ; Returns with DL = first HEX digit
  271. ;  DH = second HEX digit
  272. ;  Other registers preserved
  273. ;
  274.  push cx
  275.  push bx
  276.  mov cx,4
  277.  mov dh,dl
  278.  shr dl,cl
  279.  and dh,00001111b
  280.  sub bh,bh
  281.  mov bl,dl
  282.  mov dl,cs:translate_hex [bx]
  283.  mov bl,dh
  284.  mov dh,cs:translate_hex [bx]
  285.  pop bx
  286.  pop cx
  287.  ret
  288.  
  289. translate_hex db '0123456789ABCDEF'
  290.  
  291. binhex endp
  292.  
  293.  
  294. print proc near
  295. ;
  296. ; print string until \0
  297. ; SI points to first character
  298. ; All other regs preserved
  299. ; String in CS
  300. ;
  301.  push ds
  302.  push ax
  303.  push dx
  304.  mov ax,cs
  305.  mov ds,ax
  306.  
  307. pr1:
  308.  mov dl,[si]
  309.  cmp dl,0
  310.  jz pr2
  311.  mov ax,DISPLAYOUT
  312.  int 21h
  313.  inc si
  314.  jmp pr1
  315.  
  316. pr2:
  317.  mov dl,' '                  ; insert space for neatness.
  318.  mov ax,DISPLAYOUT
  319.  int 21h
  320.  pop dx
  321.  pop ax
  322.  pop ds
  323.  ret
  324.  
  325. print endp
  326.  
  327. crlf proc near
  328.     ; send a carriage return/line feed
  329.  push dx  ; to console.
  330.  push ax
  331.  mov ax,DISPLAYOUT
  332.  mov dl,13
  333.  int 21h
  334.  mov ax,DISPLAYOUT
  335.  mov dl,10
  336.  int 21h
  337.  pop ax
  338.  pop dx
  339.  ret
  340.  
  341. crlf endp
  342.  
  343. free_memory proc near
  344.  
  345.  push ax  ; gives back memory we allocated,
  346.  mov ax,cs:comseg ; preserves AX, which maybe has
  347.  mov es,ax  ; error code.
  348.  mov ax,FREEMEMORY
  349.  int 21h
  350.  jc fm_bad
  351.  mov ax,cs:txtseg
  352.  mov es,ax
  353.  mov ax,FREEMEMORY
  354.  int 21h
  355.  jc fm_bad
  356.  pop ax
  357.  ret
  358.  
  359. fm_bad:
  360.  jmp report_bad
  361.  
  362. free_memory endp
  363.  
  364.  
  365. memory_setup proc near
  366. ;
  367. ; request 96k, adjust for less
  368. ;
  369.  assume ds:nothing
  370.  mov bx,PARAGRAPHS  ; adjust to actual. Use equ at top
  371.  mov ax,SETBLOCK
  372.  int 21h   ; SETBLOCK - shrink us
  373.  jnc msa
  374.  jmp report_bad
  375.  
  376. msa:
  377.  mov bx,1800h  ; ask for 96k
  378.  mov ax,ALLOCATE
  379.  int 21h
  380.  jnc msb
  381.  cmp ax,8   ; insufficient memory
  382.  jz ms1
  383.  
  384. msb:
  385.  mov bx,1800h  ; got our request
  386.  jmp ms2
  387.  
  388. ms1:
  389.  push bx
  390.  mov ax,ALLOCATE
  391.  int 21h   ; so ask for less
  392.  jnc msc
  393.  jmp report_bad  ; still fouled up?
  394.  
  395. msc:
  396.  pop bx
  397.  
  398. ms2:
  399.  mov cs:txtseg,ax
  400.  mov es,ax   ; now have allocated total space
  401.  mov dx,0
  402.  mov ax,bx
  403.  mov cx,3
  404.  div cx   ; divide by three
  405.  dec ax   ; safety factor
  406.  mov cs:space,ax
  407.  mov bx,ax
  408.  shl bx,1   ; multiply by 2
  409.  mov ax,SETBLOCK  ; shrink our total space
  410.  int 21h
  411.  jnc ms2a
  412.  jmp report_bad  ; get out if error after all this
  413.  
  414. ms2a:
  415.  mov bx,cs:space
  416.  mov ax,ALLOCATE  ; allocate second block
  417.  int 21h
  418.  jnc ms3
  419.  jmp report_bad
  420.  
  421. ms3:
  422.  mov cs:comseg,ax
  423.  mov bx,cs:space  ; get 1/3 of paragraphs
  424.  mov cl,4
  425.  shl bx,cl   ; times 16 = bytes available
  426.  dec bx   ; sub 2 for safety
  427.  dec bx
  428.  mov cs:comspace,bx  ; com file put here in either
  429.  inc bx   ; routine.
  430.  inc bx
  431.  shl bx,1   ; times 2 = text space
  432.  dec bx
  433.  dec bx
  434.  mov cs:txtspace,bx  ; hex file always in this one.
  435.  mov ax,cs:txtspace  ; [bp-2]  structure for easy access
  436.      ;   to end of space.
  437.  push ax   ;   Valid in either routine.
  438.  mov ax,cs:comspace  ; [bp-4]
  439.  push ax
  440.  mov ax,cs   ; don't use blocks    yet, have
  441.  mov ds,ax   ; to do file setup.
  442.  mov es,ax
  443.  jmp open_files
  444.  
  445. memory_setup endp
  446.  
  447. write_hc proc near
  448.  assume ds:nothing  ; universal write to file routine.
  449.  push cx   ; Saves registers used in time
  450.  push bx   ; critical loops, provides safe
  451.  push ds   ; error exits. Most of the errors
  452.  push es   ; in this program will come from
  453.  pop ds   ; disk, so take care here.
  454.  mov dx,0
  455.  mov cx,di
  456.  mov bx,cs:handle2  ; assume file already open for write
  457.  mov ax,WRITEFILE
  458.  int 21h
  459.  jnc whc1
  460.  push cs
  461.  pop ds
  462.  mov si,offset arg2  ; lots of messages for foul ups
  463.  call print
  464.  call crlf
  465.  shl ax,1
  466.  mov si,offset error
  467.  add si,ax
  468.  mov dx,[si]
  469.  mov ax,PRINTSTRING
  470.  int 21h
  471.  jmp bad_input  ; bad_input tidies up mess.
  472.  
  473. whc1:
  474.  cmp di,ax
  475.  jnz wh_full
  476.  mov ax,0
  477.  add cs:f_size,di
  478.  adc cs:f_size+2,ax
  479.  mov di,0
  480.  pop ds
  481.  pop bx
  482.  pop cx
  483.  ret
  484.  
  485. wh_full:
  486.  mov si,offset cs:disk_full ; if disk is full,
  487.  call print
  488.  call crlf
  489.  call free_memory
  490.  mov bx,cs:handle2
  491.  mov ax,CLOSEFILE  ; close file,
  492.  int 21h
  493.  jnc wh_full2
  494.  jmp report_bad
  495.  
  496. wh_full2:
  497.  push cs
  498.  pop ds
  499.  mov dx,offset arg2
  500.  mov ax,DELETEFILE  ; then delete it from disk.
  501.  int 21h   ; save user some time.
  502.  jnc wh_full3
  503.  jmp report_bad
  504.  
  505. wh_full3:
  506.  mov dx,offset cs:cancelled
  507.  jmp report_abort
  508.  
  509. write_hc endp
  510.  
  511. hcread proc near
  512.      ; universal read from file routine.
  513.  push bx   ; just slight differences for
  514.  mov cx,cs:txtspace  ; com->hex and hex<-com.
  515.  push cx
  516.  jmp read_input
  517.  
  518. hcread endp
  519.  
  520. chread proc near
  521.  
  522.  push bx
  523.  mov cx,cs:comspace
  524.  push cx
  525.  jmp read_input
  526.  
  527. chread endp
  528.  
  529. read_input proc near
  530.  
  531.  mov bx,cs:handle1
  532.  mov dx,0
  533.  mov ax,READFILE
  534.  int 21h   ; read from file
  535.  jnc ri_ok
  536.  push ax   ; if we come back with the
  537.  push cs   ; carry flag set, things didn't
  538.  pop ds   ; go allright, so we had better
  539.  mov si,offset arg1  ; not continue
  540.  call print
  541.  call crlf
  542.  mov bx,cs:handle2
  543.  mov ax,CLOSEFILE  ; close 2
  544.  int 21h
  545.  call free_memory
  546.  mov dx,offset arg2
  547.  mov ax,DELETEFILE  ; delete
  548.  int 21h
  549.  mov dx,offset cs:cancelled
  550.  mov ax,PRINTSTRING
  551.  int 21h
  552.  pop ax
  553.  jmp report_bad
  554.  
  555. ri_ok:
  556.  
  557.  cmp ax,0   ; EOF and no checksum?
  558.  jnz ri1   ; special case for HEX file.
  559.  cmp byte ptr cs:com_to_hex,TRUE   ; its all right to not have
  560.  jz ri1   ; a checksum, but theres no
  561.  jmp no_hc_checksum  ; sense in heading back to
  562.      ; the process loop.
  563. ri1:
  564.  mov si,ax
  565.  mov byte ptr [si],0ffh ; set last byte to ff for check
  566.  pop cx
  567.  pop bx
  568.  mov si,0
  569.  cmp ax,cx   ; all read in?
  570.  jb ri_done
  571.  
  572.  ret
  573.  
  574. ri_done:
  575.  mov byte ptr cs:all_read,TRUE  ; set flag indicating no more
  576.  cmp byte ptr cs:com_to_hex,TRUE  ; reading required
  577.  jnz ri_hc
  578.  mov cs:comspace,ax  ; store maxbytes all over
  579.  mov [bp-4],ax
  580.  mov cx,ax
  581.  ret
  582.  
  583. ri_hc:
  584.  mov cs:txtspace,ax
  585.  mov [bp-2],ax
  586.  mov cx,ax
  587.  ret
  588.  
  589. read_input endp
  590.  
  591.  
  592. open_files proc near
  593.  
  594.  
  595.  mov ax,cs
  596.  mov ds,ax
  597.  mov cx,BUFSIZE*2  ; make args lowercase
  598.  mov si,offset arg1
  599.  
  600. of2:
  601.  mov al,[si]
  602.  cmp al,'A'
  603.  jl of3
  604.  cmp al,'Z'
  605.  ja of3
  606.  add al,32
  607.  mov [si],al
  608.  
  609. of3:
  610.  inc si
  611.  loop of2
  612.  
  613.  cmp byte ptr cs:numargs,2    ; have to find which is hex
  614.  jz of4
  615.  jmp find_files
  616.  
  617. of4:
  618.  mov si,offset arg1
  619.  
  620. of4a:
  621.  
  622.  mov al,[si]
  623.  cmp al,'.'
  624.  jz of5
  625.  inc si
  626.  cmp al,0  ; end of arg and no extension
  627.  jnz of4a
  628.  mov byte ptr cs:com_to_hex,TRUE ; better be true
  629.  jmp of10
  630.  
  631. of5:
  632.  inc si
  633.  mov al,[si]
  634.  cmp al,'h'          ; is this hex?
  635.  jz of6
  636.  mov byte ptr cs:com_to_hex,TRUE ; set flag
  637.  jmp of10
  638.  
  639. of6:
  640.  mov byte ptr cs:com_to_hex,FALSE  ; first arg is HEX,
  641.  jmp open         ; so its hex_to_com.
  642.  
  643. of10:
  644.  mov si,offset arg2
  645.  
  646. of11:
  647.  mov al,[si]
  648.  cmp al,'.'          ; look for .
  649.  jz of12
  650.  inc si
  651.  cmp al,0  ; end of arg and no extension
  652.  jnz of11
  653.  call free_memory
  654.  mov dx,offset need_hex   ; two args, one has to be hex
  655.  jmp report_abort
  656.  
  657. of12:
  658.  inc si
  659.  mov al,[si]
  660.  cmp al,'h'          ; here this better be HEX
  661.  jz of13
  662.  call free_memory ; otherwise bye bye
  663.  mov dx,offset need_hex
  664.  jmp report_abort
  665.  
  666. of13:
  667.  jmp open
  668.  
  669. find_files:   ; only one arg supplied, have to find which
  670.  mov si,offset arg1
  671.  mov di,offset arg2
  672.  
  673. ff1:
  674.  mov al,[si]  ; search for extension
  675.  mov [di],al
  676.  cmp al,'.'
  677.  jz ff2
  678.  inc si
  679.  inc di
  680.  cmp al,0  ; no ext means com_to_hex
  681.  jnz ff1
  682.  
  683.  dec di
  684.  
  685.  mov byte ptr cs:com_to_hex,TRUE ; make second arg HEX
  686.  mov al,'.'
  687.  mov [di],al
  688.  
  689. ff1a:
  690.  mov al,'h'
  691.  inc di
  692.  mov [di],al
  693.  mov al,'e'
  694.  inc di
  695.  mov [di],al
  696.  mov al,'x'
  697.  inc di
  698.  mov [di],al
  699.  mov al,0
  700.  inc di
  701.  mov [di],al
  702.  jmp open
  703.  
  704. ff2:
  705.  inc si
  706.  inc di
  707.  mov cs:temp,di
  708.  mov al,[si]
  709.  cmp al,'h'          ; is it hex?
  710.  jz ff3
  711.  
  712.  mov byte ptr cs:check_exe,FALSE ; no, make second HEX
  713.  mov byte ptr cs:com_to_hex,TRUE
  714.  dec di
  715.  jmp ff1a
  716.  
  717. ff3:
  718.  mov byte ptr cs:check_exe,TRUE
  719.  mov byte ptr cs:com_to_hex,FALSE
  720.  
  721. open:  ; we now have 2 args, with one possibly waiting
  722.   ; for COM or EXE extension
  723.  assume ds:cseg
  724.  mov ax,cs
  725.  mov ds,ax
  726.  cmp byte ptr cs:com_to_hex,TRUE
  727.  jz openc
  728.  jmp openh
  729.  
  730. openc:
  731.  mov dx,offset arg1
  732.  mov ax,OPENFILE ; for reading
  733.  clc
  734.  int 21h
  735.  jnc opcok
  736.  mov si,offset arg1
  737.  call print
  738.  call free_memory
  739.  jmp report_bad
  740.  
  741. opcok:
  742.  mov cs:handle1,ax
  743.  
  744.  mov dx,offset arg2
  745.  mov cx,0  ; normal file attribute
  746.  mov ax,CREAT
  747.  clc
  748.  int 21h
  749.  jnc opcok1
  750.  mov si,offset arg2 ; print which file caused error
  751.  call print
  752.  call free_memory
  753.  jmp report_bad
  754.  
  755. opcok1:
  756.  mov cs:handle2,ax ; otherwise store handle
  757.  jmp com_hex  ; do com->hex
  758.  
  759. openh:
  760.  mov dx,offset arg1
  761.  mov ax,OPENFILE ; for reading
  762.  clc
  763.  int 21h
  764.  jnc ophok
  765.  mov si,offset arg1
  766.  call print
  767.  jmp report_bad
  768.  
  769. ophok:
  770.  mov cs:handle1,ax
  771.  cmp byte ptr cs:check_exe,TRUE
  772.  jz opcheck
  773.  jmp ophok1
  774.  
  775. opcheck:
  776.  assume ds:nothing ; here we read in first block
  777.  mov ax,cs:txtseg ; then look for the  MZ
  778.  mov ds,ax  ; footprint of an EXE file.
  779.  
  780.  call hcread
  781.  
  782. opcheck2:
  783.  mov si,0
  784.  
  785. opchl:
  786.  mov dl,[si]  ; ignor all leading stuff until
  787.  cmp dl,13  ; first convertible bytes
  788.  jz opch1
  789.  cmp dl,10
  790.  jz opch1
  791.  cmp dl,' '
  792.  jz opch1
  793.  cmp dl,';'
  794.  jnz opch4
  795.  call op_find
  796.  
  797.  jmp opchl
  798.  
  799. opch1:
  800.  inc si
  801.  jmp opchl
  802.  
  803. opch4:
  804.  
  805.  inc si
  806.  mov dh,[si]
  807.  call hexbin  ; hexbin comes back with carry set
  808.  jnc opch5  ; if it can't convert input.
  809.  jmp opcom  ; can't make sense,    so make    com
  810.  
  811. opch5:
  812.  mov al,dl
  813.  inc si
  814.  mov dx,[si]
  815.  call hexbin
  816.  jnc opch6
  817.  jmp opcom
  818.  
  819. opch6:
  820.  mov dh,dl
  821.  mov dl,al
  822.  push cs
  823.  pop ds
  824.  cmp dx,5a4dh ; MZ are the first two bytes of an EXE file.
  825.  jz opexe  ; make ext EXE
  826.  jmp opcom  ; make ext COM
  827.  
  828. op_find:
  829.  inc si  ; simple ignor
  830.  mov dl,[si]  ; we can convert files downloaded
  831.  cmp dl,13  ; without line feeds.
  832.  jnz op_find
  833.  inc si
  834.  mov dl,[si]
  835.  cmp dl,10
  836.  jnz opf1
  837.  inc si
  838.  
  839. opf1:
  840.  ret
  841.  
  842. opexe:
  843.  mov si,cs:temp
  844.  mov al,'e'
  845.  mov [si],al
  846.  inc si
  847.  mov al,'x'
  848.  mov [si],al
  849.  inc si
  850.  mov al,'e'
  851.  mov [si],al
  852.  inc si
  853.  mov al,0
  854.  mov [si],al
  855.  jmp ophok1
  856.  
  857. opcom:
  858.  mov si,cs:temp
  859.  mov al,'c'
  860.  mov [si],al
  861.  inc si
  862.  mov al,'o'
  863.  mov [si],al
  864.  inc si
  865.  mov al,'m'
  866.  mov [si],al
  867.  inc si
  868.  mov al,0
  869.  mov [si],al
  870.  
  871. ophok1:
  872. ; now have second arg for sure
  873.  mov dx,offset arg2
  874.  mov cx,0
  875.  mov ax,CREAT ; CREATE a file
  876.  clc
  877.  int 21h
  878.  jnc ophok2
  879.  mov si,offset arg2
  880.  call print
  881.  call free_memory
  882.  jmp report_bad
  883.  
  884. ophok2:
  885.  mov cs:handle2,ax
  886.  
  887. open_files endp
  888.  
  889. hex_com  proc near
  890.  
  891.  mov ax,cs:txtseg ; finally use our memory set-up
  892.  mov ds,ax
  893.  mov ax,cs:comseg ; DS always input, ES always output
  894.  mov es,ax
  895.     ; first check if data already in buffer
  896.  
  897.  mov al,byte ptr cs:check_exe
  898.  cmp al,TRUE
  899.  jnz hc1
  900.  jmp hc_read
  901.  
  902. hc1:
  903.  call hcread
  904.  
  905. hc_read:
  906.  mov si,0
  907.  mov di,0
  908.  mov bx,0  ; checksum stored in BX, don't lose it
  909.  mov cx,cs:txtspace
  910.  
  911. hcloop:
  912.  mov dl,[si]  ; most used routine, process stuff till
  913.  cmp dl,13  ; out of space in buffer or EOF
  914.  jz hclcont
  915.  cmp dl,10
  916.  jz hclcont
  917.  cmp dl,' '
  918.  jz hclcont
  919.  cmp dl,';'
  920.  jz hcl8
  921.  
  922. hcl1:
  923.  cmp dl,0ffh  ; if we run out of data,
  924.  jz hcl6
  925.  
  926. hcl2:
  927.  inc si
  928.  
  929. hcl3:
  930.  mov dh,[si]
  931.  cmp dh,0ffh
  932.  jz hcl5
  933.  call hexbin  ; if nothing else works it must be data
  934.  jc bad_i
  935.  
  936. hcl4:
  937.  mov es:[di],dl ; store
  938.  xor dh,dh
  939.  add bx,dx  ; checksum
  940.  and bx,07ffh
  941.  inc di
  942.  cmp di,[bp-4] ; output buffer size in [bp-4]
  943.  jz hcl7
  944.  
  945. hclcont:
  946.  inc si
  947.  
  948.  jmp hcloop
  949.  
  950. hcl5:
  951.  push dx
  952.  call hcread  ; if we fall through here, we need more
  953.  pop dx
  954.  jmp hcl3  ; data, then go back for more loop.
  955.  
  956. hcl6:
  957.  call hcread  ; go dig up some more.
  958.  jmp hcloop
  959.  
  960. hcl7:
  961.  call write_hc ; write buffer when full.
  962.  jmp hclcont
  963.  
  964. hcl8:
  965.  sub cx,si  ; checksum uses cx
  966.  call checksum ; may or may not return to here
  967.  jmp hclcont
  968. bad_i:
  969.  push cs
  970.  pop ds
  971.  mov si,offset arg1
  972.  call print     ; if hexbin comes back invalid
  973.  call crlf     ; abort routine and clean up.
  974.  mov dx,offset not_hex
  975.  mov ax,PRINTSTRING
  976.  int 21h
  977.  
  978. bad_input:
  979.  call free_memory ; restores memory to original,
  980.  mov bx,cs:handle1 ; closes both files,
  981.  mov ax,CLOSEFILE ; then deletes output file.
  982.  int 21h
  983.  jnc bi1
  984.  jmp report_bad
  985.  
  986. bi1:
  987.  mov bx,cs:handle2
  988.  mov ax,CLOSEFILE
  989.  int 21h
  990.  jnc bi2
  991.  jmp report_bad
  992.  
  993. bi2:
  994.  push cs
  995.  pop ds
  996.  mov dx,offset cs:arg2
  997.  mov ax,DELETEFILE
  998.  int 21h  ; delete output file
  999.  jnc bi3
  1000.  jmp report_bad
  1001.  
  1002. bi3:
  1003.  mov dx,offset cs:cancelled
  1004.  jmp report_abort
  1005.  
  1006.  
  1007. hex_com endp
  1008.  
  1009. checksum proc near
  1010. ;
  1011. ; si points to ';'
  1012. ; check for checksum, else read to end of line
  1013. ;
  1014.  push es
  1015.  push di
  1016.  mov ax,cs
  1017.  mov es,ax
  1018.  cld
  1019.  mov dh,0
  1020.  inc si
  1021.  cmp dl,0ffh  ; its possible to hit end of buffer
  1022.  jnz ch0  ; during this, so we need to check
  1023.  call hcread  ; and cope.
  1024.  
  1025. ch0:
  1026.  mov dl,[si]  ; we can convert ;checksum
  1027.  cmp dl,'c'          ;             or ;CHECKSUM
  1028.  jnz ch0a
  1029.  mov di,offset cs:lchksum+1
  1030.  jmp ch1
  1031.  
  1032. ch0a:
  1033.  cmp dl,'C'
  1034.  jnz ch_read_end
  1035.  mov di,offset cs:uchksum+1
  1036.  
  1037. ch1:
  1038.  cmpsb   ; compare till the bitter end.
  1039.  jnz ch_read_end
  1040.  dec cx
  1041.  cmp cx,0
  1042.  jnz ch2
  1043.  call hcread
  1044.  
  1045. ch2:
  1046.  inc dh
  1047.  cmp dh,8
  1048.  jnz ch1
  1049.  pop di
  1050.  pop es  ; this is it.
  1051.  pop ax  ; discard return, no longer need hcloop
  1052.  jmp dhc1  ; found checksum word
  1053.  
  1054. ch_read_end:
  1055.  dec si
  1056.  
  1057. cre1:
  1058.  mov dl,[si]  ; no find, so read till end
  1059.  cmp dl,13  ; of line and go back to hcloop
  1060.  jz cre_back
  1061.  inc si
  1062.  dec cx
  1063.  cmp cx,0
  1064.  jnz cre2
  1065.  call hcread
  1066.  
  1067. cre2:
  1068.  jmp cre1
  1069.  
  1070. cre_back:
  1071.  pop di
  1072.  pop es
  1073.  ret
  1074.  
  1075. dhc1:
  1076.  mov dl,[si]  ; ignor leading blanks
  1077.  cmp dl,' '
  1078.  jnz dhc2
  1079.  inc si
  1080.  dec cx
  1081.  cmp cx,0
  1082.  jnz dhc1
  1083.  call hcread  ; get more text if end of buffer
  1084.  jmp dhc1
  1085.  
  1086. dhc2:
  1087.  push cx  ; convert ASCII checksum to binary
  1088.  mov ax,0
  1089.  mov cx,10
  1090.  mov dh,0
  1091.  
  1092. dhc3:
  1093.  mov dl,[si]  ; read numbers until no number
  1094.  cmp dl,'0'
  1095.  jae dhc4
  1096.  jmp dhc_found
  1097.  
  1098. dhc4:
  1099.  cmp dl,'9'
  1100.  jbe dhc5
  1101.  jmp dhc_found
  1102.  
  1103. dhc5:
  1104.  push dx  ; the old multiply by ten routine
  1105.  mov dx,0  ; to convert ASCII number string
  1106.  mul cx  ; into binary
  1107.  pop dx
  1108.  sub dl,'0'
  1109.  add ax,dx
  1110.  inc si
  1111.  pop cx
  1112.  dec cx  ; CX still has the loop or buffer count
  1113.  cmp cx,0
  1114.  jnz dhc5a
  1115.  call hcread  ; oops, ran out of buffer, so fill up again.
  1116.  
  1117. dhc5a:
  1118.  push cx
  1119.  mov cx,10
  1120.  jmp dhc3
  1121.  
  1122. dhc_found:
  1123.  pop cx  ; got a checksum.
  1124.  cmp bx,ax  ; does checksum check out?
  1125.  jz dhc_ok
  1126.  mov si,offset cs:chk_bad
  1127.  call print
  1128.  call crlf
  1129.  jmp dhc_cont ; report either way.
  1130.  
  1131. dhc_ok:
  1132.  mov si,offset cs:chk_ok
  1133.  call print
  1134.  call crlf
  1135.  jmp dhc_cont
  1136.  
  1137. no_hc_checksum:
  1138.  mov si,offset chk_no  ; its OK not to have a checksum,
  1139.  call print  ; but we're more confident    if its there
  1140.  call crlf
  1141.  
  1142. dhc_cont:
  1143.  call write_hc ; write final section.
  1144.  
  1145. dhcok1:
  1146.  mov bx,cs:handle2
  1147.  mov ax,CLOSEFILE
  1148.  int 21h  ; close outfile
  1149.  jnc dhcok2
  1150.  call free_memory ; hope things don't bomb after all this
  1151.  jmp report_bad
  1152.  
  1153. dhcok2:
  1154.  mov bx,cs:handle1
  1155.  mov ax,CLOSEFILE
  1156.  int 21h  ; close infile
  1157.  jnc dhcok3
  1158.  call free_memory
  1159.  jmp report_bad
  1160.  
  1161. dhcok3:
  1162.  
  1163.  call free_memory ; give back memory
  1164.  mov si,offset cs:arg2
  1165.  call print
  1166.  call crlf
  1167.  call print_file_size
  1168.  mov dx,offset cs:msuccess  ; print a reassuring message
  1169.  jmp report_abort ; clean up and go home.
  1170.  
  1171. checksum  endp
  1172.  
  1173. print_file_size proc near
  1174.     ; print out file size bytes using
  1175.  assume ds:cseg  ; bcd table
  1176.  push cs
  1177.  pop ds
  1178.  mov bx,offset cs:bcd0
  1179.  mov si,0
  1180.  mov ax,cs:f_size
  1181.  mov dx,1
  1182.  
  1183. pfs1:
  1184.  test ax,dx  ; test bits
  1185.  jz pfs2
  1186.  call add_bcd  ; add in bcd if so
  1187.  
  1188. pfs2:
  1189.  add si,5  ; bump pointer
  1190.  cmp dx,8000h ; test for end
  1191.  jz pfs3
  1192.  shl dx,1  ; get next test
  1193.  jmp pfs1
  1194.  
  1195. pfs3:
  1196.  mov ax,cs:f_size+2 ; get hi word
  1197.  mov dx,1  ; start again
  1198.  
  1199. pfs4:
  1200.  test ax,dx
  1201.  jz pfs5
  1202.  call add_bcd
  1203.  
  1204. pfs5:
  1205.  add si,5
  1206.  cmp dx,0100h ; only need up to 16meg
  1207.  jz pfs6
  1208.  shl dx,1
  1209.  jmp pfs4
  1210.  
  1211. pfs6:
  1212.  mov si,offset bf_size
  1213.  call print_bcd ; print out result
  1214.  mov si,offset cs:f_len
  1215.  call print  ; print 'bytes recorded'
  1216.  call crlf
  1217.  ret   ; back
  1218.  
  1219. add_bcd:
  1220.  push si
  1221.  push ax
  1222.  mov di,offset bf_size  ; point to bcd storage
  1223.  mov cx,5  ; its five bytes long
  1224.  clc   ; clear carry to start
  1225.  
  1226. ab1:
  1227.  mov al,[bx+si] ; get byte
  1228.  adc al,[di]  ; add
  1229.  daa   ; adjust for bcd
  1230.  mov [di],al  ; store
  1231.  inc si  ; bump
  1232.  inc di
  1233.  dec cx  ; check
  1234.  jnz ab1  ; leave if done
  1235.  
  1236.  pop ax
  1237.  pop si
  1238.  ret
  1239.  
  1240. print_bcd:
  1241.  add si,4  ; go to end (high byte)
  1242.  mov cx,5  ; set up for five total
  1243.  mov ax,0  ; AH used to check first zero
  1244.  
  1245. pbd1:
  1246.  mov dl,[si]  ; get byte
  1247.  cmp ah,1  ; see if we've started to print
  1248.  jz pbd2  ; if so don't    skip
  1249.  cmp dl,0  ; else check if zero
  1250.  jz pbd3  ; and skip if so
  1251.  
  1252. pbd2:
  1253.  mov dh,dl  ; copy
  1254.  push cx  ; don't lose place
  1255.  push ax
  1256.  mov cl,4  ; bcd:( 12 hex. = 12 dec. for example)
  1257.  shr dl,cl  ; shr makes ( 01 )
  1258.  cmp ah,1  ; if printing print
  1259.  jz pbd2a
  1260.  cmp dl,0  ; else see if zero
  1261.  jz pbd2c  ; and don't print if    so
  1262.  
  1263. pbd2a:
  1264.  add dl,30h  ; make ASCII ( '1' )
  1265.  push dx
  1266.  mov ax,DISPLAYOUT ; print
  1267.  int 21h
  1268.  pop dx
  1269.  
  1270. pbd2c:
  1271.  mov dl,dh  ; get copy ( 12 )
  1272.  and dl,0fh  ; mask    ( 02 )
  1273.  add dl,30h  ; make ASCII ( '2' )
  1274.  mov ax,DISPLAYOUT ; print
  1275.  int 21h
  1276.  pop ax
  1277.  pop cx
  1278.  mov ah,1  ; now set flag to print rest
  1279.  
  1280. pbd3:
  1281.  dec si
  1282.  dec cx
  1283.  jnz pbd1  ; loop till done.
  1284.  ret
  1285.  
  1286. print_file_size endp
  1287.  
  1288.  
  1289. com_hex  proc near
  1290. ; files are open, nothing read in yet.
  1291.  
  1292.  mov ax,cs:txtseg ; do everything in reverse
  1293.  mov es,ax
  1294.  mov ax,cs:comseg ; remember in-buffer = DS
  1295.  mov ds,ax  ;   out-buffer = ES
  1296.  mov si,0
  1297.  mov di,0
  1298.  mov bx,0
  1299.  
  1300.  call chread
  1301.  mov ah,0  ; use for line length
  1302.     ; need to put crlf every 32(64) bytes.
  1303. chloop:
  1304.  mov dl,[si]  ; this is much simpler than hex->com
  1305.  mov dh,0  ; because there is no extraneous stuff
  1306.  add bx,dx  ; chloop is time-critical, cause
  1307.  and bx,07ffh ; its 90% of routine
  1308.  call binhex
  1309.  mov es:[di],dx
  1310.  inc ah
  1311.  cmp ah,32
  1312.  jnz ch2a
  1313.  inc di
  1314.  inc di
  1315.  cmp di,[bp-2] ; out of space in text buffer?
  1316.  jnz ch1a
  1317.  call write_hc ; clean it out.
  1318.  
  1319. ch1a:
  1320.  mov ax,0a0dh ; crlf
  1321.  mov es:[di],ax
  1322.  mov ah,0
  1323.  
  1324. ch2a:
  1325.  inc si
  1326.  inc di
  1327.  inc di
  1328.  cmp di,[bp-2] ; this buffer is an even number so
  1329.  jnz ch3  ; we don't need to worry about
  1330.  push ax  ; odd addresses like in hex->com
  1331.  call write_hc ; [bp-2] = always text buffer
  1332.  pop ax  ; [bp-4] = always com buffer
  1333.  
  1334. ch3:
  1335.  loop chloop
  1336.  
  1337.  cmp byte ptr cs:all_read,TRUE  ; if its all read in
  1338.  jz ch4      ; we are almost done.
  1339.  push ax
  1340.  call chread  ; else read next and continue
  1341.  pop ax  ; chread will set CX to length of data
  1342.  cmp cx,0  ; tried to read past EOF?
  1343.  jz ch4  ; then we're finished with loop.
  1344.  jmp chloop
  1345.  
  1346. ch4:
  1347.  push ax
  1348.  call write_hc ; clear buffer to make life simpler
  1349.  pop ax
  1350.  cmp ah,0  ; just did EOL?
  1351.  jz ch4a
  1352.  mov ax,0a0dh ; skip extra crlf
  1353.  mov es:[di],ax
  1354.  inc di
  1355.  inc di
  1356.  
  1357. ch4a:
  1358.  mov ax,0a0dh
  1359.  mov es:[di],ax
  1360.  inc di
  1361.  inc di
  1362.  
  1363.  push cs  ; write out ;checksum
  1364.  pop ds
  1365.  mov si,offset cs:lchksum
  1366.  mov cx,10
  1367.  cld
  1368.  
  1369.  rep movsb  ; ;checksum
  1370.  
  1371.  mov ax,bx  ; compute ASCII representation of
  1372.  mov dx,0  ; checksum and make it neat.
  1373.  mov cx,1000
  1374.  div cx
  1375.  mov ch,0
  1376.  cmp ax,0  ; no 1000s?
  1377.  jz ch5
  1378.  add al,30h  ; ASCII 0
  1379.  mov es:[di],al
  1380.  inc di
  1381.  mov ch,1
  1382.  
  1383. ch5:
  1384.  mov ax,dx  ; remainder
  1385.  mov cl,100
  1386.  div cl
  1387.  cmp ch,1
  1388.  jz ch5a
  1389.  cmp al,0  ; no 100s?
  1390.  jz ch6
  1391.  
  1392. ch5a:
  1393.  add al,30h
  1394.  mov es:[di],al
  1395.  inc di
  1396.  mov ch,1
  1397.  
  1398. ch6:
  1399.  mov al,ah
  1400.  mov ah,0
  1401.  mov cl,10
  1402.  div cl
  1403.  cmp ch,1
  1404.  jz ch6a
  1405.  cmp al,0  ; no 10s?
  1406.  jz ch7
  1407.  
  1408. ch6a:
  1409.  add al,30h
  1410.  mov es:[di],al
  1411.  inc di
  1412.  
  1413. ch7:
  1414.  mov al,ah  ; must print at least one number
  1415.  add al,30h
  1416.  mov es:[di],al
  1417.  inc di
  1418.  mov ax,0a0dh ; crlf
  1419.  mov es:[di],ax
  1420.  inc di
  1421.  inc di
  1422.  mov al,EOF  ; Ctrl-Z
  1423.  mov es:[di],al
  1424.  inc di
  1425.  
  1426.  call write_hc
  1427.  jmp dhcok1  ; close and finish
  1428.  
  1429.  
  1430. com_hex  endp
  1431.  
  1432. messages proc near
  1433.  
  1434. himess db '[[hc]]  MS-DOS 2.+ hexconverter,',13,10
  1435.  db '  v1.4 by Marty Smith.',13,10,13,10,'$'
  1436.  
  1437.  
  1438. need_hex db 'One of files must be .HEX',13,10,'$'
  1439. not_hex  db 'Not a hex format file.',13,10,'$'
  1440. lchksum  db ';checksum '   ; 10 bytes
  1441. uchksum  db ';CHECKSUM '
  1442. msuccess db 'Successfully created!',13,10,'$'
  1443. chk_ok  db 'Checksum verified.',0
  1444. chk_bad  db 'Checksums different,',13,10
  1445.   db 'file possibly bad.',0
  1446. chk_no  db 'No checksum    found.',0
  1447. disk_full db 'Disk full.',0
  1448. cancelled db 'Please check file.',13,10,'$'
  1449. f_len  db ' bytes recorded.',0
  1450. must_be_20 db '** Must be running DOS 2.+ **',13,10,'$'
  1451. do_cr  db 13,10,'$'
  1452.  
  1453. ; DOS error returns we may encounter, others return 'unknown error'
  1454.  
  1455. err0 db 'unknown error.',13,10,'$'
  1456. err1 db 'bad function number.',13,10,'$'
  1457. err2 db 'file not found.',13,10,'$'
  1458. err3 db 'path not found.',13,10,'$'
  1459. err4 db 'too many files.',13,10,'$'
  1460. err5 db 'access    denied.',13,10,'$'
  1461. err6 db 'invalid handle.',13,10,'$'
  1462. err7 db 'memory    blocks damaged.',13,10,'$'
  1463. err8 db 'insufficient memory.',13,10,'$'
  1464. err9 db 'bad memory block address.',13,10,'$'
  1465. err12 db 'bad access code.',13,10,'$'
  1466. err15 db 'bad drive specified.',13,10,'$'
  1467. err17 db 'not same device.',13,10,'$'
  1468. err18 db 'no more files.',13,10,'$'
  1469.  
  1470. error dw err0,err1,err2,err3,err4,err5,err6,err7,err8,err9,err0
  1471.  dw err0,err12,err0,err0,err15,err0,err17,err18
  1472.  
  1473. f_size  dw 0  ; dword file size
  1474.   dw 0
  1475. txtseg  dw 0  ; memory management
  1476. txtspace dw 0
  1477. comseg  dw 0
  1478. comspace dw 0
  1479. space  dw 0  ; temp for figuring workspace
  1480. handle1  dw 0  ; file handles
  1481. handle2  dw 0
  1482. temp  dw 0  ; scratch
  1483. oldstack dw 0  ; store orig. stack ptr.
  1484.  
  1485. numargs  db 0  ; command line number of args.
  1486. arg1  db BUFSIZE dup ('    ')  ; plenty of space for args
  1487. arg2  db BUFSIZE dup ('    ')  ; and PATHs
  1488. com_to_hex db 0  ; flags
  1489. check_exe db 0
  1490. all_read db 0
  1491.  
  1492. bf_size  db 5 dup (0)  ; bcd file size
  1493.  
  1494. bcd0 db 01h,00h,00h,00h,00h ; five byte bcd power of 2
  1495.  db 02h,00h,00h,00h,00h ; 2^0 to 2^24
  1496.  db 04h,00h,00h,00h,00h ; for showing file size
  1497.  db 08h,00h,00h,00h,00h ; up to 16meg MS-DOS limit
  1498.  db 16h,00h,00h,00h,00h
  1499.  db 32h,00h,00h,00h,00h
  1500.  db 64h,00h,00h,00h,00h
  1501.  db 28h,01h,00h,00h,00h
  1502.  db 56h,02h,00h,00h,00h
  1503.  db 12h,05h,00h,00h,00h
  1504.  db 24h,10h,00h,00h,00h
  1505.  db 48h,20h,00h,00h,00h
  1506.  db 96h,40h,00h,00h,00h
  1507.  db 92h,81h,00h,00h,00h
  1508.  db 84h,63h,01h,00h,00h
  1509.  db 68h,27h,03h,00h,00h
  1510.  db 36h,55h,06h,00h,00h
  1511.  db 72h,10h,13h,00h,00h
  1512.  db 44h,21h,26h,00h,00h
  1513.  db 88h,42h,52h,00h,00h
  1514.  db 76h,85h,04h,01h,00h
  1515.  db 52h,71h,09h,02h,00h
  1516.  db 04h,43h,19h,04h,00h
  1517.  db 08h,86h,38h,08h,00h
  1518.  db 16h,72h,77h,16h,00h
  1519.  
  1520. ; doc at end so it can be used for stack space.
  1521.  
  1522. doc db 'Converts HEX format files to COM,EXE or    BIN.',13,10
  1523.  db '  or COM,EXE or BIN files to HEX.',13,10,13,10
  1524.  db '  Type: >hc in_file [out_file]',13,10,13,10
  1525.  db 'If    TWO files are entered, ONE of them MUST    be HEX,',13,10
  1526.  db '  i.e. xxx.HEX xxx.COM = Hex to Com, xxx.EXE xxx.HEX = Exe    to Hex.',13,10,13,10
  1527.  db 'If    ONE file is entered, the following occurs:',13,10
  1528.  db '    If the first file has no extension, or it is non-HEX:',13,10
  1529.  db '        A second file is made in HEX format, with an extension .HEX.',13,10
  1530.  db '    If the first file has a    .HEX extension:',13,10
  1531.  db '        The    program    will automatically provide a .COM or .EXE extension,',13,10
  1532.  db '        depending on file type.'
  1533.  db '$'
  1534.  
  1535. messages endp
  1536.  
  1537. cseg ends   ; that's all folks
  1538.  end start
  1539.  
  1540.  
  1541.  
  1542.  
  1543. Access: