delphi - Implementation of FNV -
i trying implement fnv hash http://isthe.com/chongo/tech/comp/fnv/
i converted powerbasic's inline asm on page delphi.
function readfiletomem(spath:string):pointer; var hfile: thandle; pbuffer: pointer; dsize: dword; dread: dword; begin hfile := createfile(pchar(spath), generic_read, file_share_read, nil, open_existing, 0, 0); if hfile <> 0 dsize := getfilesize(hfile, nil); if dsize <> 0 begin setfilepointer(hfile, 0, nil, file_begin); getmem(result, dsize); readfile(hfile, result^, dsize, dread, nil); if dread = 0 messagebox(0, pchar('error reading file.'), pchar('read error'), mb_iconexclamation) end; closehandle(hfile); end; function getpointersize(lpbuffer: pointer): cardinal; // function erazerz begin if lpbuffer = nil result := cardinal(-1) else result := cardinal(pointer(cardinal(lpbuffer) -4)^) , $7ffffffc -4; end; function fnv32( dwoffset : pointer; dwlen : dword; offset_basis : dword) : dword ; asm mov esi, dwoffset //;esi = ptr buffer mov ecx, dwlen //;ecx = length of buffer (counter) mov eax, offset_basis //;set 2166136261 fnv-1 mov edi, 16777619//&h01000193 //;fnv_32_prime = 16777619 xor ebx, ebx //;ebx = 0 @nextbyte: mul edi //;eax = eax * fnv_32_prime mov bl, [esi] //;bl = byte esi xor eax, ebx //;al = al xor bl inc esi //;esi = esi + 1 (buffer pos) dec ecx //;ecx = ecx - 1 (counter) jnz @nextbyte //;if ecx 0, jmp nextbyte mov @result, eax //;else, function = eax end; procedure tform1.button1click(sender: tobject); var pfile : pointer; hfile : cardinal; begin //profiler1['test'].start; pfile := readfiletomem(fn); hfile := fnv32(pfile,getpointersize(pfile),2166136261); //profiler1['test'].stop; //outputdebugstring(pchar(profiler1['test'].astext[tiall])); outputdebugstring(pchar(inttostr(hfile))); end;
if size of given file more 200kb, output random (hash) number. missing something?
your asm code buggy, imho. crash application, written.
- you need preseve esi/edi/ebx registers
- parameters passed in eax,ecx,edx registers
- result eax register
correct way (not tested, written here there):
function fnv32(dwoffset : pointer; dwlen : dword; offset_basis: dword) : dword ; asm // eax=dwoffset ecx=dwlen edx=offset_basis -> result in eax push esi push edi mov esi,eax mov eax,edx or ecx,ecx je @z mov edi,16777619 xor edx,edx @1: mul edi mov dl,[esi] xor eax,edx inc esi dec ecx jnz @1 @z: pop edi pop esi end;
so read , hash file, in pure delphi way (don't use windows api did):
function fnv32file(const afilename: tfilename): dword; begin tmemorystream.create try loadfromfile(afilename); result := fnv32(memory,size,0); free; end; end;
a pure pascal version won't slower imho (the bottleneck definitively reading data hard drive):
function fnv32(dwoffset : pbytearray; dwlen : dword; offset_basis: dword): dword ; var i: integer; begin result := offset_basis; := 0 dwlen-1 result := (result*16777619) xor dword(dwoffset^[i]); end;
Comments
Post a Comment