@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
stdin      equ     0000h           ;standard input device
stdout     equ     0001h           ;standard output device
stderror   equ     0002h           ;standard error output device
param_c    equ     0080h
buf_length equ     512             ;input buffer size

;======================================================
cls macro                            ; proc l”scht den bildschirm
           mov ax,0003h              ; ohne parameter aufrufen
           int 010h
#em

zeigbild   macro
           mov dx,offset #1
           mov ah,09
           int 021h
#em

con1       macro            ;converts byte in al to hex string
           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     #1, al
           pop     ax              ;recover character
           and     al, 0fh         ;mask off high nybble
           xlat                    ;translate low nybble to hex
           mov     #2, al       ;and stuff it into buffer
           pop     dx
           pop     bx
#em
           jmp com2data
baddos     db  beep cr lf
           db  'Dieses Programm ben”tigt DOS >= 2.00'
           db  cr,lf '$'
rcx        db  'rcx',13,10,'$'
cr_lf      db  cr,lf,'$'
title_msg  db  cr,lf
benutzfehl db  '                 COM-DATA    Version 1.5', cr,lf,lf,lf
           db  '*  Kein *  Copyright (c) 1988 by MS    '
           db  '**  public - domain **',cr,lf,lf
           db  'Dieses Programm erzeugt txt-Files aus com-Programmen.'
           db  cr,lf,lf,lf
           db  'aufruf : com-data < ein.com > aus.txt ',cr,lf,lf
           db  'Mit * aus.txt * kann dann DEBUG gefttert werden      '
           db  'Beispiel : DEBUG < aus.txt', cr,lf,lf
           db  'DEBUG erstellt  ** OUT.COM **',cr,lf,lf,lf
tmse       db  cr,lf
           db  beep,cr,lf,lf, 'Falsche Benutzung  *  ABBRUCH$'
schreib    db  'nout.com',13,10
           db  'w',13,10
           db  'q',13,10,13,10,'$'
linenum    dw  100h
table      db  '0123456789ABCDEF'
cur_pos    dw  offset first_hex       ;current position in line

com2data:  cls
           cmp b[param_c],00
           jne co1
           zeigbild benutzfehl
           mov ah,04ch
           int 021h
co1:       call init            ;check dos, print title
           call doit            ;run conversion
           call cleanup         ;final processing
           zeigbild rcx
           add linenum,16
           mov ax, linenum      ;print line number
           xchg ah,al
           push ax
           xor ah,ah
           con1 cur1,cur11
           pop ax
           xchg ah,al
           con1 cur2,cur22
           mov al,'$'
           mov cur33,al
           zeigbild cur1
           zeigbild cr_lf
           zeigbild schreib
           mov ah,04ch
           int 021h             ;return to dos

init:      mov ah, @dosver     ;what dos are we under?
           int 021h
           cmp al,2            ;dos 2.0 or over?
           jae a1              ;yes, skip
           zeigbild baddos
           pop ax              ;reset stack
           mov ah,04ch
           int 021h              ;and exit
a1:        mov ah,@write      ;send title message
           mov bx,stderror    ;to stderror
           mov cx,(offset tmse - offset title_msg)
           mov dx, offset title_msg
           int 021h
           ret

doit:      call wlinenb
do1:       mov ah,@read       ;read
           mov bx,stdin       ;from stdin
           mov cx,buf_length  ;one buffer's worth
           mov dx,offset in_buf
           int 021h
           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

wlinenb:   push ax              ;save machine state
           push bx
           push cx
           push dx
           push di
           mov al,' '         ;blank out old number
           mov di,offset cur1
           mov cx,5
           rep
           stosb
           mov ax, linenum      ;print line number
           xchg ah,al
           push ax
           xor ah,ah
           con1 cur1,cur11
           pop ax
           xchg ah,al
           con1 cur2,cur22
           pop di
           pop dx
           pop cx
           pop bx
           pop ax
           ret

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

output:    cmp w[cur_pos],offset eol  ;is the line full?
           jb o1                      ;no, skip
           call newline               ;yes, dump buffer
o1:        call send_byte             ;print  value of byte
           add cur_pos,3              ;bump line positions used
           ret                        ;and exit

newline:   push ax                   ;save state
           push dx
           mov ah,@prnstr            ;print line
           mov dx,offset out_buf
           int 021h
           mov cur_pos,offset first_hex   ;reset pointer
           add linenum,16
           call wlinenb
           pop dx                         ;restore state
           pop ax
           ret                            ;and exit


cleanup:   cmp cur_pos,offset first_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 cvoll                      ;special case: full line
           sub cx,offset out_buf         ;normal case: incomplete line
           sub cx,6                      ;don't use ',' or next field
           jmp short cfertig

cvoll:     mov cx,(offset eol - offset out_buf)
cfertig:   mov dx,offset out_buf
           int 021h
           mov ah,@prnstr                ;print cr/lf to end line
           mov dx,offset eol
           int 021h
cexit:     ret

out_buf    db 'e'              ;5 digit line number
cur1       db ' '
cur11      db ' '
cur2       db ' '              ;8 hex bytes per line
cur22      db ' '
cur33      db '  '
first_hex  db      '00 '       ;first hex field
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00 '
           db      '00'
eol:       db cr, lf, '$'       ;end of output line
in_buf     db 0
