NAME: CRC32
CREATOR: ?
PB AUTHOR: Semen Matusovski, Wayne Diamond, Dave Navarro, Marc Sven Schulte
DESCRIPTION: A relatively fast algorithm that creates a 32-bit checksum. CRC32 is the most commonly-used 32-bit checksum algorithm.
NOTES: Four different implementations of CRC32.
SOURCE: http://www.powerbasic.com/support/forums/Archives/Archive-000002/HTML/20000801-7-000025.html
Viewing source from crc32.bas   15486 bytes   Last modified Wed, 20 September 2006

'################################################################
'CRC32, by Hans Joerg Viechtbauer and Marc Sven Schulte, 26th July 2003.
'Currently the fastest CRC32 implementation for PB.
FUNCTION CRC32(BYVAL Address AS DWORD, _
  BYVAL Length AS LONG, BYVAL Seed AS LONG) AS LONG
  ! MOV EBX, Seed
  ! XOR EBX, &HFFFFFFFF
  ! MOV ESI, Length
  ! CMP ESI, 0
  ! JZ  QuitLoop
  ! MOV EDI, Address
  ! XOR EAX, EAX
  NextByte:
  ! MOV AL, BL
  ! XOR AL, [EDI]
  ! MOV ECX, CrcTable[4*EAX]
  ! SHR EBX, 8
  ! XOR EBX, ECX
  ! INC EDI
  ! DEC ESI
  ! JNZ NextByte
  QuitLoop:
  ! XOR EBX, &HFFFFFFFF
  ! MOV Function, EBX
  EXIT FUNCTION
  CrcTable:
  ! dd &H000000000&, &H077073096&, &H0EE0E612C&, &H0990951BA&
  ! dd &H0076DC419&, &H0706AF48F&, &H0E963A535&, &H09E6495A3&
  ! dd &H00EDB8832&, &H079DCB8A4&, &H0E0D5E91E&, &H097D2D988&
  ! dd &H009B64C2B&, &H07EB17CBD&, &H0E7B82D07&, &H090BF1D91&
  ! dd &H01DB71064&, &H06AB020F2&, &H0F3B97148&, &H084BE41DE&
  ! dd &H01ADAD47D&, &H06DDDE4EB&, &H0F4D4B551&, &H083D385C7&
  ! dd &H0136C9856&, &H0646BA8C0&, &H0FD62F97A&, &H08A65C9EC&
  ! dd &H014015C4F&, &H063066CD9&, &H0FA0F3D63&, &H08D080DF5&
  ! dd &H03B6E20C8&, &H04C69105E&, &H0D56041E4&, &H0A2677172&
  ! dd &H03C03E4D1&, &H04B04D447&, &H0D20D85FD&, &H0A50AB56B&
  ! dd &H035B5A8FA&, &H042B2986C&, &H0DBBBC9D6&, &H0ACBCF940&
  ! dd &H032D86CE3&, &H045DF5C75&, &H0DCD60DCF&, &H0ABD13D59&
  ! dd &H026D930AC&, &H051DE003A&, &H0C8D75180&, &H0BFD06116&
  ! dd &H021B4F4B5&, &H056B3C423&, &H0CFBA9599&, &H0B8BDA50F&
  ! dd &H02802B89E&, &H05F058808&, &H0C60CD9B2&, &H0B10BE924&
  ! dd &H02F6F7C87&, &H058684C11&, &H0C1611DAB&, &H0B6662D3D&
  ! dd &H076DC4190&, &H001DB7106&, &H098D220BC&, &H0EFD5102A&
  ! dd &H071B18589&, &H006B6B51F&, &H09FBFE4A5&, &H0E8B8D433&
  ! dd &H07807C9A2&, &H00F00F934&, &H09609A88E&, &H0E10E9818&
  ! dd &H07F6A0DBB&, &H0086D3D2D&, &H091646C97&, &H0E6635C01&
  ! dd &H06B6B51F4&, &H01C6C6162&, &H0856530D8&, &H0F262004E&
  ! dd &H06C0695ED&, &H01B01A57B&, &H08208F4C1&, &H0F50FC457&
  ! dd &H065B0D9C6&, &H012B7E950&, &H08BBEB8EA&, &H0FCB9887C&
  ! dd &H062DD1DDF&, &H015DA2D49&, &H08CD37CF3&, &H0FBD44C65&
  ! dd &H04DB26158&, &H03AB551CE&, &H0A3BC0074&, &H0D4BB30E2&
  ! dd &H04ADFA541&, &H03DD895D7&, &H0A4D1C46D&, &H0D3D6F4FB&
  ! dd &H04369E96A&, &H0346ED9FC&, &H0AD678846&, &H0DA60B8D0&
  ! dd &H044042D73&, &H033031DE5&, &H0AA0A4C5F&, &H0DD0D7CC9&
  ! dd &H05005713C&, &H0270241AA&, &H0BE0B1010&, &H0C90C2086&
  ! dd &H05768B525&, &H0206F85B3&, &H0B966D409&, &H0CE61E49F&
  ! dd &H05EDEF90E&, &H029D9C998&, &H0B0D09822&, &H0C7D7A8B4&
  ! dd &H059B33D17&, &H02EB40D81&, &H0B7BD5C3B&, &H0C0BA6CAD&
  ! dd &H0EDB88320&, &H09ABFB3B6&, &H003B6E20C&, &H074B1D29A&
  ! dd &H0EAD54739&, &H09DD277AF&, &H004DB2615&, &H073DC1683&
  ! dd &H0E3630B12&, &H094643B84&, &H00D6D6A3E&, &H07A6A5AA8&
  ! dd &H0E40ECF0B&, &H09309FF9D&, &H00A00AE27&, &H07D079EB1&
  ! dd &H0F00F9344&, &H08708A3D2&, &H01E01F268&, &H06906C2FE&
  ! dd &H0F762575D&, &H0806567CB&, &H0196C3671&, &H06E6B06E7&
  ! dd &H0FED41B76&, &H089D32BE0&, &H010DA7A5A&, &H067DD4ACC&
  ! dd &H0F9B9DF6F&, &H08EBEEFF9&, &H017B7BE43&, &H060B08ED5&
  ! dd &H0D6D6A3E8&, &H0A1D1937E&, &H038D8C2C4&, &H04FDFF252&
  ! dd &H0D1BB67F1&, &H0A6BC5767&, &H03FB506DD&, &H048B2364B&
  ! dd &H0D80D2BDA&, &H0AF0A1B4C&, &H036034AF6&, &H041047A60&
  ! dd &H0DF60EFC3&, &H0A867DF55&, &H0316E8EEF&, &H04669BE79&
  ! dd &H0CB61B38C&, &H0BC66831A&, &H0256FD2A0&, &H05268E236&
  ! dd &H0CC0C7795&, &H0BB0B4703&, &H0220216B9&, &H05505262F&
  ! dd &H0C5BA3BBE&, &H0B2BD0B28&, &H02BB45A92&, &H05CB36A04&
  ! dd &H0C2D7FFA7&, &H0B5D0CF31&, &H02CD99E8B&, &H05BDEAE1D&
  ! dd &H09B64C2B0&, &H0EC63F226&, &H0756AA39C&, &H0026D930A&
  ! dd &H09C0906A9&, &H0EB0E363F&, &H072076785&, &H005005713&
  ! dd &H095BF4A82&, &H0E2B87A14&, &H07BB12BAE&, &H00CB61B38&
  ! dd &H092D28E9B&, &H0E5D5BE0D&, &H07CDCEFB7&, &H00BDBDF21&
  ! dd &H086D3D2D4&, &H0F1D4E242&, &H068DDB3F8&, &H01FDA836E&
  ! dd &H081BE16CD&, &H0F6B9265B&, &H06FB077E1&, &H018B74777&
  ! dd &H088085AE6&, &H0FF0F6A70&, &H066063BCA&, &H011010B5C&
  ! dd &H08F659EFF&, &H0F862AE69&, &H0616BFFD3&, &H0166CCF45&
  ! dd &H0A00AE278&, &H0D70DD2EE&, &H04E048354&, &H03903B3C2&
  ! dd &H0A7672661&, &H0D06016F7&, &H04969474D&, &H03E6E77DB&
  ! dd &H0AED16A4A&, &H0D9D65ADC&, &H040DF0B66&, &H037D83BF0&
  ! dd &H0A9BCAE53&, &H0DEBB9EC5&, &H047B2CF7F&, &H030B5FFE9&
  ! dd &H0BDBDF21C&, &H0CABAC28A&, &H053B39330&, &H024B4A3A6&
  ! dd &H0BAD03605&, &H0CDD70693&, &H054DE5729&, &H023D967BF&
  ! dd &H0B3667A2E&, &H0C4614AB8&, &H05D681B02&, &H02A6F2B94&
  ! dd &H0B40BBE37&, &H0C30C8EA1&, &H05A05DF1B&, &H02D02EF8D&
