Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Adler-32 checksum

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Adler-32 checksum

    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!

    Code:
    #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
    ------------------
    -

  • #2
    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)
    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:
    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;
    My C-code implementation is about 33% faster than Adler32 and 5 times
    as fast as CRC32.
    ------------------
    -

    Comment


    • #3
      Wayne, try this for speed and correctness.
      If it works, add a favour for me .

      regards,

      Torsten

      Code:
      #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 Function
      
      Function 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).]

      Comment


      • #4
        i ported Adler32 over to PB inline asm for a bit of extra speed
        Code:
        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/pbc...orithm=adler32 for more details


        ------------------
        The PowerBASIC Crypto Archives
        -

        Comment

        Working...
        X