这段翻译好的汇编代码还有什么更大的意义吗?
Is there any larger significance to this piece of translated assembly code?
对于 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 , %eax // left shift all bits in long y by 31 places
sarl , %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
有效的结论是我们从 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
澄清一下,这不是硬件分配的一部分;我已经通过翻译代码完成了作业,但我很想知道为什么他一开始就给了我们 this 代码。
我的猜测是您的教授试图说明如何使用 bit-shifting/masking 操作来避免分支。如果你天真地翻译
y -= z;
if (y % 2 == 0) return y * x;
return -(y * x) - 1;
转换为机器代码,您可以为条件语句使用分支指令。分支会显着降低您的代码速度,尤其是当它们处于紧密循环中时*。汇编代码和您前面的 C 代码具有使用条件 y - z
是否为偶数的效果,但仅使用算术指令。
*如果您还不熟悉这个事实,this SO answer 有我最喜欢的插图之一。
对于 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 , %eax // left shift all bits in long y by 31 places
sarl , %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
有效的结论是我们从 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
澄清一下,这不是硬件分配的一部分;我已经通过翻译代码完成了作业,但我很想知道为什么他一开始就给了我们 this 代码。
我的猜测是您的教授试图说明如何使用 bit-shifting/masking 操作来避免分支。如果你天真地翻译
y -= z;
if (y % 2 == 0) return y * x;
return -(y * x) - 1;
转换为机器代码,您可以为条件语句使用分支指令。分支会显着降低您的代码速度,尤其是当它们处于紧密循环中时*。汇编代码和您前面的 C 代码具有使用条件 y - z
是否为偶数的效果,但仅使用算术指令。
*如果您还不熟悉这个事实,this SO answer 有我最喜欢的插图之一。