Source file: /~heha/hs/dos/dosmisc.zip/SRC/HD.ASM

;Programm HD (HexDump) mit:
;- Pipe-Möglichkeit
;- Auswahl der Darstellungsbreite
;- Angabe eines Start- und Endoffsets
;- Auswahl der ASCII-Dump-Ausgabe (betreffs Zeichen <20h und >80h)
;- Möglichkeit der Binärausgabe, CAT-Ersatz

		include	prolog.asm
	JUMPS
		cld
		mov	si,81h
Parse2:		lodsb
		cmp	al,'+'
		je	Offs
		cmp	al,'-'
		je	hxwidth
		cmp	al,'/'
		je	sonst
		cmp	al,' '
		je	Parse2
		mov	bx,0		;StdIn
		jc	StdIn
		dec	si		;auf Dateiname, Z=0
		mov	dx,si
Parse3:		lodsb
		cmp	al,21h
		jnc	Parse3
		mov	[byte si-1],0
		mov	ax,3d00h	;Datei zum Lesen öffnen
		int	21h
		jc	errF01		;Nicht gefunden
		mov	bx,ax
		jmp	normal
StdIn:
		mov	dx,offset NewInt23
		mov	ax,2523h	;Set Int23
		int	21h
normal:
		mov	dx,[wo LOW FilePos]
		mov	cx,[wo HIGH FilePos]
		mov	ax,4200h	;Zeiger setzen
		int	21h
		jc	errm01
		BTST	[switches],10h
		jz	NextLine
		mov	[Bytes],8000h	;große Brocken spucken
NextLine:
		mov	cx,[Bytes]
		mov	dx,ofs buffer
		DOS	3fh		;lesen
		jc	errm01
		push	bx
		 call	DecAX		;korrigiert AX für den Fall der
					;Endadressenüberschreitung
		 jc	ende
		 or	ax,ax		;Null? (Dateiende?)
		 jz	ende
		 test	[by LOW switches],10h	;Plain ByteOutput?
		 jz	hexo
		 mov	cx,ax		;wirkliche Zeichenzahl
		 mov	dx,ofs buffer
		 jmp	bcat
hexo:
		 mov	[LineLen],ax
		 mov	di,ofs OutBuf
		 call	OutPos
		 call	HexDmp
		 call	AscDmp
		 call	crlf
		 mov	cx,di
		 mov	dx,ofs OutBuf
		 sub	cx,dx
bcat:		 mov	bx,1		;stdout
		 DOS	40h		;Handle-schreiben
		pop	bx
		mov	ax,[bytes]
		add	[wo LOW FilePos],ax
		adc	[wo HIGH FilePos],0
		jmp	NextLine
ende:		xor	al,al		;errorlevel 0
exi:
		DOS	4ch

errm01:		jmp	errm
errf01:		jmp	errf

offs:
		call	InPos
		jc	errp
		STL	[FilePos],dx,bx	;Neues Makro! Store Long!
		cmp	[byte si],'-'	;Endadresse?
		jnz	Parse201
		inc	si
		call	InPos
		jc	errp
		mov	[word EndPos],bx
		mov	[word EndPos+2],dx
Parse201:	jmp	Parse2

hxwidth:
		call	InPos
		jc	ErrP
		or	dx,dx
		jnz	ErrP
		or	bx,bx
		jz	ErrP
		cmp	bx,0e000h	;Zu groß?
		jnc	ErrP
		mov	[Bytes],bx
		jmp	Parse2
sonst:
		lodsb			;Buchstabe
		call	UpCase
		cmp	al,'H'
		je	Help
		cmp	al,'?'
		je	Help
		dec	si
		call	InPos
		jc	ErrP
		or	dx,dx
		jnz	ErrP
		mov	[Switches],bx
		jmp	Parse2
ErrP:
		PRINT	msgP
exiCrlf:
		push	ax
		call	crlf
		pop	ax
		jmp	exi
