;*; Created on 17-Sep-92 at 12:36 AM by James A. Jarboe I V; edit time: 0:40:40
; 	
; TBXHSH - Demonstrates bug in TOOLBX  hashing routine,
;	   and a possible solution. Although  actually all it shows
;	   is that the newer hashing routine hashes this sample differently.
;
;  Rob/Ken,
;
;	After mystic revelations, d/FIX, and 5 cups of expresso,
;       the following program will demonstrate how TOOLBX handles it's
; 	hashing of each ESP field.
;	The TBXHSH: routine is what appears to be ESP's hashing routine.
;	The IRVHSH: routine was taken from JOBSTS.LIT by Irv Bromberg
;        and was used to compute a hash of each display line and not output
;	 and consume I/O time if no changes where to made to the display 
;	 for a dynamic display of a job's JCB.
;
;	The results I get using Ken's magic strings are:	 
;
; ESP hashing.
;
;	String  Decimal hash    Octal hash
;--------------------------------------------------
;	16906 = 84280356	501402044
;	16834 = 84280356	501402044
;	36906 = 84411492	502002144
;
; IRV's Hashing.
;
;	16906 = 84321787	501522773
;	16834 = 84338650	501563732
;	36906 = 84468088	502160570
;
; Which does show that the newer hashing routine works differently.
; As to if it is more accurate and has a lessor redundency
; is another question. 
;
; [100] 17-Sep-92 by James A. Jarboe IV  


	SEARCH	SYS
	SEARCH	SYSSYM


DEFINE	PRTTAB	ROW, COL
	MOVW	#<ROW_8.+COL>, D1
	TCRT
ENDM

	VMAJOR	=	1
	VMINOR	=	0
	VEDIT	=	100.		; 17-Sep-92


; Demonstrate TOOLBX hashing problem.
;
START:
	PHDR	-1,0,PH$REE!PH$REU

	PRTTAB	-1,0			; Clear screen
	TYPECR	<Testing TOOLBX Hashing routine to demonstrate bug.>
	CRLF				; Bump line

	TYPECR	<String   Hash            Hash >
	CRLF

	LEA	A6, TEST1		; Index first string.
	MOV	#TSIZ1, D6		; Set number of chars.
	CALL	DO.IT			; Do hashing and display.

	LEA	A6, TEST2		; Index second string.
	MOV	#TSIZ2, D6		; Set number of chars.
	CALL	DO.IT			; Do hashing and display.

	LEA	A6, TEST3		; Index control string.
	MOV	#TSIZ3, D6		; Set number of chars.
	CALL	DO.IT			; Do hashing and display.

	CRLF
	TYPECR	<Now, try IRV's HASHing>
	CRLF

	LEA	A6, TEST1		; Index first string.
	MOV	#TSIZ1, D6		; Set number of chars.
	CALL	DO.ME			; Do hashing and display.

	LEA	A6, TEST2		; Index second string.
	MOV	#TSIZ2, D6		; Set number of chars.
	CALL	DO.ME			; Do hashing and display.

	LEA	A6, TEST3		; Index control string.
	MOV	#TSIZ3, D6		; Set number of chars.
	CALL	DO.ME			; Do hashing and display.

	EXIT				; Finito!


; Do hashing and display.
; 
; Incoming:
;		D6 =: Number of chars to hash
;		A6 -> Indexes buffer of string to hash.
; Outgoing:
;		D6 =: Hash total of string.
;		A6 -> Indexes end of buffer.
;
DO.IT:
	PUSH	A6			; Save buffer address.
	CALL	TBXHSH			; Call hashing routine.
	MOV	D6, D1			; Save hash total
	POP	A6			; Restore buffer address.
	TTYL	@A6			; Output string.
	TYPE	< = >			; Output seperator.
	DCVT	0, OT$TRM		; Output in decimal.
	TAB				;  
	OCVT	0,OT$TRM		; Output in current base.
	CRLF				; Bump line.
	RTN				; Return to caller.


; Do hashing and display. Using another hashing method.
; 
; Incoming:
;		D6 =: Number of chars to hash
;		A6 -> Indexes buffer of string to hash.
; Outgoing:
;		D6 =: Hash total of string.
;		A6 -> Indexes end of buffer.
;
DO.ME:
	PUSH	A6			; Save buffer address.
	CALL	IRVHSH			; Call hashing routine.
	MOV	D6, D1			; Save hash total
	POP	A6			; Restore buffer address.
	TTYL	@A6			; Output string.
	TYPE	< = >			; Output seperator.
	DCVT	0, OT$TRM		; Output in decimal.
	TAB				; 
	OCVT	0,OT$TRM		; Output in current base.
	CRLF				; Bump line.
	RTN				; Return to caller.



