汇编语言到 C 问题与寄存器
Assembly Language to C issue with registers
我正在尝试编写 C 代码,其效果等同于以下汇编代码:
addq %rsi, %rdi
imulq %rdx, %rdi
movq %rdi, %rax
sarq , %rax
salq , %rax
andq %rdi, %rax
ret
有函数原型
长解码(长x,长y,长z)
参数 x、y 和 z 在寄存器 %rdi、%rsi 和 %rdx 中传递。该代码将 return 值存储在寄存器 %rax 中。
到目前为止,我有以下 C 代码:
long decode(long x, long y, long z)
{
long w;
x = x+y;
x = x*z;
w = x;
w = ((x>>15)<<31);
return x&w;
}
其中,当使用 gcc -O2 -S -c filename.c 编译时产生以下内容:
addq %rdi, %rsi
imulq %rdx, %rsi
movq %rsi, %rax
sarq , %rax
salq , %rax
andq %rsi, %rax
ret
显然,寄存器 %rdi 和 %rsi 被交换了。
所以,如果我通过交换 x 和 y 来更改函数,它看起来像这样:
long decode4(long x, long y, long z)
{
long w;
y = x + y;
y = y * z;
w = y;
w = ((y>>15)<<31);
return y&w;
}
并且,程序集再次如下所示:
addq %rdi, %rsi
imulq %rdx, %rsi
movq %rsi, %rax
sarq , %rax
salq , %rax
andq %rsi, %rax
ret
y 和 x 的交换,并没有改变生成的汇编代码中的任何东西。
关于如何解决该问题的任何想法?
谢谢!
编译器已优化您的代码,因此在交换 x 和 y 后您看不到汇编代码有任何差异。
您的代码被编译器处理如下,
long decode4(long x, long y, long z)
{
long w;
// y = x + y;
// y = y * z;
// w = y;
// The above three lines are combined as
x = (x + y)*z; // result of addition and multiplication in rsi
w = x; // move the above result to rax
//w = ((y>>15)<<31);
//return y&w;
//The above two lines are treated as
w = ((w>>15)<<31); // shift operations on rax
return x&w; // rax and rsi
}
x 或 y 的变化不会影响此函数的预期行为,因此编译器对其进行了优化。
希望对您有所帮助。
您也可以尝试使用优化 O0(无优化)编译您的代码,然后您可以看到汇编代码的变化如您所愿。
您对代码的解读确实没有任何问题:
long decode(long x, long y, long z)
{
long w;
x = x+y;
x = x*z;
w = x;
w = ((x>>15)<<31);
return x&w;
}
它可以简化一点,但它没有任何问题,因为输出仅在所用寄存器的反转方面有所不同。可观察到的结果将是相同的。您声明此要求:
I am trying to write C code that will have an effect equivalent to the following assembly
两者等价所以我相信你的解决方案已经满足了作业。
有时这种类型的事情可以归结为所使用的编译器。我注意到我可以使用 GCC 4.6.4 和 -O2
优化级别获得您正在寻找的确切输出。您可以在 godbolt 上使用此代码,输出为:
decode:
addq %rsi, %rdi
imulq %rdx, %rdi
movq %rdi, %rax
sarq , %rax
salq , %rax
andq %rdi, %rax
ret
这似乎与您课程的输出完全匹配。使用相同版本的 GCC (4.6.4) 您可以获得相同的输出:
long decode(long x, long y, long z)
{
x = (x + y) * z;
return x & ((x >> 15) << 31);
}
我正在尝试编写 C 代码,其效果等同于以下汇编代码:
addq %rsi, %rdi
imulq %rdx, %rdi
movq %rdi, %rax
sarq , %rax
salq , %rax
andq %rdi, %rax
ret
有函数原型
长解码(长x,长y,长z)
参数 x、y 和 z 在寄存器 %rdi、%rsi 和 %rdx 中传递。该代码将 return 值存储在寄存器 %rax 中。
到目前为止,我有以下 C 代码:
long decode(long x, long y, long z)
{
long w;
x = x+y;
x = x*z;
w = x;
w = ((x>>15)<<31);
return x&w;
}
其中,当使用 gcc -O2 -S -c filename.c 编译时产生以下内容:
addq %rdi, %rsi
imulq %rdx, %rsi
movq %rsi, %rax
sarq , %rax
salq , %rax
andq %rsi, %rax
ret
显然,寄存器 %rdi 和 %rsi 被交换了。
所以,如果我通过交换 x 和 y 来更改函数,它看起来像这样:
long decode4(long x, long y, long z)
{
long w;
y = x + y;
y = y * z;
w = y;
w = ((y>>15)<<31);
return y&w;
}
并且,程序集再次如下所示:
addq %rdi, %rsi
imulq %rdx, %rsi
movq %rsi, %rax
sarq , %rax
salq , %rax
andq %rsi, %rax
ret
y 和 x 的交换,并没有改变生成的汇编代码中的任何东西。 关于如何解决该问题的任何想法? 谢谢!
编译器已优化您的代码,因此在交换 x 和 y 后您看不到汇编代码有任何差异。
您的代码被编译器处理如下,
long decode4(long x, long y, long z)
{
long w;
// y = x + y;
// y = y * z;
// w = y;
// The above three lines are combined as
x = (x + y)*z; // result of addition and multiplication in rsi
w = x; // move the above result to rax
//w = ((y>>15)<<31);
//return y&w;
//The above two lines are treated as
w = ((w>>15)<<31); // shift operations on rax
return x&w; // rax and rsi
}
x 或 y 的变化不会影响此函数的预期行为,因此编译器对其进行了优化。
希望对您有所帮助。
您也可以尝试使用优化 O0(无优化)编译您的代码,然后您可以看到汇编代码的变化如您所愿。
您对代码的解读确实没有任何问题:
long decode(long x, long y, long z)
{
long w;
x = x+y;
x = x*z;
w = x;
w = ((x>>15)<<31);
return x&w;
}
它可以简化一点,但它没有任何问题,因为输出仅在所用寄存器的反转方面有所不同。可观察到的结果将是相同的。您声明此要求:
I am trying to write C code that will have an effect equivalent to the following assembly
两者等价所以我相信你的解决方案已经满足了作业。
有时这种类型的事情可以归结为所使用的编译器。我注意到我可以使用 GCC 4.6.4 和 -O2
优化级别获得您正在寻找的确切输出。您可以在 godbolt 上使用此代码,输出为:
decode:
addq %rsi, %rdi
imulq %rdx, %rdi
movq %rdi, %rax
sarq , %rax
salq , %rax
andq %rdi, %rax
ret
这似乎与您课程的输出完全匹配。使用相同版本的 GCC (4.6.4) 您可以获得相同的输出:
long decode(long x, long y, long z)
{
x = (x + y) * z;
return x & ((x >> 15) << 31);
}