Sen*_*zle 8 c algorithm x86 assembly reverse-engineering
对于CS体系结构中的简短家庭作业,我们将以下IA-32程序集转换为C.我已正确翻译它(据我所知),但代码似乎没有做任何特别有用的事情.我的教授通常会给我们这样的问题,最终会做一些事情:像我这样的最后一个任务就是pop_count.看下面的C代码,这个函数有用吗?有些算法可能吗?
代码如下所示(我已为每条ASM行添加了注释).
// 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
Run Code Online (Sandbox Code Playgroud)
有效的结果是我们从y中减去z,然后用最低有效位填充每一位以形成零或MAX_UINT.这与(y - z)*x的乘积进行异或并返回.
我对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
Run Code Online (Sandbox Code Playgroud)
为了澄清,这不是硬件分配的一部分; 我已经通过翻译代码完成了作业,但我很想知道他为什么开始给我们这个代码.
我的猜测是,您的教授试图说明如何使用位移/掩码操作来避免分支。如果你天真地翻译
y -= z;
if (y % 2 == 0) return y * x;
return -(y * x) - 1;
Run Code Online (Sandbox Code Playgroud)
到机器代码中,您可以使用条件分支指令。分支会极大地减慢您的代码速度,尤其是当它们位于紧密循环*内时。y - z汇编代码和前面的 C 代码具有使用条件判断是否为偶数的效果,但仅使用算术指令。
*如果您还不熟悉这个事实,这个答案有我最喜欢的插图之一。