ErrM:
		xchg	bx,ax		;Errorlevel
		Print	msgE
		mov	ax,bx
		call	AHEX
		mov	ax,bx
		jmp	exiCrlf
errF:
		push	ax
		push	dx
		Print	msgF
		pop	dx
		mov	di,dx
		mov	al,0
		repne	scasb		;Länge ermitteln (strlen)
		lea	cx,[di-1]
		sub	cx,dx
		mov	bx,1
		DOS	40h		;Dateiname ausgeben
errf1:		pop	ax
		jmp	exiCrlf

Help:
		PRINT	msgH		;Hilfeseite
		jmp	exiCrlf
proc HexDmp
		mov	cx,[bytes]
		mov	bx,[LineLen]
		mov	si,ofs buffer
		xor	dx,dx
loop1:		inc	dx
		dec	bx
		js	NoDigits
		lodsb
		call	AHEX
		jmp	digits
NoDigits:	call	dSPAC		;2 Leerzeichen ausgeben
digits:		mov	al,20h
		BTST	[switches],8	;Bit4
		jnz	ospac
		BTST	dx,7
		jnz	ospac
		cmp	bx,2
		jl	ospac
		mov	al,'-'
ospac:		stosb
		loop	loop1
		ret
endp

proc AscDmp
		call	SPAC
		mov	cx,[LineLen]
		mov	si,offset buffer
loop2:		lodsb
		cmp	al,80h
		jc	tasc1
		BTST	[switches],1
		jz	tasc11
		and	al,7fh		;"Herunterziehen"
tasc11:		test	[switches],2
		jz	tasc1
		mov	al,'.'		;Füllzeichen HOHE ASCII
tasc1:		cmp	al,20h
		jc	tasc2
		cmp	al,7fh
		jnz	tascok
tasc2:		BTST	[switches],4
		jnz	tasc4
tasc3:		cmp	al,7
		jc	tascok
		cmp	al,11
		jc	tasc4		;7..10: Spezialbehandlung
		cmp	al,13
		jz	tasc4
		cmp	al,26		;EOF wegen MSDOS
		jz	tasc4
		cmp	al,27
		jz	tasc4
		cmp	al,7fh
		jnz	tascok
tasc4:		mov	al,'_'		;Füllzeichen TIEFE ASCII
tascok:		stosb
		loop	loop2
		ret
endp

DecAX:		;Dekrementiert AX, CY=1: wir sind HINTER dem File-Ende!
		LDL	cx,bx,[EndPos]
		sub	bx,[wo LOW FilePos]
		sbb	cx,[wo HIGH FilePos]
		jnz	decax1
		cmp	ax,bx
		jc	decax2
		mov	ax,bx		;neue Zeichenzahl
decax2:		clc
decax1:		ret

	;Testet ob Zeichen eine Ziffer, al:= al-'0'!
IsDigit:	sub	al,'0'
		jc	ID1
		cmp	al,10
		cmc
ID1:		ret

	;AL:= Hexäquivalent zum ASCII-Zeichen AL, CY=1: Keine HexZahl!
HexNibble:	call	UpCase
		call	IsDigit
		jnc	hn1
		sub	al,17
		jc	hn1
		add	al,10
		cmp	al,10h
		cmc
hn1:		ret

	;Zweistelliges Hex-Byte einlesen nach [di]
InHexByte:	push	cx
		mov	al,[si]
		call	HexNibble
		jc	IHB1		;Fehler 1.Zeichen
		inc	si
		mov	cl,4
		mov	ch,al
		shl	ch,cl
		mov	cl,al		;aufheben für 1-Zeichen-Hexzahlen!
		mov	al,[si]
		call	HexNibble
		jc	IHB2
		or	al,ch
		inc	si
		jmp	IHB3
IHB2:		mov	al,cl		;alte Tetrade!
IHB3:		stosb
IHD1:		clc
IHB1:		pop	cx
		ret

	;8stellige Hexzahl (Dateiposition) einlesen nach DX-BX (und AX)