END FUNCTION
FUNCTION PBMAIN() AS LONG
  DIM buffer AS STRING, crc AS LONG
  buffer = "1234567890"
  crc = CRC32(STRPTR(buffer), LEN(buffer), crc)
  MSGBOX "CRC32: " & HEX$(crc, 8) & " (should be: 261DAEE5)"
END FUNCTION


'################################################################
'CRC32, by Wayne Diamond, 9th December 2002. For PBCC/PBDLL/PBWIN
'Usage: dwHash = CRC32(BYVAL STRPTR(Buffer), BYVAL LEN(Buffer))
FUNCTION CRC32(BYVAL dwOffset AS DWORD, BYVAL dwLen AS DWORD) AS DWORD
#REGISTER NONE
 ! mov esi, dwOffset  ;esi = ptr to buffer
 ! mov edi, dwLen     ;edi = length of buffer
 ! mov ecx, -1        ;ecx = -1
 ! mov edx, ecx       ;edx = -1
 nextbyte:           ';next byte from butter
 ! xor eax, eax       ;eax = 0
 ! xor ebx, ebx       ;ebx = 0
 ! lodsb              ;get next byte
 ! xor al, cl         ;xor al with cl
 ! mov cl, ch         ;cl = ch
 ! mov ch, dl         ;ch = dl
 ! mov dl, dh         ;dl = dh
 ! mov dh, 8          ;dh = 8
 nextbit:            ';next bit in the byte
 ! shr bx, 1          ;shift bits in bx right by 1
 ! rcr ax, 1          ;(rotate through carry) bits in ax by 1
 ! jnc nocarry        ;jump to nocarry if carry flag not set
 ! xor ax, &h08320    ;xor ax with 33568
 ! xor bx, &h0EDB8    ;xor bx with 60856
 nocarry:            ';if carry flag wasn't set
 ! dec dh             ;dh = dh - 1
 ! jnz nextbit        ;if dh isnt zero, jump to nextbit
 ! xor ecx, eax       ;xor ecx with eax
 ! xor edx, ebx       ;xor edx with ebx
 ! dec edi            ;finished with that byte, decrement counter
 ! jnz nextbyte       ;if edi counter isnt at 0, jump to nextbyte
 ! not edx            ;invert edx bits - 1s complement
 ! not ecx            ;invert ecx bits - 1s complement
 ! mov eax, edx       ;mov edx into eax
 ! rol eax, 16        ;rotate bits in eax left by 16 places
 ! mov ax, cx         ;mov cx into ax
 ! mov FUNCTION, eax  ;crc32 result is in eax
