'===========================================================================
' Subject: UPDATE 32 BIT CRC                  Date: Year of 1991 (00:00:00)
'  Author: Mark Lamb                          Code: TASM, MASM             
'  Origin: UPDATE,32,BIT,CRC                Packet: ASMCODE.ABC
'===========================================================================
;**********************************************************************

;       UpdCRC32 --- Routine to quickly update a 32 bit CRC
;
;Copyright (c) 1991, HAIL Associates
;Written by Mark Lamb
;
;   Code is under the table. :)
;
;   My thanks and recognition to Gary S. Brown for his Pascal CRC-32
; routine. Although it was just a starting point, really.
;
;   The table is precalculated for speed. The polynomial is
;      
; X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
;
;   Note that it's backwards. I pulled this table from a ZModem
; implementation and, apparently, ZModem builds its CRC's in reverse.
; I could have made it into a 'normal' CRC, I suppose, but as the most
; likely use for this routine (other than pattern matching, where the
; inversion of the CRC doesn't matter) is a ZModem implmentation, I did
; it the way ZModem does it.
;
;   I curse the day that I decided this would be a fun thing to do.
; Typing 256 32 bit numbers, in hex, triple checking, so much fun!
; Fortunately, my dear Mother did most of it.
;
;   You should be able to use this routine as-is for Microsoft BASIC,
; FORTRAN, and Pascal, or any language which adheres to the calling
; and return conventions of those languages.
;
;
;   Usage:  (In QuickBASIC)
;
;       Call UpdCRC32(Char%,CRC&)
;          
;           CRC& needs to be initialized to -1.
;
;   Or:
;       Declare Function UpdCRC32&(Char%,CRC&)
;       .
;       .
;       .
;       NewCRC& = UpdCRC32&(Char%,CRC&)
;
;**********************************************************************


    .Model Medium

    .Data

;Reference to the start of the table

CRCTable    label   byte

    dd  000000000h      ;0 thru 7
    dd  077073096h  
    dd  0ee0e612ch
    dd  0990951bah
    dd  0076dc419h
    dd  0706af48fh
    dd  0e963a535h
    dd  09e6495a3h

    dd  00edb8832h      ;8 thru 15
    dd  079dcb8a4h
    dd  0e0d5e91eh
    dd  097d2d988h
    dd  009b64c2bh
    dd  07eb17cbdh
    dd  0e7b82d07h
    dd  090bf1d91h

    dd  01db71064h      ;16 thru 23
    dd  06ab020f2h
    dd  0f3b97148h
    dd  084be41deh
    dd  01adad47dh
    dd  06ddde4ebh
    dd  0f4d4b551h
    dd  083d385c7h

    dd  0136c9856h      ;24 thru 31
    dd  0646ba8c0h
    dd  0fd62f97ah
    dd  08a65c9ech
    dd  014015c4fh
    dd  063066cd9h
    dd  0fa0f3d63h
    dd  08d080df5h

    dd  03b6e20c8h      ;32 thru 39
    dd  04c69105eh
    dd  0d56041e4h
    dd  0a2677172h
    dd  03c03e4d1h
    dd  04b04d447h
    dd  0d20d85fdh
    dd  0a50ab56bh

    dd  035b5a8fah      ;40 thru 47
    dd  042b2986ch
    dd  0dbbbc9d6h
    dd  0acbcf940h
    dd  032d86ce3h
    dd  045df5c75h
    dd  0dcd60dcfh
    dd  0abd13d59h

    dd  026d930ach      ;48 thru 55
    dd  051de003ah
    dd  0c8d75180h
    dd  0bfd06116h
    dd  021b4f4b5h
    dd  056b3c423h
    dd  0cfba9599h
    dd  0b8bda50fh

    dd  02802b89eh      ;56 thru 63
    dd  05f058808h
    dd  0c60cd962h
    dd  0b10be924h
    dd  02f6f7c87h
    dd  058684c11h
    dd  0c1611dabh
    dd  0b6662d3dh

    dd  076dc4190h      ;64 thru 71
    dd  001db7106h
    dd  098d220bch
    dd  0efd5102ah
    dd  071b18589h
    dd  006b6b51fh
    dd  09fbfe4a5h
    dd  0e8b8d433h

    dd  07807c9a2h      ;72 thru 79
    dd  00f00f934h
    dd  09609a88eh
    dd  0e10e9818h
    dd  07f6a0dbbh
    dd  0086d3d2dh
    dd  091646c97h
    dd  0e6635c01h

    dd  06b6b51f4h      ;80 thru 87
    dd  01c6c6162h
    dd  0856530d8h
    dd  0f262004eh
    dd  06c0695edh
    dd  01601a57bh
    dd  08208f4c1h
    dd  0f50fc457h

    dd  065b0d9c6h      ;88 thru 95
    dd  012b7e950h
    dd  08bbeb8eah
    dd  0fcb9887ch
    dd  062dd1ddfh
    dd  015da2d49h
    dd  08cd37cf3h
    dd  0fbd44c65h

    dd  04db26158h      ;96 thru 103
    dd  03ab551ceh
    dd  0a3bc0074h
    dd  0d4bb30e2h
    dd  04adfa541h
    dd  03dd895d7h
    dd  0a4d1c46dh
    dd  0d3d6f4fbh

    dd  04369e96ah      ;104 thru 111
    dd  0346ed9fch
    dd  0ad678846h
    dd  0da60b8d0h
    dd  044042d73h
    dd  033031de5h
    dd  0aa0a4c5fh
    dd  0dd0d7cc9h

    dd  05005713ch      ;112 thru 119
    dd  0270241aah
    dd  0be0b1010h
    dd  0c90c2086h
    dd  05768b525h
    dd  0206f85b3h
    dd  0b966d409h
    dd  0ce61e49fh

    dd  05edef90eh      ;120 thru 127
    dd  029d9c998h
    dd  060d09822h
    dd  0c7d7a8b4h
    dd  059b33d17h
    dd  02eb40d81h
    dd  067bd5c3bh
    dd  0c0ba6cadh     

    dd  0edb88320h      ;128 thru 135
    dd  09abfb3b6h
    dd  003b6e20ch
    dd  074b1d29ah
    dd  0ead54739h
    dd  09dd277afh
    dd  004db2615h
    dd  073dc1683h

    dd  0e3630b12h      ;136 thru 143
    dd  094643b84h
    dd  00d6d6a3eh
    dd  07a6a5aa8h
    dd  0e40ecf0bh
    dd  09309ff9dh
    dd  00a00ae27h
    dd  07d079eb1h

    dd  0f00f9344h      ;144 thru 151
    dd  08708a3d2h
    dd  01e01f268h
    dd  06906c2feh
    dd  0f762575dh
    dd  0806567cbh
    dd  0196c3671h
    dd  06e6b06e7h

    dd  0fed41b76h      ;152 thru 159
    dd  089d32be0h
    dd  010da7a5ah
    dd  067dd4acch
    dd  0f9b9df6fh
    dd  08ebeeff9h
    dd  017b7be43h
    dd  060608ed5h

    dd  0d6d6a3e8h      ;160 thru 167
    dd  0a1d1937eh
    dd  038d8c2c4h
    dd  04fdff252h
    dd  0d1bb67f1h
    dd  0a6bc5767h
    dd  03fb506ddh
    dd  048b2364bh

    dd  0d80d2bdah      ;168 thru 175
    dd  0af0a1b4ch
    dd  036034af6h
    dd  041047a60h
    dd  0df60efc3h
    dd  0a867df55h
    dd  0316e8eefh
    dd  04669be79h

    dd  0cb61b38ch      ;176 thru 183
    dd  0bc66831ah
    dd  0256fd2a0h
    dd  05268e236h
    dd  0cc0c7795h
    dd  0bb0b4703h
    dd  0220216b9h
    dd  05505262fh

    dd  0c5ba3bbeh      ;184 thru 191
    dd  0b2bd0b28h
    dd  02bb45a92h
    dd  05cb36a04h
    dd  0c2d7ffa7h
    dd  0b5d0cf31h
    dd  02cd99e8bh
    dd  05bdeae1dh

    dd  09b64c2b0h     ;192 thru 199
    dd  0ec63f226h
    dd  0756aa39ch
    dd  0026d930ah
    dd  09c0906a9h
    dd  0eb0e363fh
    dd  072076785h
    dd  005005713h

    dd  095bf4a82h      ;200 thru 207
    dd  0e2687a14h
    dd  07bb12baeh
    dd  00cb61b38h
    dd  092d28e9bh
    dd  0e5d5be0dh
    dd  07cdcefb7h
    dd  00bdbdf21h

    dd  086d3d2d4h      ;208 thru 215
    dd  0f1d4e242h
    dd  068ddb3f8h
    dd  01fda836eh
    dd  081be16cdh
    dd  0f6b9265bh
    dd  06fb077e1h
    dd  018b74777h
 
    dd  088085ae6h      ;216 thru 223
    dd  0ff0f6a70h
    dd  066063bcah
    dd  011010b5ch
    dd  08f659effh
    dd  0f862ae69h
    dd  0616bffd3h
    dd  0166ccf45h

    dd  0a00ae278h      ;224 thru 231
    dd  0d70dd2eeh
    dd  04e048354h
    dd  03903b3c2h
    dd  0a7672661h
    dd  0d06016f7h
    dd  04969474dh
    dd  03e6e77dbh

    dd  0aed16a4ah      ;232 thru 239
    dd  0d9d65adch
    dd  040df0b66h
    dd  037d83bf0h
    dd  0a9bcae53h
    dd  0debb9ec5h
    dd  047b2cf7fh
    dd  030b5ffe9h

    dd  0bdbdf21ch      ;240 thru 247
    dd  0cabac28ah
    dd  053b39330h
    dd  024b4a3a6h
    dd  0bad03605h
    dd  0cdd70693h
    dd  054de5729h
    dd  023d967bfh

    dd  0b3667a2eh      ;248 thru 255
    dd  0c4614ab8h
    dd  05d681b02h
    dd  02a6f2b94h
    dd  0640bbe37h
    dd  0c30c8ea1h
    dd  05a05df1bh
    dd  02d02ef8dh

    dd  04c494148h      ;256. Finis!

    .Code

    Public  UpdCRC32

UpdCRC32    Proc    Far

    push    bp      ;Set up the stack frame
    mov bp,sp
    push    si
    push    di

    mov bx,[bp+8]   ;Pull Char off the stack
    mov cx,[bx]     ;Incidentally shaving the upper 8 bits.
    xor ch,ch  
   
    mov bx,[bp+6]   ;Pull CRC off the stack into AX:DX
    mov ax,[bx]
    mov dx,[bx+2]

    ;Here, AX:DX holds CRC& and CL holds Char%
   
;Step #1:  Lookup = CRC xor Char

    xor cl,al       ;since it's one byte, and we don't use Char again,
                    ;this is all we need to do.

;Step #2:   TableVal = Table(Lookup)

    mov bx,cx       ;Multiply Lookup by 4 to figure offset of TableVal
    mov cl,2
    shl bx,cl
    mov cx,Offset CRCTable
    add bx,cx    
   
    mov si,[bx]     ;place Table(Lookup) into SI:DI
    mov di,[bx+2]
   
    ;At this point, AX:DX holds the old CRC, and the table value to XOR it to
    ;   (after it's been shifted) is in SI:DI
    ;   I put it into SI:DI becuz I'll use BX:CX inna minute


;Step #3:   sCRC = (CRC SHR 8) AND 00ffffffh

    mov cl,dh       ;look closely
    mov bh,dl       ;this actually works
    mov bl,ah       ;neat, huh?
    xor ch,ch

    ;Now, BX:CX holds the shifted CRC, and SI:DI holds the value to
    ;   XOR it with. Since I want to return the value in AX:DX, isn't
    ;   it nice that they happen to be free?

;Step #4:   CRC=TableVal XOR sCRC

    mov ax,bx       ;Copy the shifted CRC into AX:DX
    mov dx,cx

    xor ax,si       ;Do the XORing
    xor dx,di

;And we're done!

    pop di          ;We're done with these two, and the manual insists that
    pop si          ;you need to save 'em, so let's restore 'em.
   
    mov bx,[bp+6]   ;Place the contents of AX:DX into CRC&
    mov [bx],ax
    mov [bx+2],dx
   
    ;Notice that we're leaving the new CRC in AX:DX, as well as replacing
    ;   the old CRC value that was passed to us. This allows the routine
    ;   to be used either as a procedure or as a function, as well as being
    ;   convienient.
   
    pop bp          ;Clear the stack frame
    ret 4           ;Return over two params

UpdCRC32    EndP

    End