; What appears to be TOOLBX's Hashing routine.
;
; Incoming:
;		D6 =: Number of characters to hash.
;
;		A6 -> Indexes buffer to hash.
;
; Outgoing:
;		D6 =: Hash total of field.
;		A6 -> Indexes end of buffer.

TBXHSH:

; It appears that the first step is to save the number of char in a field
; in the high byte of the low word and then save the total ASCII value
; of the string in the low byte of the low word, then save all of that
; in the high word.

	MOV	D6, D7			; Save number of chars.
	BEQ	99$			; Opps..none there..quit.
	SUB	#1, D7			; Dbf adjust count.
	ASL	D6, #8.			; Mul * 256. 
	SAVE	A6, D7			; Save address of buffer & count.
10$:	ADDB	(A6)+, D6		; Add ascii value byte to number.
	DBF	D7, 10$			; For all chars.

; The following code represents what appears to be adding in 
; the ESP field's Read and Write security level.
;
;  Which for most of the time is a constant unless it is changed in
;  an ESP screen. While changing this value would create a different
;  hash total than a previous one with different field security levels, it
;  would create the same hash total on the next pass if the values for Read
;  and Write security remain the same. Soooo for this example we assume
;  that the Read and Write security is 0. Thus we comment it out because
;  any number + 0 is still that number.

;;	ADDB    22(A3), D6	        ; Add read security value.
;;	ADDB    23(A3), D6	        ; Add Write security value.

	REST	A6, D7			; Restore buffer address & count.
	SWAP	D6			; Swap Words.

20$:	CLR	D1			; Preclear hasher.
	MOVB	(A6)+, D1		; Get next char.
	XORW	D1, D6			; Shake it.
	ROLW	D6, #1			; Roll it.
	DBF	D7, 20$			; And try again.
99$:	RTN				; Return to caller.


;IRVHSH:
;
; Part of this hashing routine was taken from JOBSTS.LIT by Irv Bromberg
; off the AMUS Newtork. It always appeared to work without any problems.
; I am sure some mathmematicion could verify it's redundency occurance of
; likely hash matches for different string values.
;
; Incoming:
;		D6 =: Number of characters to hash.
;
;		A6 -> Indexes buffer to hash.
;
; Outgoing:
;		D6 =: Hash total of field.
;		A6 -> Indexes end of buffer.


IRVHSH:
	MOV	D6, D7			; Save number of chars.
	BEQ	99$			; Opps..none there..quit.
	SUB	#1, D7			; Dbf adjust count.
	ASL	D6, #8.			; Mul * 256.
	SAVE	A6, D7			; Save address of buffer & count.
10$:	ADDB	(A6)+, D6		; Add ascii value byte to number.
	DBF	D7, 10$			; For all chars.

;;	ADDB    22(A3), D6	        ; Add read security value.
;;	ADDB    23(A3), D6	        ; Add Write security value.

	REST	A6, D7			; Restore buffer address & count.
	SWAP	D6			; Swap Words.

	CLR	D1			; Preclear hasher.

; Here's a modified adaptation of Irv's hashing routine. Actually he only
; stored and checked the resulting word value. Assuming that ESP stores this
; as a long word, we just tack it on to what is done above since it appears
; that the TOOLBX version does about the same thing.
;
20$:	MOVB	(A6)+, D1		; Get next char.
	LSLW	D1, #8.			; Shift to high byte.
	XORW	D1, D6			; Rattle.
	PUSH	D7			; Save current char count.
	MOVW	#<8.-1>, D7		; Set number of bits (dbf adj).

30$:	TSTW	D6			; Is hash word negative?
	BMI	40$			;  Yes..
	LSLW	D6, #1			; No..shift.
	BR	50$			; Try next bits.

40$:	LSLW	D6, #1			; Shift.
	XORW	#^O10041, D6		; Rattle.

50$:	DBF	D7, 30$			; Do all bits.
	POP	D7			; Restore current count.
	DBF	D7, 20$			; Do all chars.

99$:	RTN				; Return to caller.


; Strings
;
TEST1:	ASCII	/16906/ 		; Ken's magic string 1.
TSIZ1=.-TEST1				; Size of string.
	BYTE	0			; 

TEST2:	ASCII	/16834/			; Ken's magic string 2.
TSIZ2=.-TEST2				; Size of string.
	BYTE	0			; 

TEST3:	ASCII	/36906/			; Control string.
TSIZ3=.-TEST3				; Size of string.
	BYTE	0			; 
	EVEN

	END