END FUNCTION
'################################################################
 
 
'==============================================================================
'  CRC32 - Calculate a CCITT 32-bit for a buffer
'  Copyright (c) 1998 by PowerBASIC, Inc.
'  This source will compile unmodified in PB/CC.  The Crc32 function itself
'  is compatible with PB/DLL 5.0.
'==============================================================================
FUNCTION PBCrc32(BYVAL Address AS DWORD, _
         BYVAL Length AS LONG, _
         BYVAL Seed AS LONG) AS LONG
  ! push    EBX             ; save EBX for PowerBASIC
  ! push    EDI             ; save EDI for PowerBASIC
  ! mov   EDI,Address         ; address in EDI
  ! mov   ECX,Length          ; length in ECX
  ! jecxz   CrcDone           ; exit is zero length
  ! cld                   ; clear the direction flag
BuildCRC:
  ! movzx   EBX, Byte Ptr [EDI]   ; get a char
  ! mov   AX, Seed[1]         ; get 2nd and 3rd bytes of seed
  ! xor   DX, DX            ; clear DX
  ! mov   DL, Seed[3]         ; get 4th byte of seed
  ! xor   BL, Seed[0]         ; xor char against first byte of seed
  ! xor   BH, BH            ; clear BH
  ! shl   BX, 2             ; shift the index
  ! xor   AX, CrcTable[EBX]     ; xor low-half against the table
  ! xor   DX, CrcTable[EBX+2]   ; xor high-half against the table
  ! mov   Seed[0], AX         ; save the result
  ! mov   Seed[2], DX         ;   ...
  ! inc   EDI             ; move to next char
  ! loop    BuildCRC          ; do ECX times
