В процессоры была добавлена поддержка инструкций хеширования включая SHA1 и SHA256 https://en.wikipedia.org/wiki/Intel_SHA_extensions
Как показала практика на процессоре вычисление SHA1 выполняется примерно в 3 раза быстрее чем функциями PB.
Нужна версия PB не ниже 6.00 (или придется заменить компилятор фасма на версию из 6.00).
CompilerIf #PB_Compiler_Processor <> #PB_Processor_x64 CompilerError "Поддерживается только x64 платформа" CompilerEndIf CompilerIf #PB_Compiler_Version>=600 CompilerIf #PB_Compiler_Backend <> #PB_Backend_Asm CompilerError "Поддерживается только компилятор ассемблера" CompilerEndIf CompilerElse CompilerError "FASM не поддерживает SHA1 инструкции" CompilerEndIf DeclareModule CPU_SHA1 Declare IsCPU_SHA() Declare CPU_StartFingerprint() Declare CPU_CopyInstance(*Sha) Declare CPU_AddFingerprintBuffer(*Sha, *Buffer, Size) Declare.s CPU_GetSHA(*Sha) Declare.s CPU_FinishFingerprint(*Sha) Declare.s CPU_Fingerprint(*Buffer, Size) Declare.s CPU_StringFingerprint(s.s) EndDeclareModule Module CPU_SHA1 EnableExplicit #SHA1_ChunksSize = 64 Structure SHA_Data Align #PB_Structure_AlignC xmm0.M128A xmm1.M128A AllSize.q Buff.a[#SHA1_ChunksSize] BuffSize.a EndStructure Procedure SetReg(*Sha.SHA_Data) Protected xmm.M128A, *p xmm = *Sha\xmm0 !movdqu xmm0, dqword[p.v_xmm] xmm = *Sha\xmm1 !movdqu xmm1, dqword[p.v_xmm] *p = ?PSHUFFLE_BYTE_FLIP_MASK !mov rdi,[p.p_p] !movdqu xmm7,[rdi] DataSection PSHUFFLE_BYTE_FLIP_MASK: Data.q $08090a0b0c0d0e0f, $0001020304050607 ; like "bswap" EndDataSection EndProcedure Procedure GetReg(*Sha.SHA_Data) Protected *xmm.M128A *xmm = *Sha\xmm0 !mov rdi,[p.p_xmm] !movdqu [rdi],xmm0 *xmm = *Sha\xmm1 !mov rdi,[p.p_xmm] !movdqu [rdi],xmm1 EndProcedure Procedure SHA1_Calc(*Buff, CountChunks) !mov rsi,[p.p_Buff] !mov rcx,[p.v_CountChunks] !@@: !movdqa xmm8,xmm1 !movdqa xmm9,xmm0 ;Rounds 0-3 !movdqu xmm3,[rsi] !pshufb xmm3,xmm7 !paddd xmm1,xmm3 !movdqa xmm2,xmm0 !sha1rnds4 xmm0,xmm1,0 ;Rounds 4-7 !movdqu xmm4,[rsi+16] !pshufb xmm4,xmm7 !sha1nexte xmm2,xmm4 !movdqa xmm1,xmm0 !sha1rnds4 xmm0,xmm2,0 !sha1msg1 xmm3,xmm4 ;Rounds 8-11 !movdqu xmm5,[rsi+32] !pshufb xmm5,xmm7 !sha1nexte xmm1,xmm5 !movdqa xmm2,xmm0 !sha1rnds4 xmm0,xmm1,0 !sha1msg1 xmm4,xmm5 !pxor xmm3,xmm5 ;Rounds 12-15 !movdqu xmm6,[rsi+48] !pshufb xmm6,xmm7 !sha1nexte xmm2,xmm6 !movdqa xmm1,xmm0 !sha1msg2 xmm3,xmm6 !sha1rnds4 xmm0,xmm2,0 !sha1msg1 xmm5,xmm6 !pxor xmm4,xmm6 ;Rounds 16-19 !sha1nexte xmm1,xmm3 !movdqa xmm2,xmm0 !sha1msg2 xmm4,xmm3 !sha1rnds4 xmm0,xmm1,0 !sha1msg1 xmm6,xmm3 !pxor xmm5,xmm3 ;Rounds 20-23 !sha1nexte xmm2,xmm4 !movdqa xmm1,xmm0 !sha1msg2 xmm5,xmm4 !sha1rnds4 xmm0,xmm2,1 !sha1msg1 xmm3,xmm4 !pxor xmm6,xmm4 ;Rounds 24-27 !sha1nexte xmm1,xmm5 !movdqa xmm2,xmm0 !sha1msg2 xmm6,xmm5 !sha1rnds4 xmm0,xmm1,1 !sha1msg1 xmm4,xmm5 !pxor xmm3,xmm5 ;Rounds 28-31 !sha1nexte xmm2,xmm6 !movdqa xmm1,xmm0 !sha1msg2 xmm3,xmm6 !sha1rnds4 xmm0,xmm2,1 !sha1msg1 xmm5,xmm6 !pxor xmm4,xmm6 ;Rounds 32-35 !sha1nexte xmm1,xmm3 !movdqa xmm2,xmm0 !sha1msg2 xmm4,xmm3 !sha1rnds4 xmm0,xmm1,1 !sha1msg1 xmm6,xmm3 !pxor xmm5,xmm3 ;Rounds 36-39 !sha1nexte xmm2,xmm4 !movdqa xmm1,xmm0 !sha1msg2 xmm5,xmm4 !sha1rnds4 xmm0,xmm2,1 !sha1msg1 xmm3,xmm4 !pxor xmm6,xmm4 ;Rounds 40-43 !sha1nexte xmm1,xmm5 !movdqa xmm2,xmm0 !sha1msg2 xmm6,xmm5 !sha1rnds4 xmm0,xmm1,2 !sha1msg1 xmm4,xmm5 !pxor xmm3,xmm5 ;Rounds 44-47 !sha1nexte xmm2,xmm6 !movdqa xmm1,xmm0 !sha1msg2 xmm3,xmm6 !sha1rnds4 xmm0,xmm2,2 !sha1msg1 xmm5,xmm6 !pxor xmm4,xmm6 ;Rounds 48-51 !sha1nexte xmm1,xmm3 !movdqa xmm2,xmm0 !sha1msg2 xmm4,xmm3 !sha1rnds4 xmm0,xmm1,2 !sha1msg1 xmm6,xmm3 !pxor xmm5,xmm3 ;Rounds 52-55 !sha1nexte xmm2,xmm4 !movdqa xmm1,xmm0 !sha1msg2 xmm5,xmm4 !sha1rnds4 xmm0,xmm2,2 !sha1msg1 xmm3,xmm4 !pxor xmm6,xmm4 ;Rounds 56-59 !sha1nexte xmm1,xmm5 !movdqa xmm2,xmm0 !sha1msg2 xmm6,xmm5 !sha1rnds4 xmm0,xmm1,2 !sha1msg1 xmm4,xmm5 !pxor xmm3,xmm5 ;Rounds 60-63 !sha1nexte xmm2,xmm6 !movdqa xmm1,xmm0 !sha1msg2 xmm3,xmm6 !sha1rnds4 xmm0,xmm2,3 !sha1msg1 xmm5,xmm6 !pxor xmm4,xmm6 ;Rounds 64-67 !sha1nexte xmm1,xmm3 !movdqa xmm2,xmm0 !sha1msg2 xmm4,xmm3 !sha1rnds4 xmm0,xmm1,3 !sha1msg1 xmm6,xmm3 !pxor xmm5,xmm3 ;Rounds 68-71 !sha1nexte xmm2,xmm4 !movdqa xmm1,xmm0 !sha1msg2 xmm5,xmm4 !sha1rnds4 xmm0,xmm2,3 !pxor xmm6,xmm4 ;Rounds 72-75 !sha1nexte xmm1,xmm5 !movdqa xmm2,xmm0 !sha1msg2 xmm6,xmm5 !sha1rnds4 xmm0,xmm1,3 ;Rounds 76-79 !sha1nexte xmm2,xmm6 !movdqa xmm1,xmm0 !sha1rnds4 xmm0,xmm2,3 ;Add current hash values with previously saved !sha1nexte xmm1,xmm8 !paddd xmm0,xmm9 !add rsi,64 !dec rcx ;Chunks !jnz @b EndProcedure ; ***************** ;- **** Public **** ; ***************** Procedure IsCPU_SHA() Protected x.l=0 !mov eax,7 !xor ecx,ecx !cpuid !mov dword [p.v_x], ebx ProcedureReturn Bool(x & $20000000) EndProcedure Procedure CPU_StartFingerprint() Protected *p.SHA_Data = 0 *p = AllocateStructure(SHA_Data) If *p With *p \BuffSize=0 \AllSize=0 CopyMemory(?CONST_H0_H4, @\xmm0, 16) CopyMemory(?CONST_H0_H4+16, @\xmm1, 16) EndWith EndIf ProcedureReturn *p DataSection CONST_H0_H4: Data.l $10325476, $98BADCFE, $0EFCDAB89, $67452301, 0, 0, 0, $0C3D2E1F0 ; Start-Values H0-H4 EndDataSection EndProcedure Procedure CPU_CopyInstance(*Sha.SHA_Data) Protected *p=0 If *Sha *p = AllocateStructure(SHA_Data) If *p CopyStructure(*Sha, *p, SHA_Data) EndIf EndIf ProcedureReturn *p EndProcedure Procedure CPU_AddFingerprintBuffer(*Sha.SHA_Data, *Buffer, Size) Protected r = #False, *p=0, x, BuffPos=0 If *Sha And *Buffer And Size>0 r = #True With *Sha If \BuffSize>0 If \BuffSize+Size<=#SHA1_ChunksSize CopyMemory(*Buffer, @\Buff[\BuffSize], Size) \BuffSize+Size Size=0 Else x=#SHA1_ChunksSize-\BuffSize CopyMemory(*Buffer, @\Buff[\BuffSize], x) SetReg(*Sha) SHA1_Calc(@\Buff, 1) GetReg(*Sha) \AllSize + #SHA1_ChunksSize \BuffSize=0 BuffPos = x Size - x EndIf EndIf If Size>0 x = Size / #SHA1_ChunksSize If x > 0 SetReg(*Sha) SHA1_Calc(*Buffer + BuffPos, x) GetReg(*Sha) \AllSize + x * #SHA1_ChunksSize EndIf x = Size % #SHA1_ChunksSize If x>0 CopyMemory(*Buffer + BuffPos + (Size-x), @\Buff[\BuffSize], x) \BuffSize+x EndIf EndIf EndWith EndIf ProcedureReturn r EndProcedure Procedure.s CPU_GetSHA(*Sha.SHA_Data) Protected r.s, Size, *p=0, i If *Sha *p = AllocateMemory(#SHA1_ChunksSize) If *p With *Sha If (\BuffSize=0 Or \BuffSize>=56) And \BuffSize<#SHA1_ChunksSize \Buff[\BuffSize]=$80 For i=\BuffSize+1 To #SHA1_ChunksSize-1 \Buff[i]=0 Next i=\AllSize+\BuffSize !mov rax,[p.v_i] !shl rax,3 !bswap rax !mov [p.v_i],rax ;Bits to encoded If \BuffSize=0 PokeB(*p, $80) EndIf PokeQ(*p + #SHA1_ChunksSize - 8, i) SetReg(*Sha) If \BuffSize>0 SHA1_Calc(@\Buff, 1) EndIf SHA1_Calc(*p, 1) ElseIf \BuffSize<56 \Buff[\BuffSize]=$80 i=\AllSize+\BuffSize !mov rax,[p.v_i] !shl rax,3 !bswap rax !mov [p.v_i],rax ;Bits to encoded PokeQ(@\Buff[56], i) SetReg(*Sha) SHA1_Calc(@\Buff, 1) Else CallDebugger EndIf EndWith !mov rdi,[p.p_p] !pshufd xmm0,xmm0,1bh !movdqu [rdi],xmm0 !pextrd [rdi+16],xmm1,3 For i = 0 To 16 Step 4 r + RSet(Hex(PeekL(*p + i) & $FFFFFFFF), 8, "0") Next FreeMemory(*p) EndIf EndIf ProcedureReturn r EndProcedure Procedure.s CPU_FinishFingerprint(*Sha.SHA_Data) Protected r.s If *Sha r = CPU_GetSHA(*Sha) FreeStructure(*Sha) EndIf ProcedureReturn r EndProcedure Procedure.s CPU_Fingerprint(*Buffer, Size) Protected r.s, *p *p=CPU_StartFingerprint() If *p CPU_AddFingerprintBuffer(*p, *Buffer, Size) r = CPU_FinishFingerprint(*p) EndIf ProcedureReturn r EndProcedure Procedure.s CPU_StringFingerprint(s.s) Protected r.s, *p=UTF8(s) If *p r = CPU_Fingerprint(*p, MemorySize(*p)-1) FreeMemory(*p) EndIf ProcedureReturn r EndProcedure EndModule
В первую очередь проверьте поддерживает ли процессор необходимые инструкции.
UseModule CPU_SHA1 If IsCPU_SHA() Debug "SHA инструкции поддерживаются" Else Debug "SHA инструкции НЕ поддерживаются" EndIf
Если не поддерживает, значит пора обновлять комп.
Стандартный тест из вики
UseSHA1Fingerprint() UseModule CPU_SHA1 s.s="В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!" Debug CPU_StringFingerprint(s) Debug StringFingerprint(s, #PB_Cipher_SHA1)
Тоже с лисицей и собакой
UseSHA1Fingerprint() UseModule CPU_SHA1 s.s="The quick brown fox jumps over the lazy dog." Debug CPU_StringFingerprint(s) Debug StringFingerprint(s, #PB_Cipher_SHA1)
Хеширование 1 ГБ случайных данных для сравнения скорости CPU и функций PB.
UseSHA1Fingerprint() UseModule CPU_SHA1 Count = 100 Size=10*1024*1024 *Buff = AllocateMemory(Size) If *Buff RandomData(*Buff, Size) Define sPB.s, sCPU.s, tPB, tCPU, i tPB = ElapsedMilliseconds() If StartFingerprint(0, #PB_Cipher_SHA1) For i = 1 To Count AddFingerprintBuffer(0, *Buff, Size) Next sPB = UCase(FinishFingerprint(0)) EndIf tPB = ElapsedMilliseconds() - tPB tCPU = ElapsedMilliseconds() *p=CPU_StartFingerprint() If *p For i = 1 To Count CPU_AddFingerprintBuffer(*p, *Buff, Size) Next sCPU = CPU_FinishFingerprint(*p) EndIf tCPU = ElapsedMilliseconds() - tCPU MessageRequester("",~"PB \nВремя = "+tPB+~" мс\n"+sPB+~"\n\nCPU\nВремя = "+tCPU+~" мс\n"+sCPU) FreeMemory(*Buff) EndIf