Вверх ↑
Ответов: 273
Рейтинг: 29
#1: 2011-04-10 09:09:36 ЛС | профиль | цитата
Tad, делись исходником

Сам пока нашел интересный алгоритм на http://guildalfa.ru/alsha/node/2
Пробовал засунуть в инлайн - стандартный компилятор ругается на ассемблер, fpc не ругается, но не дает создать событие.
Пока дошел до такого:
Add(InlineCode,9593793,483,406)
{
WorkPoints=#33:doCRC32=Начинает вычисление CRC32|
EventPoints=#32:onCRC32=Выдает вычесленный CRC32|
DataPoints=#46:Data=Данные, для которых нужно вычислить CRC32|68:OldCRC32=CRC32 предыдущего фрагмента. Для первого фрагмента=FFFFFFFF|
Code=#15:unit HiAsmUnit;|0:|9:interface|0:|21:uses kol,Share,Debug;|0:|4:type|28: THiAsmClass = class(TDebug)|10: private|4: |34:// function CrcRefresh:cardinal;|30:// function CRCInit:boolean;|3: |9: public|3: |24: _data_Data:THI_Event;|28: _data_OldCRC32:THI_Event;|21: onCRC32:THI_Event;|68: procedure doCRC32(var _Data:TData; Index:word);//Вычисление CRC32|0:|5: end;|0:|14:implementation|1: |3:var|48: tbl: array[0..7] of array[0..255] of cardinal;|15: Init:integer;|77://···········································································|77://·····················http://guildalfa.ru/alsha/node/2······················|77://···········································································|0:|81:function CrcRefresh(OldCRC: cardinal; BufPtr: pointer; BufLen: integer):cardinal;|3:asm|15: test edx, edx|11: jz @ret|10: neg ecx|11: jz @ret|10: push ebx|6:@head:|12: test dl, 3|16: jz @bodyinit|23: movzx ebx, byte [edx]|10: inc edx|13: xor bl, al|13: shr eax, 8|25: xor eax, [ebx*4 + tbl]|10: inc ecx|12: jnz @head|10: pop ebx|5:@ret:|5: ret|10:@bodyinit:|15: sub edx, ecx|13: add ecx, 8|16: jg @bodydone|10: push esi|10: push edi|15: mov edi, edx|15: mov edx, eax|10:@bodyloop:|26: mov ebx, [edi + ecx - 4]|26: xor edx, [edi + ecx - 8]|15: movzx esi, bl|33: mov eax, [esi*4 + tbl + 1024*3]|15: movzx esi, bh|33: xor eax, [esi*4 + tbl + 1024*2]|13: shr ebx, 16|15: movzx esi, bl|33: xor eax, [esi*4 + tbl + 1024*1]|15: movzx esi, bh|33: xor eax, [esi*4 + tbl + 1024*0]|0:|15: movzx esi, dl|33: xor eax, [esi*4 + tbl + 1024*7]|15: movzx esi, dh|33: xor eax, [esi*4 + tbl + 1024*6]|13: shr edx, 16|15: movzx esi, dl|33: xor eax, [esi*4 + tbl + 1024*5]|15: movzx esi, dh|33: xor eax, [esi*4 + tbl + 1024*4]|0:|12: add ecx, 8|12: jg @done |0:|26: mov ebx, [edi + ecx - 4]|26: xor eax, [edi + ecx - 8]|15: movzx esi, bl|33: mov edx, [esi*4 + tbl + 1024*3]|15: movzx esi, bh|33: xor edx, [esi*4 + tbl + 1024*2]|13: shr ebx, 16|15: movzx esi, bl|33: xor edx, [esi*4 + tbl + 1024*1]|15: movzx esi, bh|33: xor edx, [esi*4 + tbl + 1024*0]|0:|15: movzx esi, al|33: xor edx, [esi*4 + tbl + 1024*7]|15: movzx esi, ah|33: xor edx, [esi*4 + tbl + 1024*6]|13: shr eax, 16|15: movzx esi, al|33: xor edx, [esi*4 + tbl + 1024*5]|15: movzx esi, ah|33: xor edx, [esi*4 + tbl + 1024*4]|0:|12: add ecx, 8|15: jle @bodyloop|14: mov eax, edx|6:@done:|14: mov edx, edi|9: pop edi|9: pop esi|10:@bodydone:|12: sub ecx, 8|10: jl @tail|9: pop ebx|5: ret|6:@tail:|30: movzx ebx, byte [edx + ecx];|12: xor bl,al;|12: shr eax,8;|25: xor eax, [ebx*4 + tbl];|10: inc ecx;|12: jnz @tail;|9: pop ebx|5: ret|6: end;|0:|77://···········································································|0:|18:procedure CRCInit;|3:var|14: c: cardinal;|16: i, j: integer;|6:begin;|27: for i:=0 to 255 do begin;|9: c:=i;|30: for j:=1 to 8 do if odd(c)|52: then c:=(c shr 1) xor $EDB88320|39: else c:=(c shr 1);|17: tbl[0][i]:=c;|8: end;|0:|27: for i:=0 to 255 do begin;|17: c:=tbl[0][i];|27: for j:=1 to 7 do begin;|39: c:=(c shr 8) xor tbl[0][byte(c)];|19: tbl[j][i]:=c;|10: end;|8: end;|49:// CrcRefresh($FFFFFFFF, @tbl[0,0], SizeOf(tbl))|16:// = $1A76768F);|8: end; |0:|77://...........................................................................|0:|59:procedure THiAsmClass.doCRC32(var _Data:TData; Index:word);|4:var |13:buff:string; |18:old,crc:cardinal; |12:len:integer;|5:begin|38://Рассчет таблиц - это очень накладно.|59://Потому выполняем его только если их уже/еще нет в памяти!|56://А теперь проверяем их наличие и вычисляем, если нужно:|45: If Init=0 then begin CRCInit; Init:=1; end;|16://Вычисляем CRC:|19://Грузим старую CRC|42: buff:=ReadString(_Data, _data_OldCRC32);|21: old:=Hex2Int(buff);|14://Грузим буфер|38: buff:=ReadString(_Data, _data_Data);|20: len:=Length(buff);|18://Обрабатываем его|35: crc:=CrcRefresh(old, @buff, len);|23: buff:=Int2Hex(crc,8);|18://Отдаем результат|27: _hi_OnEvent(onCRC32,crc);|6: end;|0:|77://···········································································|4:end.|
link(onCRC32,8882687:doMessage,[])
link(OldCRC32,4975099:Value,[])
}
Add(MainForm,2953706,350,350)
{
}
Add(Button,14533549,350,406)
{
Width=160
Caption="map"
link(onClick,1029845:doConvert,[])
}
Add(Message,8882687,532,406)
{
}
Add(CRC16_32,8038859,420,455)
{
}
Add(MemoryStream,14693252,420,350)
{
}
Add(StreamConvertor,1029845,420,406)
{
Mode=6
link(onResult,9593793:doCRC32,[])
link(Data,14693252:Stream,[])
}
Add(Memory,4975099,490,350)
{
Default=String(FFFFFFFF)
}


code_23293.txt
В MemoryStream предполагалось загрузить файл для отладки, но пока до этого не дошел.

С fpc тоже ситуация не радует - тогда и весь проект должен быть под fpc.
Варианты: Скомпилить под fpc dll с кодом и подключать ее когда надо либо исправить асм под стандартный компилятор либо разобрать алгоритм и переписать его под стандартный компилятор без ассемблера.
Все не веселые.

Да, мне с этими вариантами помощь не нужна - сам разберусь, если буду дальше этот алгоритм мусолить.
Все равно это муторно и занимаюсь этим не по необходимости, а от нечего делать Так что вам свое время тратить не стоит.


Вопрос пока такой:
с чего при создании событий fpc выдает Can't determine which overloaded function to call?
Пробовал
_hi_CreateEvent(_Data,@onCRC32,crc);
_hi_OnEvent(onCRC32,crc);
В обоих случаях ошибка та же. И указывает на строку с попыткой создать событие.
Просто пока хотелось бы погонять алгоритм хоть под fpc - оценить его скорость и работоспособность. Если действительно быстрый - попытаться оптимизировать.
карма: 0

0