InHexDD:	push	cx
		mov	al,[si]
		call	HexNibble
		jc	IHB1		;Schon 1. Zeichen fehlerhaft!
		xor	bx,bx
		xor	dx,dx
IHD2:		mov	cx,4
IHD3:		shl	bx,1
		rcl	dx,1
		jc	IHB1		;Zahl zu groß
		loop	IHD3
		or	bl,al
		inc	si
		mov	al,[si]
		call	HexNibble
		jnc	IHD2
		mov	ax,bx
		jmp	IHD1		;clc, pop cx, ret


InPos:	;wertet Dezpräfix '#' aus
		cmp	[byte si],'#'
		jne	InHexDD
		inc	si
	;Dezimalzahl nach DX-AX einlesen, Quelle=[si]
InDez:		push	bx
		mov	al,[si]
		call	IsDigit
		jc	IND1
		xor	bx,bx
		xor	dx,dx
InD2:		 push	si di cx
		 xchg	si,bx
		 xchg	di,dx
		 mov	bl,al
		 xor	bh,bh
		 xor	dx,dx
		 mov	cx,10
InD3:		  add	bx,si
		  adc	dx,di
		  loop	InD3
		 pop	cx di si
		jc	IND1		;Fehler: Überlauf!
		inc	si
		mov	al,[si]
		call	IsDigit
		jnc	InD2
		clc
		xchg	ax,bx
IND1:		pop	bx
		ret

OutPos:
		LDL	dx,ax,[FilePos]
		call	dxax
dspac:          call	spac
spac:		mov	al,' '
		stosb
		ret

dxax:	;Hexausgabe DX-AX ohne Bindestrich
		call	axhx0
axhx0:		xchg	dx,ax
axhx:	;Hexausgabe AX
		call	ahex0
ahex0:		xchg	ah,al
ahex:	;Hexausgabe AL
		push	ax		;Werte erhalten
		push	cx
		mov	cl,4		;oberes Nibble auf Bit 3...0
		shr	al,cl		; schieben
		pop	cx
		call	ahex1
		pop	ax
ahex1:		and	al,0fh
		add	al,90h		;Hex -> ASCII
		daa
		adc	al,40h
		daa
		stosb
		ret

crlf:		mov	ax,0a0dh
		stosw
		ret

UpCase:	 ;al:= UpCase(al) ohne hohe Zeichen
		cmp	al,'a'
		jb	UpCas1
		cmp	al,'z'
		ja	UpCas1
		and	al,not 20h
UpCas1:		ret

NewInt23:
		iret

FilePos		dd	0
EndPos		dd	7fffffffh
Bytes		dw	16;		{Maximallänge einer Zeile in Bytes}
Switches	dw	0

msgE:		db	'DOS error $'
msgP:		db	'Command line error. For help type /?$'
msgF:		db	'Can''t find or open file $'
msgH:
    db 'HexDump 1.02 (haftmann#software): HexViewer		++ Freeware ++',nl
    db 'Usage:',nl
    db 'hd [+offset[-end]] [-width] [/mode] [file]',nl,10
    db 'If no file is given HD uses stdin (Please use CAT instead of TYPE!)',nl
    db 'offset, end and width are hexnumbers or decnumbers with prefix ''#''',nl
    db 'mode is a sum-byte of following:',nl
    db '1: Do reset bit7 of ascii >7fh',nl
    db '2: Do mark ascii >7fh as ''.''',nl
    db '4: Do mark ALL ascii <20h as ''_'', else #7#8#9#10#13#26#27 only',nl
    db '8: Do not type ''-'' into hexdump',nl
    db '16: Do output plain bytes',nl
    db '$'

LineLen		dw	?;		{Momentane Länge der Zeile in Bytes}
OutBuf		db	1024 dup (?)

Buffer:
		endc
Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded