|
Author
|
Topic: Adler-32 checksum
|
Wayne Diamond Member
|
posted March 20, 2002 09:35 PM
Adler-32 (by Mark Adler) is a checksum algorithm used by ZIP files that is some 33% faster than CRC32. My port might not be that fast as it's not assembly, but it's returning the correct values!
#COMPILE EXE 'PBCC. Replace STDOUT with MSGBOX to compile in PBDLL #INCLUDE "win32api.inc" FUNCTION Adler32(sBuffer AS STRING) AS LONG DIM Seed AS LONG DIM S1 AS LONG DIM S2 AS LONG DIM N AS LONG %CrcBase = 65521 Seed = 1 S1 = Seed AND &HFFFF S2 = (Seed / 65536) AND &HFFFF FOR N = 1 TO LEN(sBuffer) S1 = (S1 + ASC(MID$(sBuffer, N,1))) MOD %CrcBase S2 = (S2 + S1) MOD %CrcBase NEXT Adler32 = (S2 * 65536) + S1 END FUNCTION FUNCTION PBMAIN() AS LONG ON ERROR RESUME NEXT DIM TestBuffer AS STRING DIM Adler AS LONG TestBuffer = CHR$(17) & CHR$(34) & CHR$(51) Adler = Adler32(TestBuffer) IF Adler = 11337831 THEN STDOUT "Calculated correctly" ELSE STDOUT "Calculation failed" END IF STDOUT "Adler=" & STR$(Adler) 'WAITKEY$ END FUNCTION ------------------
IP: Logged |
Wayne Diamond Member
|
posted March 20, 2002 09:42 PM
And here is another simple checksum algorithm designed for speed. The C++ bit shifting has got me a bit confused so if anyone else wants to port it, the challenge is all theirs  It was developed by Sami J. Mäkinen (sjm@pp.inet.fi) quote: The goal was to have extremely high speed in 32-bit Pentium platform. The algorithm is very simple, it works on 32-bit words and requires 2 ADDS, 3 SHIFTS and 1 XOR for one 32-bit word. The core is easy to represent in C-code:
uint32 *buffer; uint32 i, tmp; sum = 1; for ( i = 0; i < n; i++ ) { tmp = buffer[i]; tmp = (uint32) (sum >> 29) + tmp; tmp = (uint32) (sum >> 17) + tmp; sum = (uint32) (sum << 3) ^ tmp; } return sum; quote: My C-code implementation is about 33% faster than Adler32 and 5 times as fast as CRC32.
------------------
IP: Logged |
Torsten Rienow Member
|
posted March 21, 2002 06:08 AM
Wayne, try this for speed and correctness. If it works, add a favour for me .regards, Torsten #Compile Exe 'No range testing or buffer address validation, just the algorithm Function CRC_ASM_FOR_WAYNE(ByRef lpBuffer As Dword Ptr, ByVal lBuffer As Dword) As Dword #Register None Dim sum As Dword !LEA EAX, sum !MOV DWORD PTR [EAX], 1 !MOV EDI, lBuffer !SHR EDI, 2 !MOV ECX, lpBuffer !XOR EDX, EDX NextDWord: !MOV EDX, [ECX] !MOV ESI, [EAX] !PUSH ESI !PUSH ESI !SHR ESI, 29 !ADD EDX, ESI !POP ESI !SHR ESI, 17 !ADD EDX, ESI !POP ESI !SHL ESI, 3 !XOR ESI, EDX !MOV DWORD PTR [EAX], ESI !ADD ECX, 4 !DEC EDI !JNZ NextDWord !MOV EAX, [EAX] GetOut: !MOV Function, EAX End FunctionFunction PbMain Dim l As Long l = 1 MsgBox Str$( CRC_ASM_FOR_WAYNE(ByVal VarPtr(l), 4)) End Function
------------------
[This message has been edited by Torsten Rienow (edited March 21, 2002).] IP: Logged |
Wayne Diamond Member
|
posted July 11, 2002 01:37 AM
i ported Adler32 over to PB inline asm for a bit of extra speed
FUNCTION Adler32asm(sBuffer AS STRING) AS LONG #REGISTER NONE DIM Seed AS LONG, S1 AS LONG, S2 AS LONG, N AS LONG DIM sPtr AS LONG sPtr = STRPTR(sBuffer) - 1 N = LEN(sBuffer) + sPtr '// S1 = Seed AND &HFFFF ! mov Seed, 1 ! xor eax, eax ! add eax, Seed ! mov ebx, eax ! and eax, &hFFFF ! mov eax, ebx ! mov S1, eax '// S2 = (Seed / 65536) AND &HFFFF ! mov eax, Seed ! mov ebx, &h10000 ! xor edx, edx ! div ebx ! and eax, &hFFFF ! mov S2, eax ! mov ecx, sPtr StartLoop: '// FOR N = 1 TO LEN(sBuffer) ! inc ecx ! cmp ecx, N ! jg EndLoop '//S1 = (S1 + ASC(MID$(sBuffer, N,1))) MOD %CrcBase ! mov eax, S1 ! xor ebx, ebx ! mov bl, [ecx] ! add eax, ebx ! mov ebx, &hFFF1 ! xor edx, edx ! div ebx ! mov S1, edx '//S2 = (S2 + S1) MOD %CrcBase ! mov eax, S2 ! add eax, S1 ! mov ebx, &hFFF1 ! xor edx, edx ! div ebx ! mov S2, edx ! jmp StartLoop ;// NEXT EndLoop: '// FUNCTION = (S2 * 65536) + S1 ! mov eax, S2 ! mov ecx, &h10000 ! mul ecx ! add eax, S1 ! mov N, eax FUNCTION = N END FUNCTION See http://www.wanet.com.au/~diamond/pbcrypto/view.php?algorithm=adler32 for more details
------------------ The PowerBASIC Crypto Archives IP: Logged |