CrcDone:
  ! pop   EDI             ; restore EDI
  ! pop   EBX             ; restore EBX
  FUNCTION = Seed
  EXIT FUNCTION
CrcTable:
  ! dd &H000000000&, &H077073096&, &H0EE0E612C&, &H0990951BA&
  ! dd &H0076DC419&, &H0706AF48F&, &H0E963A535&, &H09E6495A3&
  ! dd &H00EDB8832&, &H079DCB8A4&, &H0E0D5E91E&, &H097D2D988&
  ! dd &H009B64C2B&, &H07EB17CBD&, &H0E7B82D07&, &H090BF1D91&
  ! dd &H01DB71064&, &H06AB020F2&, &H0F3B97148&, &H084BE41DE&
  ! dd &H01ADAD47D&, &H06DDDE4EB&, &H0F4D4B551&, &H083D385C7&
  ! dd &H0136C9856&, &H0646BA8C0&, &H0FD62F97A&, &H08A65C9EC&
  ! dd &H014015C4F&, &H063066CD9&, &H0FA0F3D63&, &H08D080DF5&
  ! dd &H03B6E20C8&, &H04C69105E&, &H0D56041E4&, &H0A2677172&
  ! dd &H03C03E4D1&, &H04B04D447&, &H0D20D85FD&, &H0A50AB56B&
  ! dd &H035B5A8FA&, &H042B2986C&, &H0DBBBC9D6&, &H0ACBCF940&
  ! dd &H032D86CE3&, &H045DF5C75&, &H0DCD60DCF&, &H0ABD13D59&
  ! dd &H026D930AC&, &H051DE003A&, &H0C8D75180&, &H0BFD06116&
  ! dd &H021B4F4B5&, &H056B3C423&, &H0CFBA9599&, &H0B8BDA50F&
  ! dd &H02802B89E&, &H05F058808&, &H0C60CD9B2&, &H0B10BE924&
  ! dd &H02F6F7C87&, &H058684C11&, &H0C1611DAB&, &H0B6662D3D&
  ! dd &H076DC4190&, &H001DB7106&, &H098D220BC&, &H0EFD5102A&
  ! dd &H071B18589&, &H006B6B51F&, &H09FBFE4A5&, &H0E8B8D433&
  ! dd &H07807C9A2&, &H00F00F934&, &H09609A88E&, &H0E10E9818&
  ! dd &H07F6A0DBB&, &H0086D3D2D&, &H091646C97&, &H0E6635C01&
  ! dd &H06B6B51F4&, &H01C6C6162&, &H0856530D8&, &H0F262004E&
  ! dd &H06C0695ED&, &H01B01A57B&, &H08208F4C1&, &H0F50FC457&
  ! dd &H065B0D9C6&, &H012B7E950&, &H08BBEB8EA&, &H0FCB9887C&
  ! dd &H062DD1DDF&, &H015DA2D49&, &H08CD37CF3&, &H0FBD44C65&
  ! dd &H04DB26158&, &H03AB551CE&, &H0A3BC0074&, &H0D4BB30E2&
  ! dd &H04ADFA541&, &H03DD895D7&, &H0A4D1C46D&, &H0D3D6F4FB&
  ! dd &H04369E96A&, &H0346ED9FC&, &H0AD678846&, &H0DA60B8D0&
  ! dd &H044042D73&, &H033031DE5&, &H0AA0A4C5F&, &H0DD0D7CC9&
  ! dd &H05005713C&, &H0270241AA&, &H0BE0B1010&, &H0C90C2086&
  ! dd &H05768B525&, &H0206F85B3&, &H0B966D409&, &H0CE61E49F&
  ! dd &H05EDEF90E&, &H029D9C998&, &H0B0D09822&, &H0C7D7A8B4&
  ! dd &H059B33D17&, &H02EB40D81&, &H0B7BD5C3B&, &H0C0BA6CAD&
  ! dd &H0EDB88320&, &H09ABFB3B6&, &H003B6E20C&, &H074B1D29A&
  ! dd &H0EAD54739&, &H09DD277AF&, &H004DB2615&, &H073DC1683&
  ! dd &H0E3630B12&, &H094643B84&, &H00D6D6A3E&, &H07A6A5AA8&
  ! dd &H0E40ECF0B&, &H09309FF9D&, &H00A00AE27&, &H07D079EB1&
  ! dd &H0F00F9344&, &H08708A3D2&, &H01E01F268&, &H06906C2FE&
  ! dd &H0F762575D&, &H0806567CB&, &H0196C3671&, &H06E6B06E7&
  ! dd &H0FED41B76&, &H089D32BE0&, &H010DA7A5A&, &H067DD4ACC&
  ! dd &H0F9B9DF6F&, &H08EBEEFF9&, &H017B7BE43&, &H060B08ED5&
  ! dd &H0D6D6A3E8&, &H0A1D1937E&, &H038D8C2C4&, &H04FDFF252&
  ! dd &H0D1BB67F1&, &H0A6BC5767&, &H03FB506DD&, &H048B2364B&
  ! dd &H0D80D2BDA&, &H0AF0A1B4C&, &H036034AF6&, &H041047A60&
  ! dd &H0DF60EFC3&, &H0A867DF55&, &H0316E8EEF&, &H04669BE79&
  ! dd &H0CB61B38C&, &H0BC66831A&, &H0256FD2A0&, &H05268E236&
  ! dd &H0CC0C7795&, &H0BB0B4703&, &H0220216B9&, &H05505262F&
  ! dd &H0C5BA3BBE&, &H0B2BD0B28&, &H02BB45A92&, &H05CB36A04&
  ! dd &H0C2D7FFA7&, &H0B5D0CF31&, &H02CD99E8B&, &H05BDEAE1D&
  ! dd &H09B64C2B0&, &H0EC63F226&, &H0756AA39C&, &H0026D930A&
  ! dd &H09C0906A9&, &H0EB0E363F&, &H072076785&, &H005005713&
  ! dd &H095BF4A82&, &H0E2B87A14&, &H07BB12BAE&, &H00CB61B38&
  ! dd &H092D28E9B&, &H0E5D5BE0D&, &H07CDCEFB7&, &H00BDBDF21&
  ! dd &H086D3D2D4&, &H0F1D4E242&, &H068DDB3F8&, &H01FDA836E&
  ! dd &H081BE16CD&, &H0F6B9265B&, &H06FB077E1&, &H018B74777&
  ! dd &H088085AE6&, &H0FF0F6A70&, &H066063BCA&, &H011010B5C&
  ! dd &H08F659EFF&, &H0F862AE69&, &H0616BFFD3&, &H0166CCF45&
  ! dd &H0A00AE278&, &H0D70DD2EE&, &H04E048354&, &H03903B3C2&
  ! dd &H0A7672661&, &H0D06016F7&, &H04969474D&, &H03E6E77DB&
  ! dd &H0AED16A4A&, &H0D9D65ADC&, &H040DF0B66&, &H037D83BF0&
  ! dd &H0A9BCAE53&, &H0DEBB9EC5&, &H047B2CF7F&, &H030B5FFE9&
  ! dd &H0BDBDF21C&, &H0CABAC28A&, &H053B39330&, &H024B4A3A6&
  ! dd &H0BAD03605&, &H0CDD70693&, &H054DE5729&, &H023D967BF&
  ! dd &H0B3667A2E&, &H0C4614AB8&, &H05D681B02&, &H02A6F2B94&
  ! dd &H0B40BBE37&, &H0C30C8EA1&, &H05A05DF1B&, &H02D02EF8D&
