Ce code fait la même chose que:
unsigned int func(arg0, arg1)
{
unsigned int tmp = (arg1^(((arg0 & 0x3C) >> 2) + 1))^arg0;
unsigned char c = (unsigned char)(tmp & 0xff);
return (tmp & ~0xff) | (unsigned int)((c << 7) | (c >> 1));
}
Si je lis bien, ce qui est. Tout à fait alambiqué - d'où vient-il?
Dans tous les cas, pour les détails:
Commencez par: De l'utilisation de EAX
/ECX
comme arguments, on peut voir que celui-ci utilise la convention d'appel __fastcall
de Microsoft (arg0
d'une fonction dans EAX
, arg1
dans ECX
).
Ensuite, il suffit de suivre l'arithmétique à travers. En dehors de la dernière utilisation de la rotation sur AL
seulement, il est en fait simple alors:
push eax ; saves arg0 to stack
push ecx ; saves arg1 to stack
and eax,0x3C ; tmp = arg0 & 0x3C (this isolates bits 3-6, makes all else zero)
ror eax,1 ;
ror eax,1 ; twice rot right. Since upper bits are zero: tmp >>= 2;
inc eax ; tmp++
mov edx,eax ; EDX = tmp
pop eax ; retrieve last item on stack, tmp2 = arg1
xor eax,edx ; tmp2 ^= tmp;
pop ecx ; retrieve prev item on stack, tmp3 = arg0
xor eax,ecx ; tmp2 ^= tmp3
; full line: (arg1^(((arg0 & 0x3C) >> 2) + 1))^arg0
rol al,1 ; complex ... rotate lowest byte right by one
; al = (al >> 1) | (al << 7)
;
ret
Edit: Zuljin m'a donné une idée ici ... si la fonction fonctionne en fait sur octets explicitement, il peut être déclaré dans une façon plus simple:
char transmogrify(char arg0, char arg1)
{
char tmp = (arg1^(((arg0 << 2) >> 4) + 1)))^arg0;
return ((tmp << 7) | (tmp >> 1));
}
Ce genre de rotate(a^X^b, 1)
opération est utilisée dans le cadre de certains chiffrements comme dES, mais ce que vous avez exactement dépend de la X
(qui est juste un remaniement peu ici). Je ne suis pas un expert en cryptographie et je ne reconnais pas le cas spécifique. Il serait intéressant si quelqu'un peut combler le vide dans ...
Le bit 'return (unsigned char) ...' est incorrect , car l'utilisation de 'AL' ne modifie pas les bits supérieurs de' EAX', qui ne sont pas nuls, au moins dans le cas des arguments ayant des bits supérieurs non nuls. La fonction par conséquent _either_ renvoie une valeur complète de 32 bits, ou _ attend que les deux arguments soient réels 8 bits (tous les bits supérieurs sont effacés). –