           jmp com_bas

out_buf    db 0,0,0,0,0   ;5 digit line number
           db '  DATA'
           db '   &H'        ;8 hex bytes per line
f1_hex     db '00', comma      ;first hex field
           db '   &H00', comma
           db '   &H00', comma
           db '   &H00', comma
           db '   &H00', comma
           db '   &H00', comma
           db '   &H00', comma
           db '   &H00'
eol        db cr,lf,'$'       ;end of output line
table      db '0123456789ABCDEF'
cur_pos    dw offset f1_hex  ;current position in line
linenum    dw 10000            ;line number defaults to 10000
baddos     db beep, cr, lf
           db 'Dieses Programm ben”tigt DOS >= 2.00 ', cr, lf
           db cr, lf, '$'
tmsg       db cr, lf
           db 'COM-BAS Version 1.01', cr, lf
           db 'Kein Copyright (C) 1988   by ms     August 1988', cr, lf
           db 'Angelehnt an com2data.asm von D. Whitmann ( chasm )',cr,lf,lf
           db 'Erstellt mit    A86       PD - Assembler',cr,lf,lf,lf
           db 'COM-BAS.com  wandelt com-programme in DATA-Statements fr',cr,lf
           db 'BASIC-Programme um.',cr,lf,lf
           db 'AUFRUF : com-bas < ein.com > aus.txt',cr,lf,lf
tmsge      db 0
@dosver    equ     30h             ;get dos version #
@prnchr    equ     02h             ;print character
@prnstr    equ     09h             ;print string
@read      equ     3fh             ;read device
@write     equ     40h             ;write device
beep       equ     07h             ;bell character
lf         equ     0ah             ;line feed character
cr         equ     0dh             ;carrage return character
comma      equ     2ch             ;comma character
para_c     equ     B[80h]           ;number of chars in para_a
para_a     equ     [81h]           ;command line parameter text
stdin      equ     0000h           ;standard input device
stdout     equ     0001h           ;standard output device
stderror   equ     0002h           ;standard error output device
b_lang     equ     1024             ;input buffer size

com_bas:   CMP PARA_C,0
           JNE CO1
           CALL A1
           MOV AH,04CH
           INT 021H
CO1:       call init            ;check dos, print title
           call  doit            ;run conversion
           call  cleanup         ;final processing
           mov ah,04ch
           int 021h

init:      ;initialization routine
           mov     ah, @dosver     ;what dos are we under?
           int     21h
           cmp     al,2            ;dos 2.0 or over?
           jae     a1              ;yes, skip
           mov     ah, @prnstr     ;no, bitch
           mov     dx, offset baddos
           int     21h
           mov ah,04ch
           int 021h

a1:        mov     ah, @write      ;send title message
           mov     bx, stderror    ;to stderror
           mov     cx, (offset tmsge - offset tmsg)
           mov     dx, offset tmsg
           int     21h
           ret


doit:      ;convert infile to data
           call    w_linn   ;initialize output buffer
do1:       mov     ah, @read       ;read
           mov     bx, stdin       ;from stdin
           mov     cx, b_lang  ;one buffer's worth
           mov     dx, offset in_buf
           int     21h
           test    ax, ax          ;test for eof
           jz      done            ;no bytes? done
           mov     cx, ax          ;cx <== # of bytes read
           mov     si, offset in_buf

do2:       lodsb                   ;
           call    output          ;convert and send to stdout
           loop    do2             ;loop for # of bytes read
           jmp short    do1             ;then refill buffer

done:      ret


output:    ;convert byte in al to hex string
           cmp    w[cur_pos], offset eol  ;is the line full?
           jb      o1              ;no, skip
           call    newline         ;yes, dump buffer

o1:        call    send_byte       ;print hex value of byte
           add  cur_pos,8                    ;bump line positions used
           ret                     ;and exit

newline:   ;starts a new data line
           push    ax              ;save state
           push    dx              ; "
           mov     ah, @prnstr      ;print line
           mov     dx, offset out_buf
           int     21h
           mov    cur_pos, offset f1_hex    ;reset pointer
           add    w[linenum], 10                  ;bump line number
           call    w_linn                ;update line number
           pop     dx              ;restore state
           pop     ax
           ret                     ;and exit
;==========================================================
; w_linn
;
; updates the line number field of the output line buffer.
;==========================================================
w_linn:    push    ax              ;save machine state
           push    bx
           push    cx
           push    dx
           push    di
           mov     al, ' '         ;blank out old number
           mov     di, offset out_buf
           mov     cx, 5
           rep
           stosb
           mov     ax, linenum      ;print line number
           mov     bx, 10          ;set up divisor
           xor     cx, cx          ;clear counter
nxt_in:    xor     dx, dx          ;clear for division
           div     bx              ;dl <== ax mod 10
           or      dl, '0'         ;convert to ascii digit
           push    dx              ;save digit
           inc     cx              ;bump counter
           and     ax, ax          ;are we done?
           jnz     nxt_in          ;nope, keep going
           mov     di, offset out_buf  ;peel digits off stack

nxt_out:   pop     ax                  ;into number field
           stosb
           loop    nxt_out
           pop     di              ;restore state
           pop     dx
           pop     cx
           pop     bx
           pop     ax
           ret                     ;and exit

send_byte: push    bx
           push    dx
           push    ax
           mov     bx, offset table   ;point to xlat table
           and     al, 0f0h        ;mask off low nybble
           shr     al,1
           shr     al,1
           shr     al,1
           shr     al,1
           xlat                    ;translate to hex string
           mov     bp, cur_pos     ;and stuff it into buffer
           mov     [bp], al
           pop     ax              ;recover character
           and     al, 0fh         ;mask off high nybble
           xlat                    ;translate low nybble to hex
           mov     1[bp], al       ;and stuff it into buffer
           pop     dx
           pop     bx
           ret                     ;and return

cleanup:   cmp    w[cur_pos],offset f1_hex ;any unprinted chars?
           je      cexit                      ;no, exit
           mov     ah, @write
           mov     bx, stdout
           mov     cx,cur_pos                ;calculate # of chars
           cmp     cx, offset eol                ;to output
           je      cflin                ;special case: full line
           sub     cx, offset out_buf         ;normal case: incomplete line
           sub     cx, 6                      ;don't use ',' or next field
           jmp short    clready
cflin:     mov     cx, (offset eol - offset out_buf)


clready:   mov     dx, offset out_buf
           int     21h
           mov     ah, @prnstr                ;print cr/lf to end line
           mov     dx, offset eol
           int     21h
cexit:     ret

           org $+1
in_buf     db 0