END FUNCTION

FUNCTION PBMAIN() AS LONG
'// Test both of the CRC32 functions...
'// This section by PowerBASIC Inc., 1998
  LOCAL Buffer   AS STRING
  LOCAL Crc    AS LONG
  LOCAL Filename AS STRING
  PRINT "CRC32.EXE - Calculate 32-bit CRC of a file"
  PRINT "Copyright (c) 1998 by PowerBASIC, Inc."
  PRINT
  Filename = COMMAND$
  IF LEN(DIR$(Filename)) = 0 THEN
    PRINT "Usage:  CRC32 filename"
    WAITKEY$
    EXIT FUNCTION
  END IF
  OPEN Filename FOR BINARY AS #1
    GET$ 1, LOF(1), Buffer
  CLOSE 1
  Buffer = CHR$(0) & "Testing 1 2 3" & CHR$(255)
  Crc = PBCrc32(STRPTR(Buffer), LEN(Buffer), -1)
  Crc = Crc XOR -1&  'compute PKZIP/ZMODEM compatible CRC result
  STDOUT "PB's CRC32 result:   " & HEX$(Crc,8)
  
'// This section added by Wayne Diamond, Dec 2002
  Crc = CRC32(BYVAL STRPTR(Buffer), BYVAL LEN(Buffer))
  STDOUT "Waynes CRC32 result: " & HEX$(Crc,8)
  WAITKEY$
