mã máy x86, 46 byte
Hexdump:
57 53 33 c0 33 ff f6 01 0f 75 15 6a 0a 5b 99 f7
f3 6b ff 0a 03 fa 33 c0 38 01 75 0f 97 5b 5f c3
69 c0 26 2b aa 6e 32 01 c1 e8 02 41 eb d8
Đó là một fastcall
hàm - nhận một con trỏ tới chuỗi trong ecx
và trả về kết quả eax
.
Hàm băm nhân với một số ma thuật 1856645926
, thực hiện XOR
với byte đầu vào và dịch chuyển sang phải 2 bit.
Việc lưu và khôi phục các thanh ghi noclobber ( edi
và ebx
) mất 4 byte, nhưng tôi không tìm thấy cách nào hiệu quả hơn để thực hiện điều này. Lưu trữ liên tục 10 trong ebx
là đặc biệt khó chịu!
Tháo gỡ với các byte mã tương ứng:
57 push edi ; edi = result
53 push ebx ; we use ebx to store the constant 10
33 C0 xor eax,eax
33 FF xor edi,edi
myloop:
F6 01 0F test byte ptr [ecx],0Fh ; check for end of word
75 15 jne myhash
6A 0A push 0Ah
5B pop ebx
99 cdq ; prepare 64-bit dividend in edx:eax
F7 F3 div eax,ebx ; find the remainder of division by 10
6B FF 0A imul edi,edi,0Ah
03 FA add edi,edx ; update the result
33 C0 xor eax,eax ; reset the hash temporary variable
38 01 cmp byte ptr [ecx],al ; check for end of input (here al=0)
75 0F jne mycontinue
97 xchg eax,edi ; set the return register
5B pop ebx ; restore registers
5F pop edi ; restore registers
C3 ret
myhash:
69 C0 26 2B AA 6E imul eax,eax,6EAA2B26h ; hashing...
32 01 xor al,byte ptr [ecx] ; hashing...
C1 E8 02 shr eax,2 ; hashing...
mycontinue:
41 inc ecx ; next input byte
EB D8 jmp myloop
Mã C tương đương:
int doit(const char* s)
{
int result = 0;
unsigned temp = 0;
while (true)
{
int c = *s++;
if ((c & 15) == 0)
{
temp %= 10;
result = result * 10 + temp;
temp = 0;
if (c == 0)
break;
else
continue;
}
temp *= 1856645926;
temp ^= c;
temp >>= 2;
}
return result;
}