На просторах интернета набрёл на Параллельное вычисление CRC64
Из приложенных к статье исходников на Delphi пытаюсь частично перевести на PowerBasic
Интересует процедура ShaNormalRefreshCRC64, как самая быстрая из представленных...
- Код: Выделить всё
procedure ShaNormalRefreshCRC64(var CRC: int64; BufPtr: pointer; BufLen: integer);
asm
test edx, edx
jz @ret
neg ecx
jz @ret
push ebx
push esi
push eax
mov ebx, [eax+4]
mov esi, [eax]
bswap ebx
bswap esi
xor eax, eax
@head:
test dl, 3
jz @bodyinit
mov al, byte [edx]
inc edx
xor al, bl
shrd ebx, esi, 8
xor ebx, [eax*8 + ByteSwappedTable64]
shr esi, 8
xor esi, [eax*8 + ByteSwappedTable64 + 4]
add ecx, 1
jnz @head
bswap ebx
bswap esi
pop eax
mov [eax+4], ebx
mov [eax], esi
pop esi
pop ebx
@ret:
ret
@bodyinit:
sub edx, ecx
add ecx, 8
jg @bodydone
push edi
push ebp
mov ebp, ecx
// crc64: ebx-lo esi-hi
// data: eax-lo ecx-hi
// buffer: edx-base ebp-count
// table: edi-index
@bodyloop:
mov eax, [edx + ebp - 8]
xor eax, ebx
movzx edi, al
mov ecx, [edx + ebp - 4]
xor ecx, esi
mov ebx, [edi*8 + ByteSwappedTable64 + 2048*7]
mov esi, [edi*8 + ByteSwappedTable64 + 2048*7 + 4]
movzx edi, ah
xor ebx, [edi*8 + ByteSwappedTable64 + 2048*6]
xor esi, [edi*8 + ByteSwappedTable64 + 2048*6 + 4]
shr eax, 16
movzx edi, al
xor ebx, [edi*8 + ByteSwappedTable64 + 2048*5]
xor esi, [edi*8 + ByteSwappedTable64 + 2048*5 + 4]
movzx edi, ah
xor ebx, [edi*8 + ByteSwappedTable64 + 2048*4]
xor esi, [edi*8 + ByteSwappedTable64 + 2048*4 + 4]
movzx edi, cl
xor ebx, [edi*8 + ByteSwappedTable64 + 2048*3]
xor esi, [edi*8 + ByteSwappedTable64 + 2048*3 + 4]
movzx edi, ch
xor ebx, [edi*8 + ByteSwappedTable64 + 2048*2]
xor esi, [edi*8 + ByteSwappedTable64 + 2048*2 + 4]
shr ecx, 16
movzx edi, cl
xor ebx, [edi*8 + ByteSwappedTable64 + 2048*1]
xor esi, [edi*8 + ByteSwappedTable64 + 2048*1 + 4]
movzx edi, ch
xor ebx, [edi*8 + ByteSwappedTable64 + 2048*0]
xor esi, [edi*8 + ByteSwappedTable64 + 2048*0 + 4]
add ebp, 8
jle @bodyloop
mov ecx, ebp
pop ebp
pop edi
@bodydone:
sub ecx, 8
je @result
xor eax, eax
@tail:
mov al, byte [edx + ecx]
xor al, bl
shrd ebx, esi, 8
xor ebx, [eax*8 + ByteSwappedTable64]
shr esi, 8
xor esi, [eax*8 + ByteSwappedTable64 + 4]
add ecx, 1
jnz @tail
@result:
bswap ebx
bswap esi
pop eax;
mov [eax+4], ebx
mov [eax], esi
pop esi
pop ebx
end;
Объявление примет вид Function ShaNormalRefreshCRC64(ByVal BufPtr As Byte Ptr, BufLen As Dword) As Quad.
А вот с телом функции, даже и не знаю, нужно что-то делать или нет?..
Ещё есть инициализация таблиц:
- Код: Выделить всё
function CRC64Init: boolean;
const
EcmaPoly= $42F0E1EBA9EA3693; //ECMA DLT standard (normal form), reflected form = $C96C5795D7870F42;
//Other found polinomials
OldProteinReflectedPoly= $d800000000000000; //Bad poly (reflected ISO 3309) - too many collisions on proteins with two mutations
NewProteinReflectedPoly= $95AC9329AC4BC9B5; //By David T. Jones for protein data banks(reflected form)
var
Poly, ReflectedPoly, c: int64;
i, j: integer;
begin;
Poly:=EcmaPoly;
ReflectedPoly:=$C96C5795D7870F42;
//ReflectedPoly:=NewProteinReflectedPoly;
for i:=0 to 255 do begin;
c:=i;
for j:=1 to 8 do if odd(c)
then c:=(c shr 1) xor ReflectedPoly
else c:=(c shr 1);
ReflectedTable64[0][i]:=c;
c:=i;
c:=c shl 56;
for j:=1 to 8 do if c<0
then c:=(c shl 1) xor Poly
else c:=(c shl 1);
ReferenceTable64[i]:=c;
ByteSwap(c);
ByteSwappedTable64[0][i]:=c;
end;
for i:=0 to 255 do begin;
c:=ReflectedTable64[0][i];
for j:=1 to 7 do begin;
c:=(c shr 8) xor ReflectedTable64[0][byte(c)];
ReflectedTable64[j][i]:=c;
end;
c:=ByteSwappedTable64[0][i];
for j:=1 to 7 do begin;
c:=(c shr 8) xor ByteSwappedTable64[0][byte(c)];
ByteSwappedTable64[j][i]:=c;
end;
end;
Result:=true;
' необходимость дальнейших строк сомнительна
c:=-1; ReferenceRefreshCRC64(c,@ReferenceTable64[0],SizeOf(ReferenceTable64));
Result:=Result and ($305CD291B39AA09A=not c);
c:=-1; NormalRefreshCRC64(c,@ByteSwappedTable64[0,0],SizeOf(ByteSwappedTable64));
Result:=Result and ($F0347B5C2C7411D2=not c);
c:=-1; ShaNormalRefreshCRC64(c,@ByteSwappedTable64[0,0],SizeOf(ByteSwappedTable64));
Result:=Result and ($F0347B5C2C7411D2=not c);
if ReflectedPoly=$C96C5795D7870F42 then begin;
c:=-1; ReflectedRefreshCRC64(c,@ReflectedTable64[0,0],SizeOf(ReflectedTable64));
Result:=Result and ($014ED9B63590C55E=not c);
c:=-1; ShaReflectedRefreshCRC64(c,@ReflectedTable64[0,0],SizeOf(ReflectedTable64));
Result:=Result and ($014ED9B63590C55E=not c);
end;
end;
И вспомогательная функция:
- Код: Выделить всё
procedure ByteSwap(var Value: int64);
asm
mov ecx, [eax]
mov edx, [eax+4]
bswap ecx
bswap edx
mov [eax+4], ecx
mov [eax], edx
end;
Примет вид:
- Код: Выделить всё
Function SwapQuad(ByVal QuadVar As Quad) As Quad
Prefix "ASM"
mov ecx, [eax]
mov edx, [eax+4]
bswap ecx
bswap edx
mov [eax+4], ecx
mov [eax], edx
End Prefix
End Function
Всё, что касается заполнения таблиц перевёл так:
- Код: Выделить всё
%EcmaPoly = &H42F0E1EBA9EA3693&&
%ReflectedPoly = &HC96C5795D7870F42&&
Global ByteSwappedTable64() As Quad ' array[0..7] of array[0..255] of int64
Global ReflectedTable64() As Quad
Sub InitCRC_64
Local v As Quad
Register I As Dword, J As Dword
ReDim ByteSwappedTable64(7, 255)
ReDim ReflectedTable64(7, 255)
For I = 0 To 255
v = I
For J = 1 To 8
If v And 1 Then
Shift Right V, 1
v = v Xor %ReflectedPoly
Else
Shift Right v, 1
End If
Next J
ReflectedTable64(0, I) = v
v = I
Shift Left v, 56
For J = 1 To 8
If v < 0 Then
Shift Left v, 1
v = v Xor %EcmaPoly
Else
Shift Left v, 1
End If
Next J
ByteSwappedTable64(0, I) = SwapQuad(ByVal v)
Next I
For I = 0 To 255
v = ReflectedTable64(0, I)
For J = 1 To 7
Shift Right v, 8
ReflectedTable64(J, I) = v Xor ReflectedTable64(0, CByt(v))
Next J
v = ByteSwappedTable64(0, I)
For J = 1 To 7
Shift Right v, 8
ByteSwappedTable64(J, I) = v Xor ByteSwappedTable64(0, CByt(v))
Next J
Next I
End Sub
После испраления всех ошибок встанет вопрос проверки выдаваемых CRC64 этим алгоритмом с CRC64 некой проверенной софтины...