For a short homework assignment in CS Architecture, we were made to translate the following IA-32 assembly into C. I've translated it properly (as far as I know) but the code doesn't appear to do anything particularly useful. My professor typically gives us problems like this which end up doing something: our last assignment like this was a bit pop_count. Looking at the C code below, does this function do anything useful? Some algorithm maybe?
The code appears below (I've added comments to each ASM line).
// The following variables x, y, z are located at (%ebp) +8, +12, +16 respectively
// x, y, and z, are scanned from the terminal and passed into the function
movl 12(%ebp), %edx // moves long y to register %edx
subl 16(%ebp), %edx // subtracts longs: y = y - z
movl %edx, %eax // moves long y to register %eax
sall $31, %eax // left shift all bits in long y by 31 places
sarl $31, %eax // arithmetic right shift long y by 31 places
imull 8(%ebp), %edx // multiply longs: unshifted y = y * x
xorl %edx, %eax // XOR operation: shifted y = shifted y ^ unshifted y
// The returned value is stored in register %eax
The effective takeaway is we subtract z from y, then populate every bit with the least significant bit to form either zero or MAX_UINT. This is XOR'd with the product of (y - z) * x and returned.
My translation into C:
return (((y - z) << 31) >> 31) ^ ((y - z) * x);
// In more words:
int f;
y -= z;
f = y << 31; // These two lines populate all bits with the lsb
f = f >> 31; // Effectively, if y-z is odd: f is ~0; else f is 0
y *= x;
return y ^ f;
// Or, using people logic:
y -= z;
if (y % 2 == 0) return y * x;
return -(y * x) - 1;
// If the y-z is odd, the result will be: -1 * ((y - z) * x) - 1
// If the y-z is even, the result will be: (y - z) * x
For clarification, this is not part of the HW assignment; I've completed the assignment by translating the code, but I'm interested in knowing why he gave us this code to begin with.