Adler32
Algorithm creator(s)
Mark Adler
PB author(s)
Marc Sven Schulte, Wayne Diamond
Description
Adler-32 is 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.
Note
Adler32 is also known as Fletch-32/Fletcher-32, and is used in ZLib. Marc Sven Schulte has recently (July 2003) written a faster PB implementation that my original (see below).
Source
https://forum.powerbasic.com/forum/user-to-user-discussions/source-code/24064-adler-32-checksum?t=23439
See also
n/a
Source Code
Download source code file adler32.bas (Right-click -> "Save as ...")
'Adler-32 is composed of two sums accumulated per byte: s1 is the sum
'of all bytes, s2 is the sum of all s1 values. Both sums are done
'modulo 65521. s1 is initialised to 1, s2 to zero. The Adler-32 checksum
'is stored as s2*65536 + s1 in most-significant-byte first (network) order.
'
'The algorithm is much faster than the CRC32 algorithm yet still provides
'an extremely low probability of undetected errors.
'
'The modulo on unsigned long accumulators can be delayed for 5552 bytes,
'so the modulo operation time is negligible. If the bytes are a, b, c,
'the second sum is 3a + 2b + c + 3, and so is position and order sensitive,
'unlike the first sum, which is just a checksum. That 65521 is prime is
'important to avoid a possible large class of two-byte errors that leave
'the check unchanged. (The Fletcher checksum uses 255, which is not prime
'and which also makes the Fletcher check insensitive to single byte
'changes 0-255).
'
'The sum s1 is initialised to 1 instead of zero to make the length of the
'sequence part of s2, so that the length does not have to be checked
'separately. (Any sequence of zeroes has a Fletcher checksum of zero.)")
'
#COMPILE EXE 'PBCC. Replace STDOUT with MSGBOX to compile with 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 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
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) 'PB basic code
'Adler = Adler32asm(TestBuffer) 'PB inline asm
IF Adler = 11337831 THEN
STDOUT "Calculated correctly"
ELSE
STDOUT "Calculation failed"
END IF
STDOUT "Adler32 checksum=" & STR$(Adler)
END FUNCTION
'#####################################################################################
'ADLER32, by Marc Sven Schulte, 10th July 2003.
'Note: This is the fastest implementation so far.
'
FUNCTION ADLER32(BYVAL Address AS DWORD, _
BYVAL Length AS LONG, _
BYVAL Seed AS DWORD) AS DWORD
#REGISTER NONE
! mov edx, Seed
! movzx ecx, dx
! shr edx, 16
! mov esi, Address
! mov eax, Length
! add eax, esi
! xor ebx, ebx
LP:
! mov bl, [esi]
! add ecx, ebx
! cmp ecx, 65521
! jb M1
! sub ecx, 65521
M1:
! add edx, ecx
! cmp edx, 65521
! jb M2
! sub edx, 65521
M2:
! inc esi
! cmp esi, eax
! jnz LP
! shl edx, 16
! add ecx, edx
! mov FUNCTION, ecx
END FUNCTION
FUNCTION PBMAIN() AS LONG
DIM crc AS DWORD
DIM str AS STRING
str = "Mark Adler"
crc = 1
crc = ADLER32(STRPTR(str), LEN(str), crc)
MSGBOX "ADLER32: " & HEX$(crc, 8) & " (should be: 13070394)"
END FUNCTION