c - 汇编语言到 C 问题与寄存器

标签 c gcc assembly x86-64 att

我正在尝试编写 C 代码,其效果等同于以下汇编代码:

addq %rsi, %rdi
imulq %rdx, %rdi
movq %rdi, %rax
sarq $15, %rax
salq $31, %rax
andq %rdi, %rax
ret

有一个函数原型(prototype)

长解码(长x,长y,长z)

参数 x、y 和 z 在寄存器 %rdi、%rsi 和 %rdx 中传递。代码将返回值存储在寄存器 %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 $15, %rax
salq $31, %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 $15, %rax
 salq $31, %rax
 andq %rsi, %rax
 ret

y 和 x 的交换,并没有改变生成的汇编代码中的任何东西。 关于如何解决该问题的任何想法? 谢谢!

最佳答案

您对代码的解释确实没有任何问题:

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    $15, %rax
        salq    $31, %rax
        andq    %rdi, %rax
        ret

这似乎与您类(class)的输出完全匹配。使用相同版本的 GCC (4.6.4),您可以获得相同的输出:

long decode(long x, long y, long z)
{
  x = (x + y) * z;
  return x & ((x >> 15) << 31);
}

关于c - 汇编语言到 C 问题与寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49343708/

相关文章:

assembly - Grub 和进入实模式(低级汇编语言编程)

c++ - 如何避免 C 和 C++ 中的命名空间冲突

linux - 在 Mac/BSD 上学习 x86 程序集 : Kernel built-in functions? 如何知道参数/顺序?

可以将地址分配给C中的变量吗?

c - 如何在 Linux 中读取和写入 fifo(命名管道)?

c - 决定尝试一下 C 中的自制函数

c - 使用 goto 跳过范围变量初始化不会产生所需的输出

c++ - 如何实现用gcc-4.4编译的大 vector 初始化?

linux - Ubuntu中Mit Scheme安装错误(环境变量设置)

performance - 为什么通过引用传递结构不是常见的优化?