END FUNCTION






'################################################################
'CRC32, by Semen Matusovski.
'Modified by Wayne Diamond to use a global CRCTable which only
'needs to be initialised once.
 
#COMPILE EXE
 
GLOBAL sCrcTable AS STRING * 1024, PtrCRC AS DWORD POINTER
 
SUB Crc32_BuildTable(BYVAL MagWord AS LONG)
    DIM x AS DWORD POINTER
    x = VARPTR(sCrcTable)
      ! MOV EDI, PtrCRC
      ! MOV EDX, 0
 Crc32_BuildTable_Lb1:
      ! MOV EBX, EDX
      ! MOV ECX, 8
 Crc32_BuildTable_Lb2:
      ! MOV EAX, EBX
      ! AND EAX, 1
      ! JE Crc32_BuildTable_Lb3
      ! SHR EBX, 1
      ! MOV EAX, MagWord
      ! XOR EBX, EAX
      ! JMP Crc32_BuildTable_Lb4
 Crc32_BuildTable_Lb3:
      ! SHR EBX, 1
 Crc32_BuildTable_Lb4:
      ! DEC ECX
      ! JNZ Crc32_BuildTable_Lb2
      ! MOV [EDI], EBX
      ! ADD EDI, 4
      ! INC EDX
      ! CMP EDX, 255
      ! JLE Crc32_BuildTable_Lb1
END SUB

FUNCTION Crc32_Calculate (BYVAL Address AS DWORD, BYVAL Length AS LONG, _
      sCrcTable AS STRING * 1024, BYVAL InitCrc AS LONG, BYVAL Inverse AS LONG) AS LONG
      ! MOV EBX, InitCrc
      ! MOV EDI, Address
      ! MOV ESI, EDI
      ! ADD ESI, Length
 Crc32_Calculate_Lb1:
      ! CMP EDI, ESI
      ! JGE  Crc32_Calculate_Lb2
      ! MOV EAX, 0
      ! MOV AL, [EDI]
      ! XOR EAX, EBX
      ! AND EAX, &HFF
      ! SHL EAX, 2
      ! add EaX, PtrCRC  ;sCrcTable
      ! MOV EAX, [EAX]
      ! SHR EBX, 8
      ! AND EBX, &H00FFFFFF
      ! XOR EBX, EAX
      ! INC EDI
      ! JMP Crc32_Calculate_Lb1
  Crc32_Calculate_Lb2:
      ! CMP Inverse, 0
      ! JE  Crc32_Calculate_Lb3
      ! XOR EBX, &HFFFFFFFF
 Crc32_Calculate_Lb3:
      ! MOV Function, EBX
END FUNCTION

FUNCTION PBMAIN() AS LONG
     DIM Buffer AS STRING, Crc AS LONG
     PtrCRC = VARPTR(sCrcTable)
     Buffer = "1234567890"
     Crc32_BuildTable &HEDB88320
     Crc = Crc32_Calculate (STRPTR(Buffer), LEN(Buffer), sCrcTable, &HFFFFFFFF, 1)
     MSGBOX HEX$(Crc) & " (should be 261DAEE5)",, "Winzip compatible CRC"
END FUNCTION
'################################################################

Back to The Archives