;*; 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