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

Class: SHA256

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

  • PBWin Class: SHA256

    Here a Class for SHA256 based on Code by Greg Turgeon. It is a very fast code for this generator.
    I tested a file with 11.3Gb. Duration: 226 seconds. This corresponds 50MB/s on i5 M460 @2x2,53 GHz

    Code:
    [B][COLOR="YellowGreen"]'=====================================================================
    ' This class '[B]SHA256hash.inc[/B]' was generated
    ' from the following code:
    '=====================================================================
    '-- SHA256c.INC
    '-- WIN32 API not required
    '-- Uses no global data
    '-- http://www.powerbasic.com/support/pbforums/showthread.php?t=39850
    '=====================================================================[/COLOR][/B]
    
    
    %TRUE                   = 1
    %FALSE                  = 0
    %RETURN_LITTLE_ENDIAN   = %TRUE                 [COLOR="YellowGreen"][B]'-- Set to %FALSE to return big-endian hash$ (as in 2001 code)[/B][/COLOR]
    %ALIGNMENT              = 16
    %HASHLEN                = 32                   [B][COLOR="YellowGreen"] 'bytes[/COLOR][/B]
    %BLOCKSIZE              = 64                    [B][COLOR="YellowGreen"]'bytes[/COLOR][/B]
    %FILE_BUFFERSIZE        = 32000                 [B][COLOR="YellowGreen"]'bytes[/COLOR][/B]
    %S_ARRAY_SIZE           = (%HASHLEN)
    %W_ARRAY_SIZE           = (%BLOCKSIZE*4)
    
    
    TYPE SHA256_CONTEXT
       state       AS STRING * (%HASHLEN+%ALIGNMENT)
       pstate      AS DWORD PTR
       pdata       AS BYTE PTR
       lendata     AS DWORD
       HasSSE2     AS LONG
       HasMMX      AS LONG
       k_array     AS LONG PTR
       s_array     AS LONG PTR
       w_array     AS LONG PTR
       Workspace   AS STRING * (%S_ARRAY_SIZE + %W_ARRAY_SIZE + (%ALIGNMENT * 2))  [COLOR="YellowGreen"][B]'w_array&() + s+_array&()[/B][/COLOR]
    END TYPE
    
    
    MACRO align(p,alignment)=((p+(alignment-1)) AND (NOT(alignment-1)))
    
    
    ASMDATA Init_Values
        DD  &h6A09E667???, &hBB67AE85???, &h3C6EF372???, &hA54FF53A???
        DD  &h510E527F???, &h9B05688C???, &h1F83D9AB???, &h5BE0CD19???
    END ASMDATA
    
    
    ASMDATA K_Array_Data
        DD  &h428a2f98???, &h71374491???, &hb5c0fbcf???, &he9b5dba5???, &h3956c25b???, &h59f111f1???
        DD  &h923f82a4???, &hab1c5ed5???, &hd807aa98???, &h12835b01???, &h243185be???, &h550c7dc3???
        DD  &h72be5d74???, &h80deb1fe???, &h9bdc06a7???, &hc19bf174???, &he49b69c1???, &hefbe4786???
        DD  &h0fc19dc6???, &h240ca1cc???, &h2de92c6f???, &h4a7484aa???, &h5cb0a9dc???, &h76f988da???
        DD  &h983e5152???, &ha831c66d???, &hb00327c8???, &hbf597fc7???, &hc6e00bf3???, &hd5a79147???
        DD  &h06ca6351???, &h14292967???, &h27b70a85???, &h2e1b2138???, &h4d2c6dfc???, &h53380d13???
        DD  &h650a7354???, &h766a0abb???, &h81c2c92e???, &h92722c85???, &ha2bfe8a1???, &ha81a664b???
        DD  &hc24b8b70???, &hc76c51a3???, &hd192e819???, &hd6990624???, &hf40e3585???, &h106aa070???
        DD  &h19a4c116???, &h1e376c08???, &h2748774c???, &h34b0bcb5???, &h391c0cb3???, &h4ed8aa4a???
        DD  &h5b9cca4f???, &h682e6ff3???, &h748f82ee???, &h78a5636f???, &h84c87814???, &h8cc70208???
        DD  &h90befffa???, &ha4506ceb???, &hbef9a3f7???, &hc67178f2???
    END ASMDATA
    
    
    CLASS cSHA256hash
    INSTANCE m_ctx       AS SHA256_CONTEXT
    INSTANCE m_compress  AS LONG
    INSTANCE m_filesize  AS QUAD
    INSTANCE m_bytesleft AS QUAD
    INSTANCE m_buffer    AS STRING
    INSTANCE m_padding   AS STRING
    INSTANCE m_hHash     AS DWORD
    INSTANCE m_infile    AS LONG
    INSTANCE m_lastpass  AS LONG
    INSTANCE m_maxstring AS LONG
    
    
        '====================
        CLASS METHOD Init()
        LOCAL pInit, pworkspace, pstate AS LONG
    
            RESET m_ctx
    
            m_ctx.k_array = CODEPTR(K_Array_Data)
            pInit         = CODEPTR(Init_Values)
    
            pworkspace    = align(VARPTR(m_ctx.Workspace), %ALIGNMENT)
            m_ctx.s_array = pworkspace
            m_ctx.w_array = pworkspace + %S_ARRAY_SIZE
    
            m_ctx.pstate  = align(VARPTR(m_ctx.state), %ALIGNMENT)
            pstate        = m_ctx.pstate
    
            !  push     esi
            !  push     edi
            !  mov      esi,     pInit
            !  mov      edi,     pstate
            !  mov      ecx,     8
            !  cld
            !  rep      movsd
            !  pop      edi
            !  pop      esi
    
        END METHOD
    
    
        '====================
        CLASS METHOD Compress128()
        #REGISTER NONE
        LOCAL k_array, s_array, w_array AS LONG
        LOCAL pstate, pdata, wi, ki, i AS LONG
    
            '-- Copy for inline assembler
            w_array  = m_ctx.w_array
            s_array  = m_ctx.s_array
            k_array  = m_ctx.k_array
            pstate   = m_ctx.pstate
            pdata    = m_ctx.pdata
    
            !  push     esi
            !  push     edi
            !  push     ebx
    
            '-- Copy current state into s&()
            !  mov      esi,     pstate           ;esi -> pm_ctx.state0
            !  mov      edi,     s_array
            !  movdqa   xmm0,    [esi]
            !  movdqa   xmm1,    [esi+16]
            !  movdqa   [edi],   xmm0
            !  movdqa   [edi+16],xmm1
    
            '-- Copy current data block to w&() w/little-to-big endian conversion
            !  mov      esi,     pdata
            !  mov      edi,     w_array
            !  movdqu   xmm0,    [esi]
            !  movdqu   xmm2,    [esi+16]
            !  movdqu   xmm4,    [esi+32]
            !  movdqu   xmm6,    [esi+48]
    
            !  pshufhw  xmm1,    xmm0, &b10110001
            !  pshufhw  xmm3,    xmm2, &b10110001
            !  pshufhw  xmm5,    xmm4, &b10110001
            !  pshufhw  xmm7,    xmm6, &b10110001
    
            !  pshuflw  xmm0,    xmm1, &b10110001
            !  pshuflw  xmm2,    xmm3, &b10110001
            !  pshuflw  xmm4,    xmm5, &b10110001
            !  pshuflw  xmm6,    xmm7, &b10110001
    
            !  movdqa   xmm1,    xmm0
            !  movdqa   xmm3,    xmm2
            !  movdqa   xmm5,    xmm4
            !  movdqa   xmm7,    xmm6
    
            !  psllw    xmm0,    8
            !  psllw    xmm2,    8
            !  psllw    xmm4,    8
            !  psllw    xmm6,    8
    
            !  psrlw    xmm1,    8
            !  psrlw    xmm3,    8
            !  psrlw    xmm5,    8
            !  psrlw    xmm7,    8
    
            !  por      xmm0,    xmm1
            !  por      xmm2,    xmm3
            !  por      xmm4,    xmm5
            !  por      xmm6,    xmm7
    
            !  movdqa   [edi],   xmm0
            !  movdqa   [edi+16],xmm2
            !  movdqa   [edi+32],xmm4
            !  movdqa   [edi+48],xmm6
    
            '-- Fill W[16to63]
            ! mov       esi,     w_array
            ! push      ebp
            ! mov       ebp,     16
            #ALIGN 4
            FillTop:
            !  mov      ebx,     ebp
            !  sub      ebx,     2
            !  mov      eax,     [esi+ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  sub      ebx,     13             ;prep for next access: (-2)+(-13) = -15
            !  ror      eax,     17
            !  ror      ecx,     19
            !  shr      edx,     10
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  mov      edi,     eax            ;edi = temp total
            !  mov      eax,     [esi+ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  ror      eax,     7
            !  ror      ecx,     18
            !  shr      edx,     3
            !  add      ebx,     8              ;= (-15)+8 = -7
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  add      edi,     eax
    
            !  mov      eax,     [esi+ebx*4]
            !  sub      ebx,     9              ;= (-7)+(-9) = -16
            !  add      edi,     eax
    
            !  mov      eax,     [esi+ebx*4]
            !  mov      ebx,     ebp
            !  add      eax,     edi
    
            !  inc      ebp
            !  mov      [esi+ebx*4], eax
            !  test     ebp,     &b111111       ;<64?
            !  jnz      FillTop
            !  pop      ebp
    
            '-- Compress: i& = 0 to 63
            !  xor      eax,     eax
            !  mov      esi,     s_array        ;here to CompressDone & END SUB: esi -> s[0]
            !  mov      i,       eax
            #ALIGN 4
            CompressTop:
            !  mov      ebx,     eax
            !  mov      edx,     w_array
            !  mov      eax,     [edx+ebx*4]
            !  mov      wi,      eax
            !  mov      edx,     k_array
            !  mov      eax,     [edx+ebx*4]
            !  mov      ki,      eax
    
            !  mov      eax,     [esi+16]
            !  mov      ecx,     [esi+20]
            !  mov      ebx,     eax
            !  mov      edx,     eax
            !  and      eax,     [esi+20]
    
            !  not      edx
            !  and      edx,     [esi+24]
            !  xor      eax,     edx
    
            !  mov      ecx,     ebx
            !  mov      ebx,     eax
            !  mov      eax,     ecx
    
            !  mov      edx,     ecx
            !  ror      eax,     6
            !  ror      ecx,     11
            !  ror      edx,     25
    
            !  add      ebx,     ki
            !  xor      eax,     ecx
            !  add      ebx,     wi
            !  xor      eax,     edx
    
            !  add      eax,     ebx
            !  add      eax,     [esi+28]
            !  movd     xmm6,    eax            ;xmm6 = t0
    
            !  mov      eax,     [esi]
            !  mov      ecx,     [esi+4]
            !  mov      ebx,     eax
    
            !  mov      edx,     eax
            !  and      eax,     ecx
    
            !  and      edx,     [esi+8]
            !  xor      eax,     edx
    
            !  and      ecx,     [esi+8]
            !  xor      eax,     ecx
            !  mov      edx,     eax
    
            !  mov      eax,     ebx
            !  mov      ecx,     ebx
            !  ror      eax,     2
            !  ror      ecx,     13
            !  ror      ebx,     22
            !  xor      eax,     ecx
            !  xor      eax,     ebx
    
            !  add      eax,     edx
            !  movd     xmm7,    eax            ;xmm7 = t1
    
            '  @s[7] = @s[6] : @s[6] = @s[5] : @s[5] = @s[4] : @s[4] = @s[3] + t0&
            '  @s[3] = @s[2] : @s[2] = @s[1] : @s[1] = @s[0] : @s[0] = t0& + t1&
            #ALIGN 16
            !  movdqa   xmm0,    [esi]
            !  movdqa   xmm1,    [esi+16]
            !  movd     xmm3,    [esi+12]       ;xmm3 = @s[3]
    
            !  pslldq   xmm1,    4
            !  pslldq   xmm0,    4
    
            !  paddd    xmm1,    xmm3           ;xmm1[0] = @s{3]
    
            !  paddd    xmm0,    xmm6           ;+t0
            !  paddd    xmm1,    xmm6           ;+t0
            !  paddd    xmm0,    xmm7           ;+t1
    
            !  movdqa   [esi+16],xmm1
            !  movdqa   [esi],   xmm0
    
            !  mov      eax,     i
            !  inc      eax
            !  test     eax,     &b111111       ;<64?
            !  mov      i,       eax
            !  jnz      CompressTop
    
            '-- Add current state s() to context
            '  for i& = 0 to 7 : [email protected][i&] = [email protected][i&] + @s[i&] : next i&
            !  mov      edi,     pstate
            !  movdqa   xmm0,    [edi]
            !  movdqa   xmm1,    [edi+16]
            !  paddd    xmm0,    [esi]
            !  paddd    xmm1,    [esi+16]
            !  movdqa   [edi],   xmm0
            !  movdqa   [edi+16],xmm1
    
            !  pop   ebx
            !  pop   edi
            !  pop   esi
        END METHOD
    
    
        '====================
        CLASS METHOD Compress64()
        #REGISTER NONE
        LOCAL k_array, s_array, w_array AS LONG
        LOCAL pstate, pdata, wi, ki, i AS LONG
    
            '-- Copy for inline assembler
            w_array  = m_ctx.w_array
            s_array  = m_ctx.s_array
            k_array  = m_ctx.k_array
            pstate   = m_ctx.pstate
            pdata    = m_ctx.pdata
    
            !  push     esi
            !  push     edi
            !  push     ebx
    
            '-- Copy current state into s&()
            !  mov      esi,     pstate           ;esi -> pm_ctx.state0
            !  mov      edi,     s_array
            !  movq     mm0,     [esi]
            !  movq     mm1,     [esi+8]
            !  movq     mm2,     [esi+16]
            !  movq     mm3,     [esi+24]
            !  movq     [edi],   mm0
            !  movq     [edi+8], mm1
            !  movq     [edi+16],mm2
            !  movq     [edi+24],mm3
    
            '-- Copy current data block to w&() w/little-to-big endian conversion
            !  mov      esi,     pdata
            !  mov      edi,     w_array
            !  mov      ecx,     %BLOCKSIZE
    
            #ALIGN 4
            BSwapCopyTop:
            !  sub      ecx,     4
            !  mov      eax,     [esi+ecx]
            !  sub      ecx,     4
            !  bswap    eax
            !  mov      edx,     [esi+ecx]
            !  mov      [edi+ecx+4], eax
            !  bswap    edx
            !  test     ecx,     ecx
            !  mov      [edi+ecx], edx
            !  jnz      BSwapCopyTop
    
            '-- Fill W[16to63]
            ! mov       esi,     w_array
            ! push      ebp
            ! mov       ebp,     16
            #ALIGN 4
            FillTop:
            !  mov      ebx,     ebp
            !  sub      ebx,     2
            !  mov      eax,     [esi+ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  sub      ebx,     13             ;prep for next access: (-2)+(-13) = -15
            !  ror      eax,     17
            !  ror      ecx,     19
            !  shr      edx,     10
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  mov      edi,     eax            ;edi = temp total
            !  mov      eax,     [esi+ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  ror      eax,     7
            !  ror      ecx,     18
            !  shr      edx,     3
            !  add      ebx,     8              ;= (-15)+8 = -7
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  add      edi,     eax
    
            !  mov      eax,     [esi+ebx*4]
            !  sub      ebx,     9              ;= (-7)+(-9) = -16
            !  add      edi,     eax
    
            !  mov      eax,     [esi+ebx*4]
            !  mov      ebx,     ebp
            !  add      eax,     edi
    
            !  inc      ebp
            !  mov      [esi+ebx*4], eax
            !  test     ebp,     &b111111       ;<64?
            !  jnz      FillTop
            !  pop      ebp
    
            '-- Compress: i& = 0 to 63
            !  xor      eax,     eax
            !  mov      esi,     s_array        ;here to CompressDone & END SUB: esi -> s[0]
            !  mov      i,       eax
            #ALIGN 4
            CompressTop:
            !  mov      ebx,     eax
            !  mov      edx,     w_array
            !  mov      eax,     [edx+ebx*4]
            !  mov      wi,      eax
            !  mov      edx,     k_array
            !  mov      eax,     [edx+ebx*4]
            !  mov      ki,      eax
    
            !  mov      eax,     [esi+16]
            !  mov      ecx,     [esi+20]
            !  mov      ebx,     eax
            !  mov      edx,     eax
            !  and      eax,     [esi+20]
    
            !  not      edx
            !  and      edx,     [esi+24]
            !  xor      eax,     edx
    
            !  mov      ecx,     ebx
            !  mov      ebx,     eax
            !  mov      eax,     ecx
    
            !  mov      edx,     ecx
            !  ror      eax,     6
            !  ror      ecx,     11
            !  ror      edx,     25
    
            !  add      ebx,     ki
            !  xor      eax,     ecx
            !  add      ebx,     wi
            !  xor      eax,     edx
    
            !  add      eax,     ebx
            !  add      eax,     [esi+28]
            !  movd     mm6,     eax            ;mm6 = t0
    
            !  mov      eax,     [esi]
            !  mov      ecx,     [esi+4]
            !  mov      ebx,     eax
    
            !  mov      edx,     eax
            !  and      eax,     ecx
    
            !  and      edx,     [esi+8]
            !  xor      eax,     edx
    
            !  and      ecx,     [esi+8]
            !  xor      eax,     ecx
            !  mov      edx,     eax
    
            !  mov      eax,     ebx
            !  mov      ecx,     ebx
            !  ror      eax,     2
            !  ror      ecx,     13
            !  ror      ebx,     22
            !  xor      eax,     ecx
            !  xor      eax,     ebx
    
            !  add      eax,     edx
            !  movd     mm7,     eax            ;mm7 = t1
    
            '  @s[7] = @s[6] : @s[6] = @s[5] : @s[5] = @s[4] : @s[4] = @s[3] + t0&
            '  @s[3] = @s[2] : @s[2] = @s[1] : @s[1] = @s[0] : @s[0] = t0& + t1&
            #ALIGN 8
            !  movq     mm3,     [esi+20]       ;mm3 = @s[6-5]
            !  movq     mm2,     [esi+12]       ;mm2 = @s[4-3]
            !  movq     mm1,     [esi+4]        ;mm1 = @s[2-1]
            !  movq     mm0,     [esi]          ;mm0 = @s[1-0]
    
            !  psllq    mm0,     32             ;mm0 = @s[0- ]
    
            !  paddd    mm2,     mm6            ;+t0
            !  paddd    mm0,     mm6            ;+t0
            !  paddd    mm0,     mm7            ;+t1
    
            !  movq     [esi+24],mm3
            !  movq     [esi+16],mm2
            !  movq     [esi+8], mm1
            !  movq     [esi],   mm0
    
            !  mov      eax,     i
            !  inc      eax
            !  test     eax,     &b111111       ;<64?
            !  mov      i,       eax
            !  jnz      CompressTop
    
            '-- Add current state s() to context
            '  for i& = 0 to 7 : [email protected][i&] = [email protected][i&] + @s[i&] : next i&
            !  mov      edi,     pstate
            !  movq     mm0,     [edi]
            !  movq     mm1,     [edi+8]
            !  movq     mm2,     [edi+16]
            !  movq     mm3,     [edi+24]
    
            !  paddd    mm0,     [esi]
            !  paddd    mm1,     [esi+8]
            !  paddd    mm2,     [esi+16]
            !  paddd    mm3,     [esi+24]
    
            !  movq     [edi],   mm0
            !  movq     [edi+8], mm1
            !  movq     [edi+16],mm2
            !  movq     [edi+24],mm3
    
            !  emms
            !  pop   ebx
            !  pop   edi
            !  pop   esi
        END METHOD
    
    
        '====================
        CLASS METHOD Compress32()
        #REGISTER NONE
        LOCAL k_array, s_array, w_array AS LONG
        LOCAL pstate, pdata AS LONG
        LOCAL t0, t1, wi, ki, i AS LONG
    
            '-- Copy for inline assembler
            w_array  = m_ctx.w_array
            s_array  = m_ctx.s_array
            k_array  = m_ctx.k_array
            pstate   = m_ctx.pstate
            pdata    = m_ctx.pdata
    
            !  push     esi
            !  push     edi
            !  push     ebx
    
            '-- Copy current state into s&()
            !  mov      esi,     pstate           ;esi -> pm_ctx.state0
            !  mov      edi,     s_array
            !  mov      ecx,     8
            !  cld
            !  rep      movsd
    
            '-- Copy current data block to w&() w/little-to-big endian conversion
            !  mov      esi,     pdata
            !  mov      edi,     w_array
            !  mov      ecx,     %BLOCKSIZE
            #ALIGN 4
            BSwapCopyTop:
            !  sub      ecx,     4
            !  mov      eax,     [esi+ecx]
            !  sub      ecx,     4
            !  bswap    eax
            !  mov      edx,     [esi+ecx]
            !  mov      [edi+ecx+4],eax
            !  bswap    edx
            !  test     ecx,     ecx
            !  mov      [edi+ecx],  edx
            !  jnz      BSwapCopyTop
    
            '-- Fill W[16to63]
            ! mov       esi,     w_array
            ! push      ebp
            ! mov       ebp,     16
            #ALIGN 4
            FillTop:
            !  mov      ebx,     ebp
            !  sub      ebx,     2
            !  mov      eax,     [esi]+[ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  sub      ebx,     13           ;prep for next access: (-2)+(-13) = -15
            !  ror      eax,     17
            !  ror      ecx,     19
            !  shr      edx,     10
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  mov      edi,     eax          ;edi = temp total
            !  mov      eax,     [esi]+[ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  ror      eax,     7
            !  ror      ecx,     18
            !  shr      edx,     3
            !  add      ebx,     8            ;= (-15)+8 = -7
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  add      edi,     eax
    
            !  mov      eax,     [esi]+[ebx*4]
            !  sub      ebx,     9            ;= (-7)+(-9) = -16
            !  add      edi,     eax
    
            !  mov      eax,     [esi]+[ebx*4]
            !  mov      ebx,     ebp
            !  add      eax,     edi
    
            !  inc      ebp
            !  mov      [esi]+[ebx*4], eax
            !  cmp      ebp,     63
            !  jg       FillDone
            !  jmp      FillTop
            FillDone:
            !  pop   ebp
    
            '-- Compress: i& = 0 to 63
            !  xor      eax,     eax
            !  mov      esi,     s_array            ;here to CompressDone & END SUB: esi -> s[0]
            !  mov      i,       eax
            #ALIGN 4
            CompressTop:
            !  mov      ebx,     eax
            !  mov      edx,     w_array
            !  mov      eax,     [edx]+[ebx*4]
            !  mov      wi,      eax
            !  mov      edx,     k_array&
            !  mov      eax,     [edx]+[ebx*4]
            !  mov      ki,      eax
    
            !  mov      eax,     [esi+16]
            !  mov      ecx,     [esi+20]
            !  mov      ebx,     eax
            !  mov      edx,     eax
            !  and      eax,     [esi+20]
    
            !  not      edx
            !  and      edx,     [esi+24]
            !  xor      eax,     edx
    
            !  mov      ecx,     ebx
            !  mov      ebx,     eax
            !  mov      eax,     ecx
    
            !  mov      edx,     ecx
            !  ror      eax,     6
            !  ror      ecx,     11
            !  ror      edx,     25
    
            !  add      ebx,     ki
            !  xor      eax,     ecx
            !  add      ebx,     wi
            !  xor      eax,     edx
    
            !  add      eax,     ebx
            !  add      eax,     [esi+28]
    
            !  mov      t0&,     eax
    
            !  mov      eax,     [esi]
            !  mov      ecx,     [esi+4]
            !  mov      ebx,     eax
    
            !  mov      edx,     eax
            !  and      eax,     ecx
    
            !  and      edx,     [esi+8]
            !  xor      eax,     edx
    
            !  and      ecx,     [esi+8]
            !  xor      eax,     ecx
            !  mov      edx,     eax
    
            !  mov      eax,     ebx
            !  mov      ecx,     ebx
            !  ror      eax,     2
            !  ror      ecx,     13
            !  ror      ebx,     22
            !  xor      eax,     ecx
            !  xor      eax,     ebx
    
            !  add      eax,     edx
            !  mov      t1,      eax
    
            '  @s[7] = @s[6] : @s[6] = @s[5] : @s[5] = @s[4] : @s[4] = @s[3] + t0&
            '  @s[3] = @s[2] : @s[2] = @s[1] : @s[1] = @s[0] : @s[0] = t0& + t1&
            !  mov      edi,     esi
            !  mov      ecx,     t0
    
            !  mov      eax,     [esi+24]     ;@s[7] = @s[6]
            !  mov      ebx,     [esi+20]     ;@s[6] = @s[5]
            !  mov      edx,     [esi+16]     ;@s[5] = @s[4]
            !  mov      [edi+28], eax
            !  mov      [edi+24], ebx
            !  mov      [edi+20], edx
    
            !  mov      eax,     [esi+12]     ;@s[4] = @s[3] + T0&
            !  mov      ebx,     [esi+8]      ;@s[3] = @s[2]
            !  add      eax,     ecx
            !  mov      edx,     [esi]        ;@s[1] = @s[0]
            !  mov      [edi+12],ebx
            !  mov      [edi+16],eax
            !  mov      ebx, ecx          ;@s[0] = T0& + T1&
            !  mov      eax, [esi+4]      ;@s[2] = @s[1]
            !  mov      [edi+4], edx
            !  add      ebx, t1
            !  mov      [edi+8], eax
            !  mov      [edi],   ebx
    
            !  mov      eax,     i
            !  inc      eax
            !  test     eax,     &b111111       ;<64?
            !  mov      i,       eax
            !  jnz      CompressTop
    
            '-- Add current state s() to context
            '  for i& = 0 to 7 : [email protected][i&] = [email protected][i&] + @s[i&] : next i&
            !  mov      edi, pstate
            !  mov      ecx, %HASHLEN
            #ALIGN 4
            AddCopyTop:
            !  sub      ecx,     4
            !  mov      eax,     [edi+ecx]
            !  add      eax,     [esi+ecx]
            !  mov      [edi+ecx], eax
            !  test     ecx,     ecx
            !  jnz      AddCopyTop
    
            !  pop      ebx
            !  pop      edi
            !  pop      esi
        END METHOD
    
    
        '====================
        '-- Expects parameter Hash to point to buffer of correct size of %HASHLEN bytes (256bits\8)
        CLASS METHOD calcBuffer (BYVAL hData AS DWORD, BYVAL Length AS DWORD, BYVAL hHash AS DWORD) AS LONG
        REGISTER i AS DWORD
        LOCAL pstate     AS LONG
        LOCAL lastbuff   AS STRING
        LOCAL DataBuffer AS BYTE PTR
        LOCAL phash      AS DWORD PTR
    
            DataBuffer    = hData
            m_hHash       = hHash
            i             = Length AND (%BLOCKSIZE-1)
            lastbuff      = PEEK$((DataBuffer+Length)-i, i)
            lastbuff      = lastbuff + me.MakePadding(Length)
            m_ctx.lendata = Length
            m_ctx.pdata   = DataBuffer
    
            i = Length AND (NOT %BLOCKSIZE-1)
            DO WHILE i > 0
                SELECT CASE m_compress
                CASE 128:  CALL me.Compress128()
                CASE  64:  CALL me.Compress64()
                CASE ELSE: CALL me.Compress32()
                END SELECT
                m_ctx.pdata = m_ctx.pdata + %BLOCKSIZE
                i = i - %BLOCKSIZE
            LOOP
    
            m_ctx.pdata = STRPTR(lastbuff)
            m_ctx.lendata = LEN(lastbuff)
    
            DO WHILE m_ctx.lendata > 0
                SELECT CASE m_compress
                CASE 128:  CALL me.Compress128()
                CASE  64:  CALL me.Compress64()
                CASE ELSE: CALL me.Compress32()
                END SELECT
                m_ctx.pdata = m_ctx.pdata + %BLOCKSIZE
                m_ctx.lendata = m_ctx.lendata - %BLOCKSIZE
            LOOP
    
            phash  = m_hHash
            pstate = m_ctx.pstate
    
            '-- Copy current state from s&() to Hash
            'for i = 0 to (%HASHLEN\4)-1 : @phash[i] = [email protected][i] : next i: exit method
    
            #IF %RETURN_LITTLE_ENDIAN
            !  push  edi
            !  mov   edx,  pstate           ;esi -> m_ctx.state0
            !  mov   edi,  phash
            !  mov   ecx,  (%HASHLEN\4)-1   ;here -1
            #ALIGN 4
            LoopTop:
            !  mov   eax,  [edx+ecx*4]
            !  bswap eax
            !  mov   [edi+ecx*4],eax
            !  dec   ecx
            !  jns   LoopTop
            !  pop   edi
            #ELSE
            !  push  esi
            !  push  edi
            !  mov   esi,  pstate           ;esi -> m_ctx.state0
            !  mov   edi,  phash
            !  mov   ecx,  8
            !  cld
            !  rep   movsd
            !  pop   edi
            !  pop   esi
            #ENDIF
        END METHOD
    
    
        '====================
        '-- Returns 0 on success or PB (not OS) error code
        CLASS METHOD calcFileOpen (pFile AS WSTRINGZ, BYVAL hHash AS DWORD) AS LONG
        ON ERROR GOTO FN_ERR
        LOCAL ecode  AS LONG
    
            IF ( m_infile <> 0 ) THEN METHOD = %ERR_FILEISOPEN : EXIT METHOD
            IF ISFILE(pFile) = 0 THEN METHOD = %ERR_FILENOTFOUND : EXIT METHOD
    
            m_buffer      = STRING$(%FILE_BUFFERSIZE, 0)
            m_maxstring   = %FILE_BUFFERSIZE
            m_ctx.lendata = %BLOCKSIZE
            m_lastpass    = 0
            m_hHash       = hHash
            m_infile      = FREEFILE
    
            OPEN pFile FOR BINARY LOCK SHARED AS m_infile BASE=0
    
            m_filesize    = LOF(m_infile)
            m_bytesleft   = m_filesize
            m_padding     = me.MakePadding (m_bytesleft)
    
        FN_EXIT:
            METHOD = ecode
            EXIT METHOD
    
        FN_ERR:
            ecode = ERRCLEAR
            RESUME FN_EXIT
        END METHOD
    
    
        CLASS METHOD calcFileProcess() AS LONG
        REGISTER i AS LONG
    
            IF ( m_lastpass < 1 ) THEN
                'Resize if necessary & flag final buffer
                IF m_bytesleft =< m_maxstring THEN
                    m_maxstring = CLNG(m_bytesleft)
                    m_buffer = STRING$(m_maxstring, 0)
                    INCR m_lastpass
                END IF
                GET m_infile,, m_buffer : IF ERR THEN METHOD = ERRCLEAR: EXIT METHOD
                IF m_lastpass THEN m_buffer = m_buffer + m_padding
                m_ctx.pdata = STRPTR(m_buffer)
                SELECT CASE m_compress
                CASE 128
                    FOR i = 1 TO (LEN(m_buffer)\%BLOCKSIZE)
                        CALL me.Compress128()
                        m_ctx.pdata = m_ctx.pdata + %BLOCKSIZE
                    NEXT i
                CASE 64
                    FOR i = 1 TO (LEN(m_buffer)\%BLOCKSIZE)
                        CALL me.Compress64()
                        m_ctx.pdata = m_ctx.pdata + %BLOCKSIZE
                    NEXT i
                CASE ELSE
                    FOR i = 1 TO (LEN(m_buffer)\%BLOCKSIZE)
                        CALL me.Compress32()
                        m_ctx.pdata = m_ctx.pdata + %BLOCKSIZE
                    NEXT i
                END SELECT
                m_bytesleft = m_bytesleft - m_maxstring
            END IF
    
            METHOD = 0
        END METHOD
    
    
        CLASS METHOD calcFileClose() AS LONG
        LOCAL pstate AS LONG
        LOCAL phash  AS DWORD PTR
    
            IF ( m_infile = 0 ) THEN EXIT METHOD
    
            CLOSE m_infile
            IF ERR THEN METHOD = ERRCLEAR: EXIT METHOD
            m_infile = 0
    
            IF ( m_lastpass = 0 ) THEN EXIT METHOD
    
            phash  = m_hHash
            pstate = m_ctx.pstate
    
            '-- Copy current state
            'LOCAL i AS LONG : for i = 0 to (%HASHLEN\4)-1 : @phash[i] = [email protected][i] : next i : exit method
    
            #IF %RETURN_LITTLE_ENDIAN
            !  push  edi
            !  mov   edx,  pstate           ;esi -> m_ctx.state0
            !  mov   edi,  phash
            !  mov   ecx,  (%HASHLEN\4)-1   ;here -1
            #ALIGN 4
            LoopTop:
            !  mov   eax,  [edx+ecx*4]
            !  bswap eax
            !  mov   [edi+ecx*4],eax
            !  dec   ecx
            !  jns   LoopTop
            !  pop   edi
            #ELSE
            !  push  esi
            !  push  edi
            !  mov   esi,  pstate           ;esi -> m_ctx.state0
            !  mov   edi,  phash
            !  mov   ecx,  8
            !  cld
            !  rep   movsd
            !  pop   edi
            !  pop   esi
            #ENDIF
    
            METHOD = 0
        END METHOD
    
    
        '=========================
        '-- Creates the necessary string to append to targeted data buffer
        CLASS METHOD MakePadding (BYVAL TotalBytes AS QUAD) AS STRING
        REGISTER i AS LONG, padBytes AS LONG
        LOCAL buffbits AS QUAD
        LOCAL padding  AS STRING
        LOCAL pbyte1   AS BYTE PTR
        LOCAL pbyte2   AS BYTE PTR
    
            buffbits = TotalBytes * 8
            padding  = NUL$(8)
            pbyte1   = STRPTR(padding)
            pbyte2   = VARPTR(buffbits)
    
            '-- Copy bytes in reverse
            FOR i = 0 TO 7
               @pbyte1[i] = @pbyte2[7 - i]
            NEXT i
    
            padBytes = %BLOCKSIZE - ((TotalBytes+9) AND (%BLOCKSIZE-1))
            METHOD = CHR$(&h80) + NUL$(padBytes) + padding
        END METHOD
    
    
        '===================
        CLASS METHOD HasSSE2() AS LONG
        !  mov   eax, 1
        !  cpuid
        !  xor   eax, eax
        !  test  edx, &h04000000   ;bit 26
        !  setnz al                ;rem to force downgrade to MMX
        !  mov   METHOD, eax
        END METHOD
    
    
        '===================
        CLASS METHOD HasMMX() AS LONG
        !  mov      eax,  1
        !  cpuid
        !  xor      eax,  eax
        !  test     edx,  &h800000 ;bit 23
        !  setnz    al             ;rem to force downgrade to 32-bit
        !  mov      METHOD, eax
        END METHOD
    
    
        '===================
        CLASS METHOD CREATE()
            IF me.HasSSE2() THEN
                m_compress = 128
            ELSEIF me.HasMMX() THEN
                m_compress = 64
            ELSE
                m_compress = 32
            END IF
        END METHOD
    
    
        '===================
        CLASS METHOD DESTROY()
        END METHOD
    
    
        ' ====================================================
    
        INTERFACE iSHA256hash : INHERIT IUNKNOWN
    
        ' ====================================================
    
    
            ' -------------------------------------------------------------------------------
            ' This properties was intended for files with progress indicator.
            ' -------------------------------------------------------------------------------
            PROPERTY GET FileSize () AS QUAD
                PROPERTY = m_filesize
            END PROPERTY
    
            PROPERTY GET BytesInProcess () AS QUAD
                PROPERTY = m_bytesleft
            END PROPERTY
    
            PROPERTY GET Percent () AS LONG
                PROPERTY = ( (m_filesize - m_bytesleft) * 100 ) / m_filesize
            END PROPERTY
    
            PROPERTY GET fLastpass () AS LONG
                PROPERTY = m_lastpass
            END PROPERTY
    
    
            ' -------------------------------------------------------------------------------
            ' Methods that might be needed.
            ' -------------------------------------------------------------------------------
            METHOD ByteArrayToHexString (BYVAL bArrayPtr AS DWORD) AS STRING
            LOCAL bHash AS BYTE PTR
            LOCAL sHash AS STRING
            LOCAL i     AS LONG
                IF ( bArrayPtr ) THEN
                    bHash = bArrayPtr
                    FOR i = 0 TO %HASHLEN-1
                        sHash = sHash + HEX$(@bHash[i],2)
                    NEXT i
                END IF
                METHOD = LCASE$(sHash)
            END METHOD
    
            METHOD HexStringToByteArray (BYVAL HexString AS STRING, BYVAL bArrayPtr AS DWORD)
            LOCAL bHash AS BYTE PTR
            LOCAL i,j   AS LONG
                IF ( bArrayPtr ) AND ( LEN(HexString) <= %HASHLEN * 2 ) THEN
                    bHash = bArrayPtr
                    FOR i = 1 TO LEN(HexString) STEP 2
                        @bHash[j] = VAL("&h" + MID$(HexString,i,2))
                        INCR j
                    NEXT i
                END IF
            END METHOD
    
            ' -------------------------------------------------------------------------------
            ' This methods was intended for files with progress indicator.
            ' -------------------------------------------------------------------------------
            METHOD calc_fileOpen (pFile AS WSTRINGZ,BYVAL hashPtr AS DWORD) AS LONG
                CALL me.Init()
                METHOD = me.calcFileOpen (pFile, hashPtr)
            END METHOD
    
            METHOD calc_fileProcess() AS LONG
                METHOD = me.calcFileProcess()
            END METHOD
    
            METHOD calc_fileClose() AS LONG
                METHOD = me.calcFileClose()
            END METHOD
    
            ' -------------------------------------------------------------------------------
            ' This method is for files and if not needed progress bar.
            ' -------------------------------------------------------------------------------
            METHOD calc_file (pFile AS WSTRINGZ,BYVAL hashPtr AS DWORD) AS LONG
            LOCAL ecode AS LONG
                CALL me.Init()
                ecode = me.calcFileOpen (pFile, hashPtr)
                WHILE ( (ecode = 0) AND (m_lastpass = 0) )
                    ecode = me.calcFileProcess()
                WEND
                CALL me.calcFileClose()
                METHOD = ecode
            END METHOD
    
            ' -------------------------------------------------------------------------------
            ' This method is intended for strings, or byte arrays.
            ' -------------------------------------------------------------------------------
            METHOD calc_buffer (BYVAL dataPtr AS LONG, BYVAL dataLen AS DWORD, BYVAL hashPtr AS DWORD)
                CALL me.Init()
                CALL me.calcBuffer (dataPtr, dataLen, hashPtr)
            END METHOD
    
        END INTERFACE
    
    END CLASS
    Program for test

    Code:
    [COLOR="YellowGreen"][B]' SHA256hash.bas[/B][/COLOR]
    
    #COMPILER PBWIN 10
    #COMPILE EXE "SHA256hash.exe"
    #DIM ALL
    
    
    %UNICODE = 1
    #INCLUDE "SHA256hash.inc"
    
    
    $REFERENCE_FILE = ""
    
    
    FUNCTION GetFile (pFile AS WSTRINGZ, a() AS BYTE) AS QUAD
    LOCAL bytes AS QUAD
    LOCAL f     AS LONG
    
        IF ( ISFILE(pFile) ) THEN
            f = FREEFILE
            OPEN pFile FOR BINARY AS #f
                bytes = LOF(#f)
                IF ( bytes > 0 AND bytes < 1024*1024*1000 ) THEN
                    REDIM a(1 TO bytes)
                    GET #f,,a()
                END IF
            CLOSE #f
        END IF
    
        FUNCTION = bytes
    END FUNCTION
    
    
    FUNCTION PBMAIN () AS LONG
    LOCAL o         AS iSHA256hash
    LOCAL hTxt      AS LONG
    LOCAL file      AS WSTRINGZ * %MAX_PATH
    LOCAL hash      AS STRING
    LOCAL bytes     AS QUAD
    LOCAL ecode     AS LONG
    LOCAL oldper    AS LONG
    LOCAL time      AS SINGLE
    LOCAL refresh   AS SINGLE
    LOCAL stext     AS STRING
    
        DIM afile(0) AS BYTE
    
        file = TRIM$(COMMAND$,$$DQ)
        IF file = "" THEN file = $REFERENCE_FILE
        IF file = "" THEN DISPLAY OPENFILE 0, , , "", "", CHR$("All files (*.*)", 0 , "*.*", 0), "", "", %OFN_EXPLORER OR %OFN_FILEMUSTEXIST OR %OFN_ENABLESIZING TO file
        IF file = "" THEN EXIT FUNCTION
    
        bytes = GetFile (file, afile())
    
        TXT.WINDOW("SHA256hash - " + file + " (" + FORMAT$(bytes,"#,") + " Bytes)", 150, 100) TO hTxt
    
        ' -------------------------------------------------------------------------------------
        o = CLASS "cSHA256hash"
    
        DIM ahash(1 TO 32) AS BYTE
    
        DIM atext(1 TO 5)  AS BYTE
        ARRAY ASSIGN atext() = ASC("H"), ASC("e"), ASC("l"), ASC("l"), ASC("o")
    
        CALL o.calc_buffer (VARPTR(atext(1)), 5, VARPTR(ahash(1)))
        hash = o.ByteArrayToHexString (VARPTR(ahash(1)))
    
        TXT.PRINT LEFT$(hash,32) + "   Hello"
        TXT.PRINT RIGHT$(hash,32)
        TXT.PRINT ""
        TXT.PRINT "185f8db32271fe25f561a6fc938b2e26   Reference"
        TXT.PRINT "4306ec304eda518007d1764826381969"
        TXT.PRINT ""
        TXT.PRINT "---------------------------------------------"
        TXT.PRINT ""
    
        stext = "World"
    
        CALL o.calc_buffer (STRPTR(stext), LEN(stext), VARPTR(ahash(1)))
        hash = o.ByteArrayToHexString (VARPTR(ahash(1)))
    
        TXT.PRINT LEFT$(hash,32) + "   World"
        TXT.PRINT RIGHT$(hash,32)
        TXT.PRINT ""
        TXT.PRINT "78ae647dc5544d227130a0682a51e30b   Reference"
        TXT.PRINT "c7777fbb6d8a8f17007463a3ecd1d524"
        TXT.PRINT ""
        TXT.PRINT ""
        TXT.PRINT ""
        TXT.PRINT "Press any key..."
        TXT.WAITKEY$
        TXT.CLS
    
    
    
        ' -------------------------------------------------------------------------------------
        RESET ahash()
        TXT.PRINT file + " (" + FORMAT$(bytes,"#,") + " Bytes)"
    
        time  = TIMER
        ecode = o.calc_file (file, VARPTR(ahash(1)))
        time  = TIMER-time
        hash  = o.ByteArrayToHexString (VARPTR(ahash(1)))
    
        TXT.PRINT ""
        TXT.PRINT LEFT$(hash,32) + "   calc_file()"
        TXT.PRINT RIGHT$(hash,32)
        TXT.PRINT ">>> Time: " + FORMAT$(time,"#.###") + " s"
        IF LCASE$(file) = LCASE$($REFERENCE_FILE) THEN
            TXT.PRINT ""
            TXT.PRINT "671c3f49aab0c1f4018aa3d2faec85c8   Reference"
            TXT.PRINT "196c8b93186e931a8099dcb0df9f7a44"
        END IF
    
        ' -------------------------------------------------------------------------------------
        IF bytes < 1024*1024*1000 THEN
            RESET ahash()
    
            time = TIMER
            CALL o.calc_buffer (VARPTR(afile(1)), bytes, VARPTR(ahash(1)))
            time = TIMER-time
            hash = o.ByteArrayToHexString (VARPTR(ahash(1)))
    
            TXT.PRINT ""
            TXT.PRINT LEFT$(hash,32) + "   calc_buffer()"
            TXT.PRINT RIGHT$(hash,32)
            TXT.PRINT ">>> Time: " + FORMAT$(time,"#.###") + " s"
        END IF
    
        TXT.PRINT ""
        TXT.PRINT ""
        TXT.PRINT "Press any key..."
        TXT.WAITKEY$
        TXT.CLS
    
    
    
        ' -------------------------------------------------------------------------------------
        TXT.PRINT LEFT$(hash,32) + "   last hash"
        TXT.PRINT RIGHT$(hash,32)
        TXT.PRINT ""
        TXT.PRINT "----------------------------------------------------------------"
        TXT.PRINT ""
        RESET ahash()
    
        refresh = TIMER
        time    = TIMER
        ecode   = o.calc_fileOpen (file, VARPTR(ahash(1))) : IF ecode <> 0 THEN GOTO FN_ERR
            TXT.PRINT file + " (" + FORMAT$(o.FileSize,"#,") + " Bytes)"
            TXT.PRINT ""
            WHILE ( (ecode = 0) AND (o.fLastpass = 0) )
                ecode  = o.calc_fileProcess() : IF ecode <> 0 THEN GOTO FN_ERR
                IF ( (TIMER-refresh) > 1.9 ) THEN
                    refresh = TIMER
                    IF ( oldper <> o.Percent ) THEN
                        oldper = o.Percent
                        TXT.PRINT FORMAT$(o.Percent,"000") + "% ";
                    END IF
                END IF
                IF TXT.INSTAT THEN
                    IF TXT.INKEY$ = $ESC THEN
                        EXIT LOOP
                    END IF
                END IF
            WEND
            TXT.PRINT ""
        ecode = o.calc_fileClose() : IF ecode <> 0 THEN GOTO FN_ERR
        time  = TIMER-time
        hash  = o.ByteArrayToHexString (VARPTR(ahash(1)))
    
        TXT.PRINT ""
        TXT.PRINT LEFT$(hash,32)
        TXT.PRINT RIGHT$(hash,32)
        TXT.PRINT ">>> Time: " + FORMAT$(time,"#.###") + " s"
        IF LCASE$(file) = LCASE$($REFERENCE_FILE) THEN
            TXT.PRINT ""
            TXT.PRINT "671c3f49aab0c1f4018aa3d2faec85c8   Reference"
            TXT.PRINT "196c8b93186e931a8099dcb0df9f7a44"
        END IF
    
        o = NOTHING
    FN_EXIT:
        TXT.PRINT ""
        TXT.PRINT ""
        TXT.PRINT ""
        TXT.PRINT "Press any key..."
        TXT.WAITKEY$
        EXIT FUNCTION
    
    FN_ERR:
        TXT.PRINT ""
        TXT.PRINT ""
        TXT.PRINT ERROR$(ecode)
        TXT.PRINT ""
        TXT.PRINT ""
        TXT.PRINT "Press any key..."
        TXT.WAITKEY$
    END FUNCTION

  • #2
    Here is a power-thread-class.

    PowerSHA256.inc
    Code:
    [COLOR="DarkGreen"]'=====================================================================
    ' This class 'PowerSHA256.inc' was generated
    ' from the following code:
    '---------------------------------------------------------------------
    '-- SHA256c.INC
    '-- Compiles with either PBWIN 8/9+ or PBCC 4/5+
    '-- WIN32 API not required
    '-- Uses no global data
    '-- http://www.powerbasic.com/support/pbforums/showthread.php?t=39850
    '=====================================================================
    ' The class can also be compiled as SLL:
    '---------------------------------------------------------------------
    ' #COMPILE SLL "PowerSHA256.sll"
    ' #DIM ALL
    ' %UNICODE = 1
    ' #INCLUDE "win32api.inc"
    '=====================================================================[/COLOR]
    
    
    $C_POWER_SHA256_DATA_CID             = GUID$("{4782EBC2-0B2A-4B57-B77C-370CAC8B3E44}")
    $C_POWER_SHA256_DATA_IID             = GUID$("{2278E307-804F-4C0B-A409-D788EB177A33}")
    $C_POWER_SHA256_MAIN_CID             = GUID$("{AA82B487-2E8C-4200-AE4C-17E0462E0DA9}")
    $C_POWER_SHA256_MAIN_IID             = GUID$("{FBAD1425-DEF2-4DEC-8C69-E1B7242490EB}")
    
    
    %C_POWER_SHA256_RETURN_LITTLE_ENDIAN = %TRUE                 '-- Set to %FALSE to return big-endian hash$ (as in 2001 code)
    %C_POWER_SHA256_ALIGNMENT            = 16
    %C_POWER_SHA256_HASHLEN              = 32                             'bytes
    %C_POWER_SHA256_BLOCKSIZE            = 64                             'bytes
    %C_POWER_SHA256_FILE_BUFFERSIZE      = 32768                          'bytes
    %C_POWER_SHA256_S_ARRAY_SIZE         = %C_POWER_SHA256_HASHLEN
    %C_POWER_SHA256_W_ARRAY_SIZE         = %C_POWER_SHA256_BLOCKSIZE * 4
    
    
    TYPE SHA256_CONTEXT
       state       AS STRING * (%C_POWER_SHA256_HASHLEN + %C_POWER_SHA256_ALIGNMENT)
       pstate      AS DWORD PTR
       pdata       AS BYTE PTR
       lendata     AS DWORD
       HasSSE2     AS LONG
       HasMMX      AS LONG
       k_array     AS LONG PTR
       s_array     AS LONG PTR
       w_array     AS LONG PTR
       Workspace   AS STRING * (%C_POWER_SHA256_S_ARRAY_SIZE + %C_POWER_SHA256_W_ARRAY_SIZE + (%C_POWER_SHA256_ALIGNMENT * 2))  'w_array&() + s+_array&()
    END TYPE
    
    
    MACRO align(p,alignment)=((p+(alignment-1)) AND (NOT(alignment-1)))
    
    
    ASMDATA Init_Values
        DD  &h6A09E667???, &hBB67AE85???, &h3C6EF372???, &hA54FF53A???
        DD  &h510E527F???, &h9B05688C???, &h1F83D9AB???, &h5BE0CD19???
    END ASMDATA
    
    
    ASMDATA K_Array_Data
        DD  &h428a2f98???, &h71374491???, &hb5c0fbcf???, &he9b5dba5???, &h3956c25b???, &h59f111f1???
        DD  &h923f82a4???, &hab1c5ed5???, &hd807aa98???, &h12835b01???, &h243185be???, &h550c7dc3???
        DD  &h72be5d74???, &h80deb1fe???, &h9bdc06a7???, &hc19bf174???, &he49b69c1???, &hefbe4786???
        DD  &h0fc19dc6???, &h240ca1cc???, &h2de92c6f???, &h4a7484aa???, &h5cb0a9dc???, &h76f988da???
        DD  &h983e5152???, &ha831c66d???, &hb00327c8???, &hbf597fc7???, &hc6e00bf3???, &hd5a79147???
        DD  &h06ca6351???, &h14292967???, &h27b70a85???, &h2e1b2138???, &h4d2c6dfc???, &h53380d13???
        DD  &h650a7354???, &h766a0abb???, &h81c2c92e???, &h92722c85???, &ha2bfe8a1???, &ha81a664b???
        DD  &hc24b8b70???, &hc76c51a3???, &hd192e819???, &hd6990624???, &hf40e3585???, &h106aa070???
        DD  &h19a4c116???, &h1e376c08???, &h2748774c???, &h34b0bcb5???, &h391c0cb3???, &h4ed8aa4a???
        DD  &h5b9cca4f???, &h682e6ff3???, &h748f82ee???, &h78a5636f???, &h84c87814???, &h8cc70208???
        DD  &h90befffa???, &ha4506ceb???, &hbef9a3f7???, &hc67178f2???
    END ASMDATA
    
    
    CLASS cSHA256main $C_POWER_SHA256_MAIN_CID COMMON
    INSTANCE ThreadParam          AS DWORD
    INSTANCE cDataFace            AS iSHA256data
    INSTANCE m_hashmem            AS STRING * %C_POWER_SHA256_HASHLEN
    INSTANCE m_ctx                AS SHA256_CONTEXT
    INSTANCE m_compress           AS LONG
    INSTANCE m_bytesleft          AS QUAD
    INSTANCE m_buffer             AS STRING
    INSTANCE m_padding            AS STRING
    INSTANCE m_hashptr            AS DWORD
    INSTANCE m_hFile              AS DWORD
    INSTANCE m_lastpass           AS LONG
    INSTANCE m_maxstring          AS LONG
    INSTANCE m_Cancel             AS LONG
    INSTANCE m_Status_Index       AS LONG
    INSTANCE m_Status_Bytes       AS QUAD
    
        THREAD METHOD MAIN() AS LONG
        LOCAL file AS WSTRINGZ * %MAX_PATH
        LOCAL hash AS STRING * %C_POWER_SHA256_HASHLEN * 2
        LOCAL aerr AS LONG
        LOCAL i    AS LONG
        LOCAL lb   AS LONG
        LOCAL ub   AS LONG
            lb = cDataFace.p_lbound
            ub = cDataFace.p_ubound
            FOR i = lb TO ub
                m_Status_Index = i
                file   = cDataFace.GetFile(i)
                aerr   = me.calcFile (file)
                hash   = me.HexHash()
                CALL cDataFace.SetHash(i,hash)
                CALL cDataFace.SetError(i,aerr)
                IF ( ISTRUE m_Cancel ) THEN EXIT METHOD
            NEXT i
        END METHOD
    
        '====================
        CLASS METHOD HexHash() THREADSAFE AS STRING
        LOCAL bHash AS BYTE PTR
        LOCAL rHash AS STRING
        LOCAL i     AS LONG
            bHash = m_hashptr
            FOR i = 0 TO %C_POWER_SHA256_HASHLEN - 1
                rHash = rHash + HEX$(@bHash[i],2)
            NEXT i
            METHOD = LCASE$(rHash)
        END METHOD
    
        '====================
        CLASS METHOD Compress128()
        #REGISTER NONE
        LOCAL k_array, s_array, w_array AS LONG
        LOCAL pstate, pdata, wi, ki, i AS LONG
    
            '-- Copy for inline assembler
            w_array  = m_ctx.w_array
            s_array  = m_ctx.s_array
            k_array  = m_ctx.k_array
            pstate   = m_ctx.pstate
            pdata    = m_ctx.pdata
    
            !  push     esi
            !  push     edi
            !  push     ebx
    
            '-- Copy current state into s&()
            !  mov      esi,     pstate           ;esi -> pm_ctx.state0
            !  mov      edi,     s_array
            !  movdqa   xmm0,    [esi]
            !  movdqa   xmm1,    [esi+16]
            !  movdqa   [edi],   xmm0
            !  movdqa   [edi+16],xmm1
    
            '-- Copy current data block to w&() w/little-to-big endian conversion
            !  mov      esi,     pdata
            !  mov      edi,     w_array
            !  movdqu   xmm0,    [esi]
            !  movdqu   xmm2,    [esi+16]
            !  movdqu   xmm4,    [esi+32]
            !  movdqu   xmm6,    [esi+48]
    
            !  pshufhw  xmm1,    xmm0, &b10110001
            !  pshufhw  xmm3,    xmm2, &b10110001
            !  pshufhw  xmm5,    xmm4, &b10110001
            !  pshufhw  xmm7,    xmm6, &b10110001
    
            !  pshuflw  xmm0,    xmm1, &b10110001
            !  pshuflw  xmm2,    xmm3, &b10110001
            !  pshuflw  xmm4,    xmm5, &b10110001
            !  pshuflw  xmm6,    xmm7, &b10110001
    
            !  movdqa   xmm1,    xmm0
            !  movdqa   xmm3,    xmm2
            !  movdqa   xmm5,    xmm4
            !  movdqa   xmm7,    xmm6
    
            !  psllw    xmm0,    8
            !  psllw    xmm2,    8
            !  psllw    xmm4,    8
            !  psllw    xmm6,    8
    
            !  psrlw    xmm1,    8
            !  psrlw    xmm3,    8
            !  psrlw    xmm5,    8
            !  psrlw    xmm7,    8
    
            !  por      xmm0,    xmm1
            !  por      xmm2,    xmm3
            !  por      xmm4,    xmm5
            !  por      xmm6,    xmm7
    
            !  movdqa   [edi],   xmm0
            !  movdqa   [edi+16],xmm2
            !  movdqa   [edi+32],xmm4
            !  movdqa   [edi+48],xmm6
    
            '-- Fill W[16to63]
            ! mov       esi,     w_array
            ! push      ebp
            ! mov       ebp,     16
            #ALIGN 4
            FillTop:
            !  mov      ebx,     ebp
            !  sub      ebx,     2
            !  mov      eax,     [esi+ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  sub      ebx,     13             ;prep for next access: (-2)+(-13) = -15
            !  ror      eax,     17
            !  ror      ecx,     19
            !  shr      edx,     10
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  mov      edi,     eax            ;edi = temp total
            !  mov      eax,     [esi+ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  ror      eax,     7
            !  ror      ecx,     18
            !  shr      edx,     3
            !  add      ebx,     8              ;= (-15)+8 = -7
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  add      edi,     eax
    
            !  mov      eax,     [esi+ebx*4]
            !  sub      ebx,     9              ;= (-7)+(-9) = -16
            !  add      edi,     eax
    
            !  mov      eax,     [esi+ebx*4]
            !  mov      ebx,     ebp
            !  add      eax,     edi
    
            !  inc      ebp
            !  mov      [esi+ebx*4], eax
            !  test     ebp,     &b111111       ;<64?
            !  jnz      FillTop
            !  pop      ebp
    
            '-- Compress: i& = 0 to 63
            !  xor      eax,     eax
            !  mov      esi,     s_array        ;here to CompressDone & END SUB: esi -> s[0]
            !  mov      i,       eax
            #ALIGN 4
            CompressTop:
            !  mov      ebx,     eax
            !  mov      edx,     w_array
            !  mov      eax,     [edx+ebx*4]
            !  mov      wi,      eax
            !  mov      edx,     k_array
            !  mov      eax,     [edx+ebx*4]
            !  mov      ki,      eax
    
            !  mov      eax,     [esi+16]
            !  mov      ecx,     [esi+20]
            !  mov      ebx,     eax
            !  mov      edx,     eax
            !  and      eax,     [esi+20]
    
            !  not      edx
            !  and      edx,     [esi+24]
            !  xor      eax,     edx
    
            !  mov      ecx,     ebx
            !  mov      ebx,     eax
            !  mov      eax,     ecx
    
            !  mov      edx,     ecx
            !  ror      eax,     6
            !  ror      ecx,     11
            !  ror      edx,     25
    
            !  add      ebx,     ki
            !  xor      eax,     ecx
            !  add      ebx,     wi
            !  xor      eax,     edx
    
            !  add      eax,     ebx
            !  add      eax,     [esi+28]
            !  movd     xmm6,    eax            ;xmm6 = t0
    
            !  mov      eax,     [esi]
            !  mov      ecx,     [esi+4]
            !  mov      ebx,     eax
    
            !  mov      edx,     eax
            !  and      eax,     ecx
    
            !  and      edx,     [esi+8]
            !  xor      eax,     edx
    
            !  and      ecx,     [esi+8]
            !  xor      eax,     ecx
            !  mov      edx,     eax
    
            !  mov      eax,     ebx
            !  mov      ecx,     ebx
            !  ror      eax,     2
            !  ror      ecx,     13
            !  ror      ebx,     22
            !  xor      eax,     ecx
            !  xor      eax,     ebx
    
            !  add      eax,     edx
            !  movd     xmm7,    eax            ;xmm7 = t1
    
            '  @s[7] = @s[6] : @s[6] = @s[5] : @s[5] = @s[4] : @s[4] = @s[3] + t0&
            '  @s[3] = @s[2] : @s[2] = @s[1] : @s[1] = @s[0] : @s[0] = t0& + t1&
            #ALIGN 16
            !  movdqa   xmm0,    [esi]
            !  movdqa   xmm1,    [esi+16]
            !  movd     xmm3,    [esi+12]       ;xmm3 = @s[3]
    
            !  pslldq   xmm1,    4
            !  pslldq   xmm0,    4
    
            !  paddd    xmm1,    xmm3           ;xmm1[0] = @s{3]
    
            !  paddd    xmm0,    xmm6           ;+t0
            !  paddd    xmm1,    xmm6           ;+t0
            !  paddd    xmm0,    xmm7           ;+t1
    
            !  movdqa   [esi+16],xmm1
            !  movdqa   [esi],   xmm0
    
            !  mov      eax,     i
            !  inc      eax
            !  test     eax,     &b111111       ;<64?
            !  mov      i,       eax
            !  jnz      CompressTop
    
            '-- Add current state s() to context
            '  for i& = 0 to 7 : [email protected][i&] = [email protected][i&] + @s[i&] : next i&
            !  mov      edi,     pstate
            !  movdqa   xmm0,    [edi]
            !  movdqa   xmm1,    [edi+16]
            !  paddd    xmm0,    [esi]
            !  paddd    xmm1,    [esi+16]
            !  movdqa   [edi],   xmm0
            !  movdqa   [edi+16],xmm1
    
            !  pop   ebx
            !  pop   edi
            !  pop   esi
        END METHOD
    
    
        '====================
        CLASS METHOD Compress64()
        #REGISTER NONE
        LOCAL k_array, s_array, w_array AS LONG
        LOCAL pstate, pdata, wi, ki, i AS LONG
    
            '-- Copy for inline assembler
            w_array  = m_ctx.w_array
            s_array  = m_ctx.s_array
            k_array  = m_ctx.k_array
            pstate   = m_ctx.pstate
            pdata    = m_ctx.pdata
    
            !  push     esi
            !  push     edi
            !  push     ebx
    
            '-- Copy current state into s&()
            !  mov      esi,     pstate           ;esi -> pm_ctx.state0
            !  mov      edi,     s_array
            !  movq     mm0,     [esi]
            !  movq     mm1,     [esi+8]
            !  movq     mm2,     [esi+16]
            !  movq     mm3,     [esi+24]
            !  movq     [edi],   mm0
            !  movq     [edi+8], mm1
            !  movq     [edi+16],mm2
            !  movq     [edi+24],mm3
    
            '-- Copy current data block to w&() w/little-to-big endian conversion
            !  mov      esi,     pdata
            !  mov      edi,     w_array
            !  mov      ecx,     %C_POWER_SHA256_BLOCKSIZE
    
            #ALIGN 4
            BSwapCopyTop:
            !  sub      ecx,     4
            !  mov      eax,     [esi+ecx]
            !  sub      ecx,     4
            !  bswap    eax
            !  mov      edx,     [esi+ecx]
            !  mov      [edi+ecx+4], eax
            !  bswap    edx
            !  test     ecx,     ecx
            !  mov      [edi+ecx], edx
            !  jnz      BSwapCopyTop
    
            '-- Fill W[16to63]
            ! mov       esi,     w_array
            ! push      ebp
            ! mov       ebp,     16
            #ALIGN 4
            FillTop:
            !  mov      ebx,     ebp
            !  sub      ebx,     2
            !  mov      eax,     [esi+ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  sub      ebx,     13             ;prep for next access: (-2)+(-13) = -15
            !  ror      eax,     17
            !  ror      ecx,     19
            !  shr      edx,     10
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  mov      edi,     eax            ;edi = temp total
            !  mov      eax,     [esi+ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  ror      eax,     7
            !  ror      ecx,     18
            !  shr      edx,     3
            !  add      ebx,     8              ;= (-15)+8 = -7
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  add      edi,     eax
    
            !  mov      eax,     [esi+ebx*4]
            !  sub      ebx,     9              ;= (-7)+(-9) = -16
            !  add      edi,     eax
    
            !  mov      eax,     [esi+ebx*4]
            !  mov      ebx,     ebp
            !  add      eax,     edi
    
            !  inc      ebp
            !  mov      [esi+ebx*4], eax
            !  test     ebp,     &b111111       ;<64?
            !  jnz      FillTop
            !  pop      ebp
    
            '-- Compress: i& = 0 to 63
            !  xor      eax,     eax
            !  mov      esi,     s_array        ;here to CompressDone & END SUB: esi -> s[0]
            !  mov      i,       eax
            #ALIGN 4
            CompressTop:
            !  mov      ebx,     eax
            !  mov      edx,     w_array
            !  mov      eax,     [edx+ebx*4]
            !  mov      wi,      eax
            !  mov      edx,     k_array
            !  mov      eax,     [edx+ebx*4]
            !  mov      ki,      eax
    
            !  mov      eax,     [esi+16]
            !  mov      ecx,     [esi+20]
            !  mov      ebx,     eax
            !  mov      edx,     eax
            !  and      eax,     [esi+20]
    
            !  not      edx
            !  and      edx,     [esi+24]
            !  xor      eax,     edx
    
            !  mov      ecx,     ebx
            !  mov      ebx,     eax
            !  mov      eax,     ecx
    
            !  mov      edx,     ecx
            !  ror      eax,     6
            !  ror      ecx,     11
            !  ror      edx,     25
    
            !  add      ebx,     ki
            !  xor      eax,     ecx
            !  add      ebx,     wi
            !  xor      eax,     edx
    
            !  add      eax,     ebx
            !  add      eax,     [esi+28]
            !  movd     mm6,     eax            ;mm6 = t0
    
            !  mov      eax,     [esi]
            !  mov      ecx,     [esi+4]
            !  mov      ebx,     eax
    
            !  mov      edx,     eax
            !  and      eax,     ecx
    
            !  and      edx,     [esi+8]
            !  xor      eax,     edx
    
            !  and      ecx,     [esi+8]
            !  xor      eax,     ecx
            !  mov      edx,     eax
    
            !  mov      eax,     ebx
            !  mov      ecx,     ebx
            !  ror      eax,     2
            !  ror      ecx,     13
            !  ror      ebx,     22
            !  xor      eax,     ecx
            !  xor      eax,     ebx
    
            !  add      eax,     edx
            !  movd     mm7,     eax            ;mm7 = t1
    
            '  @s[7] = @s[6] : @s[6] = @s[5] : @s[5] = @s[4] : @s[4] = @s[3] + t0&
            '  @s[3] = @s[2] : @s[2] = @s[1] : @s[1] = @s[0] : @s[0] = t0& + t1&
            #ALIGN 8
            !  movq     mm3,     [esi+20]       ;mm3 = @s[6-5]
            !  movq     mm2,     [esi+12]       ;mm2 = @s[4-3]
            !  movq     mm1,     [esi+4]        ;mm1 = @s[2-1]
            !  movq     mm0,     [esi]          ;mm0 = @s[1-0]
    
            !  psllq    mm0,     32             ;mm0 = @s[0- ]
    
            !  paddd    mm2,     mm6            ;+t0
            !  paddd    mm0,     mm6            ;+t0
            !  paddd    mm0,     mm7            ;+t1
    
            !  movq     [esi+24],mm3
            !  movq     [esi+16],mm2
            !  movq     [esi+8], mm1
            !  movq     [esi],   mm0
    
            !  mov      eax,     i
            !  inc      eax
            !  test     eax,     &b111111       ;<64?
            !  mov      i,       eax
            !  jnz      CompressTop
    
            '-- Add current state s() to context
            '  for i& = 0 to 7 : [email protected][i&] = [email protected][i&] + @s[i&] : next i&
            !  mov      edi,     pstate
            !  movq     mm0,     [edi]
            !  movq     mm1,     [edi+8]
            !  movq     mm2,     [edi+16]
            !  movq     mm3,     [edi+24]
    
            !  paddd    mm0,     [esi]
            !  paddd    mm1,     [esi+8]
            !  paddd    mm2,     [esi+16]
            !  paddd    mm3,     [esi+24]
    
            !  movq     [edi],   mm0
            !  movq     [edi+8], mm1
            !  movq     [edi+16],mm2
            !  movq     [edi+24],mm3
    
            !  emms
            !  pop   ebx
            !  pop   edi
            !  pop   esi
        END METHOD
    
    
        '====================
        CLASS METHOD Compress32()
        #REGISTER NONE
        LOCAL k_array, s_array, w_array AS LONG
        LOCAL pstate, pdata AS LONG
        LOCAL t0, t1, wi, ki, i AS LONG
    
            '-- Copy for inline assembler
            w_array  = m_ctx.w_array
            s_array  = m_ctx.s_array
            k_array  = m_ctx.k_array
            pstate   = m_ctx.pstate
            pdata    = m_ctx.pdata
    
            !  push     esi
            !  push     edi
            !  push     ebx
    
            '-- Copy current state into s&()
            !  mov      esi,     pstate           ;esi -> pm_ctx.state0
            !  mov      edi,     s_array
            !  mov      ecx,     8
            !  cld
            !  rep      movsd
    
            '-- Copy current data block to w&() w/little-to-big endian conversion
            !  mov      esi,     pdata
            !  mov      edi,     w_array
            !  mov      ecx,     %C_POWER_SHA256_BLOCKSIZE
            #ALIGN 4
            BSwapCopyTop:
            !  sub      ecx,     4
            !  mov      eax,     [esi+ecx]
            !  sub      ecx,     4
            !  bswap    eax
            !  mov      edx,     [esi+ecx]
            !  mov      [edi+ecx+4],eax
            !  bswap    edx
            !  test     ecx,     ecx
            !  mov      [edi+ecx],  edx
            !  jnz      BSwapCopyTop
    
            '-- Fill W[16to63]
            ! mov       esi,     w_array
            ! push      ebp
            ! mov       ebp,     16
            #ALIGN 4
            FillTop:
            !  mov      ebx,     ebp
            !  sub      ebx,     2
            !  mov      eax,     [esi]+[ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  sub      ebx,     13           ;prep for next access: (-2)+(-13) = -15
            !  ror      eax,     17
            !  ror      ecx,     19
            !  shr      edx,     10
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  mov      edi,     eax          ;edi = temp total
            !  mov      eax,     [esi]+[ebx*4]
            !  mov      ecx,     eax
            !  mov      edx,     ecx
            !  ror      eax,     7
            !  ror      ecx,     18
            !  shr      edx,     3
            !  add      ebx,     8            ;= (-15)+8 = -7
            !  xor      eax,     ecx
            !  xor      eax,     edx
            !  add      edi,     eax
    
            !  mov      eax,     [esi]+[ebx*4]
            !  sub      ebx,     9            ;= (-7)+(-9) = -16
            !  add      edi,     eax
    
            !  mov      eax,     [esi]+[ebx*4]
            !  mov      ebx,     ebp
            !  add      eax,     edi
    
            !  inc      ebp
            !  mov      [esi]+[ebx*4], eax
            !  cmp      ebp,     63
            !  jg       FillDone
            !  jmp      FillTop
            FillDone:
            !  pop   ebp
    
            '-- Compress: i& = 0 to 63
            !  xor      eax,     eax
            !  mov      esi,     s_array            ;here to CompressDone & END SUB: esi -> s[0]
            !  mov      i,       eax
            #ALIGN 4
            CompressTop:
            !  mov      ebx,     eax
            !  mov      edx,     w_array
            !  mov      eax,     [edx]+[ebx*4]
            !  mov      wi,      eax
            !  mov      edx,     k_array&
            !  mov      eax,     [edx]+[ebx*4]
            !  mov      ki,      eax
    
            !  mov      eax,     [esi+16]
            !  mov      ecx,     [esi+20]
            !  mov      ebx,     eax
            !  mov      edx,     eax
            !  and      eax,     [esi+20]
    
            !  not      edx
            !  and      edx,     [esi+24]
            !  xor      eax,     edx
    
            !  mov      ecx,     ebx
            !  mov      ebx,     eax
            !  mov      eax,     ecx
    
            !  mov      edx,     ecx
            !  ror      eax,     6
            !  ror      ecx,     11
            !  ror      edx,     25
    
            !  add      ebx,     ki
            !  xor      eax,     ecx
            !  add      ebx,     wi
            !  xor      eax,     edx
    
            !  add      eax,     ebx
            !  add      eax,     [esi+28]
    
            !  mov      t0&,     eax
    
            !  mov      eax,     [esi]
            !  mov      ecx,     [esi+4]
            !  mov      ebx,     eax
    
            !  mov      edx,     eax
            !  and      eax,     ecx
    
            !  and      edx,     [esi+8]
            !  xor      eax,     edx
    
            !  and      ecx,     [esi+8]
            !  xor      eax,     ecx
            !  mov      edx,     eax
    
            !  mov      eax,     ebx
            !  mov      ecx,     ebx
            !  ror      eax,     2
            !  ror      ecx,     13
            !  ror      ebx,     22
            !  xor      eax,     ecx
            !  xor      eax,     ebx
    
            !  add      eax,     edx
            !  mov      t1,      eax
    
            '  @s[7] = @s[6] : @s[6] = @s[5] : @s[5] = @s[4] : @s[4] = @s[3] + t0&
            '  @s[3] = @s[2] : @s[2] = @s[1] : @s[1] = @s[0] : @s[0] = t0& + t1&
            !  mov      edi,     esi
            !  mov      ecx,     t0
    
            !  mov      eax,     [esi+24]     ;@s[7] = @s[6]
            !  mov      ebx,     [esi+20]     ;@s[6] = @s[5]
            !  mov      edx,     [esi+16]     ;@s[5] = @s[4]
            !  mov      [edi+28], eax
            !  mov      [edi+24], ebx
            !  mov      [edi+20], edx
    
            !  mov      eax,     [esi+12]     ;@s[4] = @s[3] + T0&
            !  mov      ebx,     [esi+8]      ;@s[3] = @s[2]
            !  add      eax,     ecx
            !  mov      edx,     [esi]        ;@s[1] = @s[0]
            !  mov      [edi+12],ebx
            !  mov      [edi+16],eax
            !  mov      ebx, ecx          ;@s[0] = T0& + T1&
            !  mov      eax, [esi+4]      ;@s[2] = @s[1]
            !  mov      [edi+4], edx
            !  add      ebx, t1
            !  mov      [edi+8], eax
            !  mov      [edi],   ebx
    
            !  mov      eax,     i
            !  inc      eax
            !  test     eax,     &b111111       ;<64?
            !  mov      i,       eax
            !  jnz      CompressTop
    
            '-- Add current state s() to context
            '  for i& = 0 to 7 : [email protected][i&] = [email protected][i&] + @s[i&] : next i&
            !  mov      edi, pstate
            !  mov      ecx, %C_POWER_SHA256_HASHLEN
            #ALIGN 4
            AddCopyTop:
            !  sub      ecx,     4
            !  mov      eax,     [edi+ecx]
            !  add      eax,     [esi+ecx]
            !  mov      [edi+ecx], eax
            !  test     ecx,     ecx
            !  jnz      AddCopyTop
    
            !  pop      ebx
            !  pop      edi
            !  pop      esi
        END METHOD
    
    
        '====================
        CLASS METHOD calcFile (pFile AS WSTRINGZ) THREADSAFE AS LONG
        REGISTER i       AS LONG
        LOCAL apiErr     AS LONG
        LOCAL pstate     AS LONG
        LOCAL phash      AS DWORD PTR
        LOCAL pInit      AS LONG
        LOCAL pworkspace AS LONG
        LOCAL readBytes  AS DWORD
    
            RESET m_ctx
    
            m_ctx.k_array = CODEPTR(K_Array_Data)
            pInit         = CODEPTR(Init_Values)
    
            pworkspace    = align(VARPTR(m_ctx.Workspace), %C_POWER_SHA256_ALIGNMENT)
            m_ctx.s_array = pworkspace
            m_ctx.w_array = pworkspace + %C_POWER_SHA256_S_ARRAY_SIZE
    
            m_ctx.pstate  = align(VARPTR(m_ctx.state), %C_POWER_SHA256_ALIGNMENT)
            pstate        = m_ctx.pstate
    
            !  push     esi
            !  push     edi
            !  mov      esi,     pInit
            !  mov      edi,     pstate
            !  mov      ecx,     8
            !  cld
            !  rep      movsd
            !  pop      edi
            !  pop      esi
    
            ' ----------------------------------------------------------------------
    
            m_hFile = CreateFile ( pFile, BYVAL %GENERIC_READ, BYVAL %FILE_SHARE_READ, BYVAL %NULL, BYVAL %OPEN_EXISTING, BYVAL %FILE_FLAG_SEQUENTIAL_SCAN, BYVAL %NULL )
            IF ( m_hFile = %INVALID_HANDLE_VALUE ) THEN
                METHOD = GetLastError()
                EXIT METHOD
            END IF
    
            i = GetFileSizeEx (m_hFile, m_bytesleft)
            IF ( i = 0 ) THEN
                apiErr = GetLastError()
                GOTO FN_EXIT
            END IF
    
            m_buffer      = STRING$(%C_POWER_SHA256_FILE_BUFFERSIZE, 0)
            m_maxstring   = %C_POWER_SHA256_FILE_BUFFERSIZE
            m_ctx.lendata = %C_POWER_SHA256_BLOCKSIZE
            m_lastpass    = 0
            m_padding     = me.MakePadding (m_bytesleft)
    
            WHILE ( m_lastpass < 1 )
                ' ----------------------------------------------------------------------------------
                IF m_bytesleft =< m_maxstring THEN          'Resize if necessary & flag final buffer
                    m_maxstring = CLNG(m_bytesleft)
                    m_buffer = STRING$(m_maxstring, 0)
                    INCR m_lastpass
                END IF
                ' ----------------------------------------------------------------------------------
                i = ReadFile (m_hFile, STRPTR(m_buffer), LEN(m_buffer), readBytes, BYVAL %NULL)
                IF ( i = 0 ) THEN
                    apiErr = GetLastError()
                    GOTO FN_EXIT
                END IF
                ' ----------------------------------------------------------------------------------
                IF m_lastpass THEN
                    m_buffer = m_buffer + m_padding
                END IF
                ' ----------------------------------------------------------------------------------
                m_ctx.pdata = STRPTR(m_buffer)
                SELECT CASE m_compress
                CASE 128
                    FOR i = 1 TO (LEN(m_buffer) \ %C_POWER_SHA256_BLOCKSIZE)
                        CALL me.Compress128()
                        m_ctx.pdata = m_ctx.pdata + %C_POWER_SHA256_BLOCKSIZE
                    NEXT i
                CASE 64
                    FOR i = 1 TO (LEN(m_buffer) \ %C_POWER_SHA256_BLOCKSIZE)
                        CALL me.Compress64()
                        m_ctx.pdata = m_ctx.pdata + %C_POWER_SHA256_BLOCKSIZE
                    NEXT i
                CASE ELSE
                    FOR i = 1 TO (LEN(m_buffer) \ %C_POWER_SHA256_BLOCKSIZE)
                        CALL me.Compress32()
                        m_ctx.pdata = m_ctx.pdata + %C_POWER_SHA256_BLOCKSIZE
                    NEXT i
                END SELECT
                ' ----------------------------------------------------------------------------------
                m_bytesleft    = m_bytesleft - m_maxstring
                m_Status_Bytes = m_Status_Bytes + m_maxstring
            WEND
    
            phash  = m_hashptr
            pstate = m_ctx.pstate
    
            '-- Copy current state
    
            #IF %C_POWER_SHA256_RETURN_LITTLE_ENDIAN
            !  push  edi
            !  mov   edx,  pstate           ;esi -> m_ctx.state0
            !  mov   edi,  phash
            !  mov   ecx,  (%C_POWER_SHA256_HASHLEN\4)-1   ;here -1
            #ALIGN 4
            LoopTop:
            !  mov   eax,  [edx+ecx*4]
            !  bswap eax
            !  mov   [edi+ecx*4],eax
            !  dec   ecx
            !  jns   LoopTop
            !  pop   edi
            #ELSE
            !  push  esi
            !  push  edi
            !  mov   esi,  pstate           ;esi -> m_ctx.state0
            !  mov   edi,  phash
            !  mov   ecx,  8
            !  cld
            !  rep   movsd
            !  pop   edi
            !  pop   esi
            #ENDIF
    
        FN_EXIT:
            CALL CloseHandle ( m_hFile )
            RESET m_hFile
            METHOD = apiErr
    
        END METHOD
    
    
        '=========================
        '-- Creates the necessary string to append to targeted data buffer
        CLASS METHOD MakePadding (BYVAL TotalBytes AS QUAD) AS STRING
        REGISTER i AS LONG, padBytes AS LONG
        LOCAL buffbits AS QUAD
        LOCAL padding  AS STRING
        LOCAL pbyte1   AS BYTE PTR
        LOCAL pbyte2   AS BYTE PTR
    
            buffbits = TotalBytes * 8
            padding  = NUL$(8)
            pbyte1   = STRPTR(padding)
            pbyte2   = VARPTR(buffbits)
    
            '-- Copy bytes in reverse
            FOR i = 0 TO 7
               @pbyte1[i] = @pbyte2[7 - i]
            NEXT i
    
            padBytes = %C_POWER_SHA256_BLOCKSIZE - ((TotalBytes + 9) AND (%C_POWER_SHA256_BLOCKSIZE - 1))
            METHOD = CHR$(&h80) + NUL$(padBytes) + padding
        END METHOD
    
    
        '===================
        CLASS METHOD HasSSE2() AS LONG
        !  mov      eax, 1
        !  cpuid
        !  xor      eax, eax
        !  test     edx, &h04000000   ;bit 26
        !  setnz    al                ;rem to force downgrade to MMX
        !  mov      METHOD, eax
        END METHOD
    
    
        '===================
        CLASS METHOD HasMMX() AS LONG
        !  mov      eax, 1
        !  cpuid
        !  xor      eax, eax
        !  test     edx, &h800000     ;bit 23
        !  setnz    al                ;rem to force downgrade to 32-bit
        !  mov      METHOD, eax
        END METHOD
    
    
        '===================
        CLASS METHOD CREATE()
            IF me.HasSSE2() THEN
                m_compress = 128
            ELSEIF me.HasMMX() THEN
                m_compress = 64
            ELSE
                m_compress = 32
            END IF
            m_Status_Bytes = 0
            m_Status_Index = -1
            m_Cancel       = %FALSE
            m_hashptr      = VARPTR(m_hashmem)
        END METHOD
    
    
        '===================
        CLASS METHOD DESTROY()
            IF ( m_hFile <> %INVALID_HANDLE_VALUE ) THEN
                CALL CloseHandle ( m_hFile )
                RESET m_hFile
            END IF
        END METHOD
    
    
        ' ====================================================
        INTERFACE iSHA256main $C_POWER_SHA256_MAIN_IID : INHERIT IPOWERTHREAD
    
            PROPERTY SET FileData ( value AS iSHA256data )
                cDataFace = value
            END PROPERTY
    
            PROPERTY GET p_Status_Bytes () AS QUAD
                PROPERTY = m_Status_Bytes
            END PROPERTY
    
            PROPERTY GET p_Status_Index () AS QUAD
                PROPERTY = m_Status_Index
            END PROPERTY
    
            ' ====================================================
    
            PROPERTY GET p_Cancel () AS LONG
                PROPERTY = m_Cancel
            END PROPERTY
            PROPERTY SET p_Cancel (BYVAL value AS LONG)
                IF ( ISTRUE value ) THEN
                    INCR m_lastpass
                    m_Cancel = %TRUE
                ELSE
                    m_Cancel = %FALSE
                END IF
            END PROPERTY
    
        END INTERFACE
    
    END CLASS
    
    
    CLASS cSHA256data $C_POWER_SHA256_DATA_CID COMMON
    INSTANCE m_lbound          AS LONG
    INSTANCE m_ubound          AS LONG
    INSTANCE m_Files()         AS WSTRING
    INSTANCE m_Hashs()         AS STRING
    INSTANCE m_Errors()        AS LONG
    
        '===================
        CLASS METHOD CREATE()
        END METHOD
    
        '===================
        CLASS METHOD DESTROY()
        END METHOD
    
        ' ====================================================
    
        INTERFACE iSHA256data $C_POWER_SHA256_DATA_IID : INHERIT DUAL
    
        ' ====================================================
    
            PROPERTY GET p_lbound () AS LONG
                PROPERTY = m_lbound
            END PROPERTY
    
            PROPERTY GET p_ubound () AS LONG
                PROPERTY = m_ubound
            END PROPERTY
    
            ' ====================================================
    
            METHOD GetFile ( BYVAL i AS LONG ) AS WSTRING
                METHOD = m_Files(i)
            END METHOD
    
            METHOD GetHash ( BYVAL i AS LONG ) AS STRING
                METHOD = m_Hashs(i)
            END METHOD
            METHOD SetHash ( BYVAL i AS LONG, BYVAL hash AS STRING )
                m_Hashs(i) = hash
            END METHOD
    
            METHOD GetError ( BYVAL i AS LONG ) AS LONG
                METHOD = m_Errors(i)
            END METHOD
            METHOD SetError ( BYVAL i AS LONG, BYVAL ErrNum AS LONG )
                m_Errors(i) = ErrNum
            END METHOD
    
            METHOD DimAT (BYVAL pFiles AS DWORD, BYVAL pHashs AS DWORD, BYVAL pErrors AS DWORD, BYVAL lb AS LONG, BYVAL ub AS LONG)
                m_lbound = lb
                m_ubound = ub
                REDIM m_Files  (lb TO ub) AS INSTANCE WSTRING AT pFiles
                REDIM m_Hashs  (lb TO ub) AS INSTANCE  STRING AT pHashs
                REDIM m_Errors (lb TO ub) AS INSTANCE    LONG AT pErrors
            END METHOD
    
        END INTERFACE
    
    END CLASS
    PowerSHA256.bas
    Code:
    [COLOR="DarkGreen"]'------------------------------------------------
    ' Demo program for SHA256-Hash-PowerTHREAD-Class
    '------------------------------------------------[/COLOR]
    #COMPILE EXE "PowerSHA256.exe"
    #DIM ALL
    %UNICODE = 1
    #INCLUDE ONCE "WIN32API.INC"
    #INCLUDE "PowerSHA256.inc"
    [COLOR="DarkGreen"]'#LINK "PowerSHA256.sll"[/COLOR]
    
    %IDD_DIALOG1      =  101
    %IDC_TEXTBOX1     = 1001
    %IDC_LABEL1       = 1002
    %IDC_LABEL2       = 1003
    %IDC_PROGRESSBAR1 = 1004
    %IDC_BUTTON1      = 1005
    %IDC_BUTTON2      = 1006
    %IDC_TIMER_STATUS = 1999
    
    GLOBAL goHashMain   AS iSHA256main
    GLOBAL goHashData   AS iSHA256data
    GLOBAL gFile   ()   AS WSTRING
    GLOBAL gHash   ()   AS STRING
    GLOBAL gErr    ()   AS LONG
    
    
    SUB SetGlobalArrays (BYVAL pFileList AS WSTRING)                   ' GLOBAL ARRAYS: gFile(), gHash(), gErr()
    LOCAL i,c    AS LONG
    LOCAL folder AS WSTRING
    
        pFileList = RTRIM$(pFileList,$$NUL)
    
        IF ISFILE (pFileList) THEN                                     ' if only one file selected
            c = 1
            REDIM gFile (1 TO 1)
            gFile (1) = pFileList
        ELSE                                                           ' if multiple files selected
            folder = PARSE$(pFileList, $$NUL, 1)
            folder = RTRIM$(folder,"\") + "\"
            c = PARSECOUNT(pFileList,$$NUL) - 1
            REDIM gFile (1 TO c)
            FOR i = 1 TO c
                gFile (i) = folder + PARSE$(pFileList, $$NUL, 1+i)
            NEXT i
        END IF
    
        REDIM gHash(1 TO c)
        REDIM gErr (1 TO c)
    
    END SUB
    
    
    FUNCTION GetTotalSize () AS QUAD
    LOCAL i,f   AS LONG
    LOCAL fsize AS QUAD
        FOR i = LBOUND(gFile) TO UBOUND(gFile)
            f = FREEFILE
            OPEN gFile (i) FOR BINARY ACCESS READ LOCK SHARED AS #f
                fsize = fsize + LOF(#f)
            CLOSE #f
        NEXT i
        FUNCTION = fsize
    END FUNCTION
    
    
    SUB SHA256hash (BYVAL hDlg AS DWORD)
    LOCAL i       AS LONG
    LOCAL time    AS SINGLE
    LOCAL tmp     AS WSTRING
    
        goHashMain   = CLASS "cSHA256main"
        goHashData   = CLASS "cSHA256data"
    
        goHashMain.FileData = goHashData
    
        CALL goHashData.DimAT (VARPTR(gFile(1)), VARPTR(gHash(1)), VARPTR(gErr(1)), LBOUND(gFile), UBOUND(gFile))
    
        SetTimer hDlg, %IDC_TIMER_STATUS, 200, BYVAL 0
    
        time = TIMER
        goHashMain.launch (BYVAL 0)
        WHILE goHashMain.isalive()
            DIALOG DOEVENTS
        WEND
        time = TIMER-time
    
        KillTimer hDlg, %IDC_TIMER_STATUS
    
        IF ISFALSE (goHashMain.p_Cancel) THEN
            FOR i = LBOUND(gFile) TO UBOUND(gFile)
                IF gErr(i) = 0 THEN
                    tmp = tmp + gFile(i) + $CRLF + " --> " + gHash(i) + $CRLF + $CRLF
                ELSE
                    tmp = tmp + gFile(i) + $CRLF + " --> " + "Api-Error:" + STR$(gErr(i)) + $CRLF + $CRLF
                END IF
            NEXT i
            CONTROL SET TEXT hDlg, %IDC_TEXTBOX1, tmp
            PROGRESSBAR SET POS hDlg, %IDC_PROGRESSBAR1, 100
            CONTROL SET TEXT hDlg, %IDC_LABEL1, FORMAT$(goHashMain.p_Status_Bytes) + " Bytes --> Time:" + STR$(time)
            CONTROL SET TEXT hDlg, %IDC_LABEL2, ""
        END IF
    
        goHashData   = NOTHING
        goHashMain   = NOTHING
    END SUB
    
    
    CALLBACK FUNCTION ShowDIALOG1Proc()
    STATIC fMouse   AS LONG
    STATIC CurBytes AS QUAD
    STATIC AllBytes AS QUAD
    STATIC Percent  AS LONG
    LOCAL files     AS WSTRING
    
        SELECT CASE AS LONG CB.MSG
        CASE %WM_INITDIALOG
            PROGRESSBAR SET RANGE CBHNDL, %IDC_PROGRESSBAR1, 0, 100             ' progress from 0 to 100%
    
        CASE %WM_NCACTIVATE
            STATIC hWndSaveFocus AS DWORD
            IF ISFALSE CB.WPARAM THEN
                hWndSaveFocus = GetFocus()                                      ' Save control focus
            ELSEIF hWndSaveFocus THEN
                SetFocus(hWndSaveFocus)                                         ' Restore control focus
                hWndSaveFocus = 0
            END IF
    
        CASE %WM_SETCURSOR
            IF ( ISTRUE fMouse ) THEN MOUSEPTR 13 : FUNCTION = 1
    
        CASE %WM_TIMER
            SELECT CASE CBWPARAM
            CASE %IDC_TIMER_STATUS
                IF ISOBJECT(goHashMain) THEN
                    IF goHashMain.isalive() THEN
                        CurBytes = goHashMain.p_Status_Bytes
                        Percent  = CurBytes * 100 / AllBytes
                        PROGRESSBAR SET POS CBHNDL, %IDC_PROGRESSBAR1, Percent
                        CONTROL SET TEXT CBHNDL, %IDC_LABEL1, FORMAT$(CurBytes) + " --> " + FORMAT$(AllBytes) + " --> " + FORMAT$(Percent) + "%"
                        CONTROL SET TEXT CBHNDL, %IDC_LABEL2, PATHNAME$(NAMEX,gFile(goHashMain.p_Status_Index))
                    END IF
                END IF
            END SELECT
    
        CASE %WM_COMMAND
            SELECT CASE AS LONG CB.CTL
    
            CASE %IDC_BUTTON1
                IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                    DISPLAY OPENFILE CBHNDL, , , "Select file", "", "", "", "", %OFN_ENABLESIZING OR %OFN_FILEMUSTEXIST OR %OFN_ALLOWMULTISELECT TO files
                    IF ( files <> "" ) THEN
                        CONTROL DISABLE CBHNDL, %IDC_BUTTON1
                        fMouse = %TRUE
                        MOUSEPTR 13
                        CALL SetGlobalArrays (files)
                        AllBytes = GetTotalSize()
                        CALL SHA256hash (CBHNDL)
                        CONTROL ENABLE CBHNDL, %IDC_BUTTON1
                        fMouse = %FALSE
                        MOUSEPTR 1
                    END IF
                END IF
    
            CASE %IDC_BUTTON2
                IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                    IF ISOBJECT(goHashMain) THEN
                        IF goHashMain.isalive() THEN
                            KillTimer CBHNDL, %IDC_TIMER_STATUS
                            goHashMain.suspend()
                            IF MSGBOX ( "Stop?", %MB_YESNO, "SHA256" ) = %IDNO THEN
                                goHashMain.resume()
                                SetTimer CBHNDL, %IDC_TIMER_STATUS, 100, BYVAL 0
                                EXIT FUNCTION
                            END IF
                            goHashMain.p_Cancel = %TRUE
                            goHashMain.resume()
    
                        END IF
                    END IF
                END IF
    
            END SELECT
    
        CASE %WM_DESTROY
            KillTimer CBHNDL, %IDC_TIMER_STATUS
            IF ISOBJECT(goHashMain) THEN
                IF goHashMain.isalive() THEN
                    goHashMain.p_Cancel = %TRUE
                    SLEEP 50
                END IF
            END IF
    
        END SELECT
    END FUNCTION
    
    
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    LOCAL lRslt AS LONG
    LOCAL hDlg  AS DWORD
    
        DIALOG NEW hParent, "SHA256", 197, 138, 421, 296, %WS_POPUP OR %WS_BORDER _
            OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
            %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _
            %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT _
            OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
        CONTROL ADD LABEL,       hDlg, %IDC_LABEL1, "", 110, 220, 200, 20
        CONTROL ADD LABEL,       hDlg, %IDC_LABEL2, "", 110, 240, 200, 20
        CONTROL ADD PROGRESSBAR, hDlg, %IDC_PROGRESSBAR1, "ProgressBar1", 110, _
            195, 200, 25
        CONTROL ADD BUTTON,      hDlg, %IDC_BUTTON1, "File...", 310, 255, 75, 20
        CONTROL ADD BUTTON,      hDlg, %IDC_BUTTON2, "Stop...", 35, 255, 75, 20
        CONTROL ADD TEXTBOX,     hDlg, %IDC_TEXTBOX1, "", 10, 10, 400, 165, _
            %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %WS_VSCROLL OR %ES_LEFT _
            OR %ES_MULTILINE OR %ES_AUTOHSCROLL OR %ES_AUTOVSCROLL OR _
            %ES_WANTRETURN, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR _
            %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
    
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
        FUNCTION = lRslt
    END FUNCTION
    
    
    FUNCTION PBMAIN()
    
        DIM gFile(0) AS WSTRING
        DIM gHash(0) AS STRING
        DIM gErr (0) AS LONG
    
        ShowDIALOG1 %HWND_DESKTOP
    
    END FUNCTION

    Comment


    • #3
      I found a sporadic error.
      The error is included in "MakePadding".
      I randomly noticed the error and cannot find the solution.



      Code:
      %BLOCKSIZE            = 64
      
      CLASS METHOD calcBuffer (BYVAL hData AS DWORD, BYVAL Length AS DWORD) AS LONG
      REGISTER i AS DWORD
      LOCAL pstate AS LONG
      LOCAL lastbuff AS STRING
      LOCAL DataBuffer AS BYTE PTR
      LOCAL phash AS DWORD PTR
      
      DataBuffer = hData
      i = Length AND (%BLOCKSIZE-1)
      
      lastbuff = PEEK$((DataBuffer+Length)-i, i)
      lastbuff = lastbuff + me.[B]MakePadding[/B](Length)
      
      [COLOR=#c0392b]' Usually the length of the "[B]lastbuff[/B]" is always 64.
      ' Sometimes the string length is 128.
      ' In this case an incorrect hash is calculated.[/COLOR]
      
      MSGBOX STR$(LEN(lastbuff))
      
      ...
      ...
      ...
      END METHOD
      
      
      CLASS METHOD [B]MakePadding [/B](BYVAL TotalBytes AS QUAD) AS STRING
      REGISTER i AS LONG, padBytes AS LONG
      LOCAL buffbits AS QUAD
      LOCAL padding AS STRING
      LOCAL pbyte1 AS BYTE PTR
      LOCAL pbyte2 AS BYTE PTR
      
      buffBits = TotalBytes * 8
      padding = NUL$(8)
      pbyte1 = STRPTR(padding)
      pbyte2 = VARPTR(buffBits)
      
      '-- Reverse bytes during copy
      FOR i = 0 TO 7
      @pbyte1[i] = @pbyte2[7 - i]
      NEXT i
      
      padBytes = %BLOCKSIZE - ((TotalBytes+9) AND (%BLOCKSIZE-1))
      METHOD = CHR$(&h80) + NUL$(padBytes) + padding
      END METHOD

      Comment

      Working...
      X