The shifts are not useless. It is a form of banchless logic that Hexray did not manage to reproduce in its c disassembly.
.text:0040DD55 movsx eax, si
.text:0040DD58 cdq
.text:0040DD59 xor eax, edx
.text:0040DD5B sub eax, edx
.text:0040DD5D and eax, 7
.text:0040DD60 xor eax, edx
.text:0040DD62 sub eax, edx
Is the significant code. EDX:EAX
is the sign-extended version of SI
, so EDX
is either 0 or -1. The xor
either leaves eax
untouched or inverts it, the sub
leaves it untouched or adds one and so on in total:
if (si < 0) {
eax = ~si;
eax += 1;
eax &= 0x7;
eax = ~eax;
eax += 1;
} else {
eax = si & 0x7;
}
The first branch can still be simplified, but I leave that to you...
update
That the branches only differ for si<0
already gives a hint at what is happening. The sequence eax = ~si; eax += 1;
can be understood as the two's-complement, so inserting our knowledge of this complement we get
if (si < 0) {
eax = -1 * si;
eax &= 0x7;
eax *= -1;
} else {
eax = si & 0x7;
}
or in short
eax = (abs(si) & 0x7) * sign(si);
Or with the signed modulus operator
al = si % 8;