
Checksum.pb:
Code: Select all
;{/ CRC32: Wayne Diamond, 2004-01-01 / PB4: sverson, 2006-08-14
;/ http://www.purebasic.fr/english/viewtopic.php?p=43376
;/ CRC32 - a relatively fast algorithm that creates a 32-bit CheckSum.
;}/ CRC32 is the most commonly-used 32-bit CheckSum algorithm.
Procedure.l CRC32d(Buffer.l, BufLen.l)
!MOV Esi, dword [p.v_Buffer] ;esi = ptr to buffer
!MOV Edi, dword [p.v_BufLen] ;edi = length of buffer
!MOV Ecx, -1 ;ecx = -1
!MOV Edx, Ecx ;edx = -1
!_crc321: ;"nextbyte" next byte from buffer
!XOR Eax, Eax ;eax = 0
!XOR Ebx, Ebx ;ebx = 0
!DB 0xAC ;"lodsb" instruction to 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
!_crc322: ;"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 near _crc323 ;jump to "nocarry" if carry flag not set
!XOR ax, 0x08320 ;xor ax with 33568
!XOR bx, 0x0EDB8 ;xor bx with 60856
!_crc323: ;"nocarry" if carry flag wasn't set
!DEC dh ;dh = dh - 1
!JNZ near _crc322 ;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 near _crc321 ;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
ProcedureReturn
EndProcedure
;{/ CRC32: Translated To PureBasic by El_Choni / PB4: sverson, 2006-08-14
;/ http://www.purebasic.fr/english/viewtopic.php?p=12348
;/ CRC32 - Calculate a CCITT 32-bit For a buffer
;}/ Copyright (c) 1998 by PowerBASIC, Inc.
Procedure.l CRC32e(Address.l, length.l, Seed.l=-1)
!MOV Edi, dword [p.v_Address] ; address in EDI
!MOV Ecx, dword [p.v_length] ; length in ecx
!JECXZ CrcDone ; exit is zero length
!CLD ; clear the direction flag
!BuildCRC:
!MOVZX Ebx, byte [Edi] ; get a char
!MOV ax, word [p.v_Seed+1] ; get 2nd and 3rd bytes of seed
!XOR dx, dx ; clear DX
!MOV dl, byte [p.v_Seed+3] ; get 4th byte of seed
!XOR bl, byte [p.v_Seed] ; 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 word [p.v_Seed], ax ; save the result
!MOV word [p.v_Seed+2], dx ; ...
!INC Edi ; move to next char
!LOOP BuildCRC ; do ECX times
!CrcDone:
!MOV Eax, dword [p.v_Seed] ; move the result to EAX
!XOR Eax, -1 ; compute PKZIP/ZMODEM compatible CRC result
ProcedureReturn
DataSection ;{/ CrcTable
!CrcTable:
!DD $000000000, $077073096, $0EE0E612C, $0990951BA
!DD $0076DC419, $0706AF48F, $0E963A535, $09E6495A3
!DD $00EDB8832, $079DCB8A4, $0E0D5E91E, $097D2D988
!DD $009B64C2B, $07EB17CBD, $0E7B82D07, $090BF1D91
!DD $01DB71064, $06AB020F2, $0F3B97148, $084BE41DE
!DD $01ADAD47D, $06DDDE4EB, $0F4D4B551, $083D385C7
!DD $0136C9856, $0646BA8C0, $0FD62F97A, $08A65C9EC
!DD $014015C4F, $063066CD9, $0FA0F3D63, $08D080DF5
!DD $03B6E20C8, $04C69105E, $0D56041E4, $0A2677172
!DD $03C03E4D1, $04B04D447, $0D20D85FD, $0A50AB56B
!DD $035B5A8FA, $042B2986C, $0DBBBC9D6, $0ACBCF940
!DD $032D86CE3, $045DF5C75, $0DCD60DCF, $0ABD13D59
!DD $026D930AC, $051DE003A, $0C8D75180, $0BFD06116
!DD $021B4F4B5, $056B3C423, $0CFBA9599, $0B8BDA50F
!DD $02802B89E, $05F058808, $0C60CD9B2, $0B10BE924
!DD $02F6F7C87, $058684C11, $0C1611DAB, $0B6662D3D
!DD $076DC4190, $001DB7106, $098D220BC, $0EFD5102A
!DD $071B18589, $006B6B51F, $09FBFE4A5, $0E8B8D433
!DD $07807C9A2, $00F00F934, $09609A88E, $0E10E9818
!DD $07F6A0DBB, $0086D3D2D, $091646C97, $0E6635C01
!DD $06B6B51F4, $01C6C6162, $0856530D8, $0F262004E
!DD $06C0695ED, $01B01A57B, $08208F4C1, $0F50FC457
!DD $065B0D9C6, $012B7E950, $08BBEB8EA, $0FCB9887C
!DD $062DD1DDF, $015DA2D49, $08CD37CF3, $0FBD44C65
!DD $04DB26158, $03AB551CE, $0A3BC0074, $0D4BB30E2
!DD $04ADFA541, $03DD895D7, $0A4D1C46D, $0D3D6F4FB
!DD $04369E96A, $0346ED9FC, $0AD678846, $0DA60B8D0
!DD $044042D73, $033031DE5, $0AA0A4C5F, $0DD0D7CC9
!DD $05005713C, $0270241AA, $0BE0B1010, $0C90C2086
!DD $05768B525, $0206F85B3, $0B966D409, $0CE61E49F
!DD $05EDEF90E, $029D9C998, $0B0D09822, $0C7D7A8B4
!DD $059B33D17, $02EB40D81, $0B7BD5C3B, $0C0BA6CAD
!DD $0EDB88320, $09ABFB3B6, $003B6E20C, $074B1D29A
!DD $0EAD54739, $09DD277AF, $004DB2615, $073DC1683
!DD $0E3630B12, $094643B84, $00D6D6A3E, $07A6A5AA8
!DD $0E40ECF0B, $09309FF9D, $00A00AE27, $07D079EB1
!DD $0F00F9344, $08708A3D2, $01E01F268, $06906C2FE
!DD $0F762575D, $0806567CB, $0196C3671, $06E6B06E7
!DD $0FED41B76, $089D32BE0, $010DA7A5A, $067DD4ACC
!DD $0F9B9DF6F, $08EBEEFF9, $017B7BE43, $060B08ED5
!DD $0D6D6A3E8, $0A1D1937E, $038D8C2C4, $04FDFF252
!DD $0D1BB67F1, $0A6BC5767, $03FB506DD, $048B2364B
!DD $0D80D2BDA, $0AF0A1B4C, $036034AF6, $041047A60
!DD $0DF60EFC3, $0A867DF55, $0316E8EEF, $04669BE79
!DD $0CB61B38C, $0BC66831A, $0256FD2A0, $05268E236
!DD $0CC0C7795, $0BB0B4703, $0220216B9, $05505262F
!DD $0C5BA3BBE, $0B2BD0B28, $02BB45A92, $05CB36A04
!DD $0C2D7FFA7, $0B5D0CF31, $02CD99E8B, $05BDEAE1D
!DD $09B64C2B0, $0EC63F226, $0756AA39C, $0026D930A
!DD $09C0906A9, $0EB0E363F, $072076785, $005005713
!DD $095BF4A82, $0E2B87A14, $07BB12BAE, $00CB61B38
!DD $092D28E9B, $0E5D5BE0D, $07CDCEFB7, $00BDBDF21
!DD $086D3D2D4, $0F1D4E242, $068DDB3F8, $01FDA836E
!DD $081BE16CD, $0F6B9265B, $06FB077E1, $018B74777
!DD $088085AE6, $0FF0F6A70, $066063BCA, $011010B5C
!DD $08F659EFF, $0F862AE69, $0616BFFD3, $0166CCF45
!DD $0A00AE278, $0D70DD2EE, $04E048354, $03903B3C2
!DD $0A7672661, $0D06016F7, $04969474D, $03E6E77DB
!DD $0AED16A4A, $0D9D65ADC, $040DF0B66, $037D83BF0
!DD $0A9BCAE53, $0DEBB9EC5, $047B2CF7F, $030B5FFE9
!DD $0BDBDF21C, $0CABAC28A, $053B39330, $024B4A3A6
!DD $0BAD03605, $0CDD70693, $054DE5729, $023D967BF
!DD $0B3667A2E, $0C4614AB8, $05D681B02, $02A6F2B94
!DD $0B40BBE37, $0C30C8EA1, $05A05DF1B, $02D02EF8D
!EndTable:
EndDataSection ;}/
EndProcedure
;{/ Adler32: Wayne Diamond, 2004-01-01 / PB4: sverson, 2006-08-14
;/ http://www.purebasic.fr/english/viewtopic.php?p=43378
;/ Adler32 - an algorithm used by ZIP files that creates a 32-bit CheckSum.
;/ The algorithm is approximately 33% faster than CRC32, And nearly As reliable.
;/ Adler32 is a 32-bit extension And improvement of The Fletcher algorithm,
;}/ used in The ITU-T x.224 / ISO 8073 standard.
Procedure.l Adler32(Buffer.l, BufLen.l, Seed.l)
!MOV Edx, dword [p.v_Seed]
!MOVZX Ecx, dx
!SHR Edx, 16
!MOV Esi, dword [p.v_Buffer]
!MOV Eax, dword [p.v_BufLen]
!ADD Eax, Esi
!XOR Ebx, Ebx
!_alder321:
!MOV bl, [Esi]
!ADD Ecx, Ebx
!CMP Ecx, 65521
!JB near _alder322
!SUB Ecx, 65521
!_alder322:
!ADD Edx, Ecx
!CMP Edx, 65521
!JB near _alder323
!SUB Edx, 65521
!_alder323:
!INC Esi
!CMP Esi, Eax
!JNZ near _alder321
!SHL Edx, 16
!ADD Ecx, Edx
!MOV Eax, Ecx
ProcedureReturn
EndProcedure
;{/ FNV32 Wayne Diamond, 2004-01-01 / PB4: sverson, 2006-08-14
;/ http://www.purebasic.fr/english/viewtopic.php?p=43379
;/ FNV32 - A very simple algorithm designed for high-speed
;/ hashing resulting in highly dispersed hashes With minimal collisions.
;}/ Named after its creators Glenn Fowler, Phong Vo, And Landon Curt Noll.
Procedure.l FNV32(Buffer.l, BufLen.l, OffsetBasis.l)
!MOV Esi, dword [p.v_Buffer] ;esi = ptr to buffer
!MOV Ecx, dword [p.v_BufLen] ;ecx = length of buffer (counter)
!MOV Eax, dword [p.v_OffsetBasis] ;set to 0 for FNV-0, or 2166136261 for FNV-1
!MOV Edi, 0x01000193 ;FNV_32_PRIME = 16777619
!XOR Ebx, Ebx ;ebx = 0
!_fnv321:
!MUL Edi ;eax = eax * FNV_32_PRIME
!MOV bl, [Esi] ;bl = byte from esi
!XOR Eax, Ebx ;al = al xor bl
!INC Esi ;esi = esi + 1 (buffer pos)
!DEC Ecx ;ecx = ecx - 1 (counter)
!JNZ near _fnv321 ;if ecx is 0, jmp to _fnv321
ProcedureReturn
EndProcedure
;{/ ELF32: Wayne Diamond, 2004-01-01 / PB4: sverson, 2006-08-14
;/ http://www.purebasic.fr/english/viewtopic.php?p=43381
;/ ELF32 - Outputs a 32-bit unsigned hash that is the modulo
;/ generated by dividing the returned integer by the Size of the table.
;}/ Used in UNIX object files that use the ELF format.
Procedure.l ELF32(Buffer.l, BufLen.l)
!XOR Ebx, Ebx ; ebx = result holder (H)
!MOV Edx, dword [p.v_BufLen] ; edx = Length
!MOV Ecx, dword [p.v_Buffer] ; ecx = Ptr to string
!XOR Esi, Esi ; esi = temp holder
!_elf321:
!XOR Eax, Eax
!SHL Ebx, 4
!MOV al, [Ecx]
!ADD Ebx, Eax
!INC Ecx
!MOV Eax, Ebx
!AND Eax, 0xF0000000
!CMP Eax, 0
!JE near _elf322
!MOV Esi, Eax
!SHR Esi, 24
!XOR Ebx, Esi
!_elf322:
!NOT Eax
!AND Ebx,Eax
!DEC Edx
!CMP Edx, 0
!JNE near _elf321
!MOV Eax, Ebx
ProcedureReturn
EndProcedure
;// MAIN
TestFile.s = #PB_Compiler_Home+"Compilers\PBCompiler.exe"
Info.s = TestFile+Chr(10)+Chr(10)
Loops.l = 3
If ReadFile(0,TestFile)
BufferLen.l = Lof(0)
*Buffer = AllocateMemory(BufferLen)
If *Buffer
QueryPerformanceCounter_(@QPC0a.q)
If ReadData(0,*Buffer,BufferLen) = BufferLen
QueryPerformanceCounter_(@QPC0b.q)
QueryPerformanceFrequency_(@QPF.q)
Info + "LoadFile:"+Chr(9)+Chr(9)+StrF(((QPC0b-QPC0a)/QPF)*1000)+" ms"+Chr(10)+Chr(10)
While Loops
QueryPerformanceCounter_(@QPC1.q)
CRC32dCheckSum.l = CRC32d(*Buffer, BufferLen)
QueryPerformanceCounter_(@QPC2.q)
CRC32eCheckSum.l = CRC32e(*Buffer, BufferLen)
QueryPerformanceCounter_(@QPC3.q)
CRC32Fingerprint.l= CRC32Fingerprint(*Buffer, BufferLen)
QueryPerformanceCounter_(@QPC4.q)
Adler32CheckSum.l = Adler32(*Buffer, BufferLen, 1)
QueryPerformanceCounter_(@QPC5.q)
FNV32CheckSum.l = FNV32(*Buffer, BufferLen, 0)
QueryPerformanceCounter_(@QPC6.q)
ELF32CheckSum.l = ELF32(*Buffer, BufferLen)
QueryPerformanceCounter_(@QPC7.q)
Info + "CRC32 Diamond:"+Chr(9)+RSet(Hex(CRC32dCheckSum),8,"0")+Chr(9)+StrF(((QPC2-QPC1)/QPF)*1000)+" ms"+Chr(10)
Info + "CRC32 El_Choni:"+Chr(9)+RSet(Hex(CRC32eCheckSum),8,"0")+Chr(9)+StrF(((QPC3-QPC2)/QPF)*1000)+" ms"+Chr(10)
Info + "CRC32 PureBasic:"+Chr(9)+RSet(Hex(CRC32Fingerprint),8,"0")+Chr(9)+StrF(((QPC4-QPC3)/QPF)*1000)+" ms"+Chr(10)
Info + "Adler32 Diamond:"+Chr(9)+RSet(Hex(Adler32CheckSum),8,"0")+Chr(9)+StrF(((QPC5-QPC4)/QPF)*1000)+" ms"+Chr(10)
Info + "FNV32 Diamond:"+Chr(9)+RSet(Hex(FNV32CheckSum),8,"0")+Chr(9)+StrF(((QPC6-QPC5)/QPF)*1000)+" ms"+Chr(10)
Info + "ELF32 Diamond:"+Chr(9)+RSet(Hex(ELF32CheckSum),8,"0")+Chr(9)+StrF(((QPC7-QPC6)/QPF)*1000)+" ms"+Chr(10)
Info + Chr(10)
Loops -1
Wend
MessageRequester("Checksum",Info)
EndIf
EndIf
CloseFile(0)
EndIf
End
