Help with assembler code
push eax
push ecx
and eax,0x3C
ror eax,1
ror eax,1
inc eax
mov edx,eax
pop eax
xor eax,edx
pop ecx
xor eax,ecx
rol al,1
ret
can anybody help me understand what this开发者_如何学运维 code is doing by commenting it and why we do such routines like and and ror? Thanks
This code does the same as:
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));
}
If I read it all right, that is. Quite convoluted - where's it from ?
In any case, for the details:
Start with: From the use of EAX
/ ECX
as arguments, it can be seen that this uses Microsoft's __fastcall
calling convention (arg0
of a function in EAX
, arg1
in ECX
).
Then just follow the arithmetic through. Apart from the last use of rotation on AL
only, it's actually simple then:
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 gave me an idea here ... if the function actually operates on bytes explicitly, then it can be stated in a simpler way:
char transmogrify(char arg0, char arg1)
{
char tmp = (arg1 ^ (((arg0 << 2) >> 4) + 1))) ^ arg0;
return ((tmp << 7) | (tmp >> 1));
}
This sort of rotate(a ^ X ^ b, 1)
operation is used as part of some ciphers like DES, but what exactly you have depends on the X
(which is just a bit shuffle here). I'm not a cryptography expert, and don't recognize the specific case. It'd be interesting if someone can fill the gap in ...
push eax ; pushing eax into stack
push ecx ; pushing ecx into stack
and eax,0x3C ; performs logical and operation on eax and 0x3C
ror eax,1 ; one bit right shift value from eax with carrying shifted bit to most significant bit (cyclic right shift)
ror eax,1 ; one bit right shift value from eax with carrying shifted bit to most significant bit (cyclic right shift)
inc eax ; increment eax value
mov edx,eax ; copy value from eax to edx
pop eax ; restore eax value from stack, which was pushed by this command "push ecx"
xor eax,edx ; exclusive or operation on eax and edx values
pop ecx ; restore ecx value from stack, which was pushed by this command "push eax"
xor eax,ecx ; exclusive or operation on eax and ecx values
rol al,1 ; one bit left shift value from al (least significant byte from eax) with carrying shifted bit to least significant bit (cyclic left shift)
ret ; return from function
and I suggest you to read some articles from https://stackoverflow.com/questions/199679/good-beginners-books-for-assembly-languages
push eax - saves eax to stack
push ecx - saves ecx to stack
and eax,0x3C - logical AND register eax with 0x3c ( 111100 in binary) - this means that only 4 bits starting from bit 2 are interesting - in C : a = a &
0x3C;
ror eax,1 - rotate one bit right - in C : a = a >> 1;
ror eax,1 - rotate one bit right - in C : a = a >> 1; so after this command these 4 interesting bits starting in position 0;
inc eax - increse these 4 bits value by one - in C : a++;
mov edx,eax - copy value from register eax to register edx
pop eax - load value from stack (value that was previously in ecx) and copy it to eax registry
xor eax,edx - xor value from stack(previously ecx) with incremented 4bits value - in C : b = b ^ a;
pop ecx - load value from stack (value that was previously in eax) and copy it to ecx registry
xor eax,ecx - xor value from stack(previously eax) once again - in C : c = c ^ b;
rol al,1 - rotate left by one bit the last byte (al) of registry eax - in C : c = (unsigned char)c << 1;
ret - return from function - probably this what is in EAX is a return value
So more or less this is how this function could looks like in C
unsigned char func1(unsigned int parm1, insigned int parm2)
{
unsigned int a = par1 & 0x3C;
a = a >> 1;
a = a >> 1;
a++;
a = parm2 ^ a;
a = parm1 ^ a;
return (unsigned char)a << 1;
}
精彩评论