c++ - 内联 gcc 汇编和局部变量( double )

标签 c++ gcc assembly inline-assembly att

我正在尝试使用 gcc/g++ 的内联 asm 指令(我不得不说我之前一直在 MSVC 上使用 Intel 语法,那就是一阵微风)。 我正在使用 double 值,并且以下 my_func2 似乎在执行后崩溃:

  #include <iostream>

  void my_func(const double *in, double *out) {
    asm("mov %0, %%r8" : : "r"(in));
    asm("movupd (%%r8), %%xmm0" :);
    asm("movupd (%%r8), %%xmm1" :);
    asm("addpd %%xmm1, %%xmm0" :);
    asm("movupd %%xmm0, (%0)" : : "r"(out) : "%r8", "%xmm0", "%xmm1");
  }

  double my_func2(const double *in) {
    double  ret = 0.0;

    asm("mov %0, %%r8" : : "r"(in));
    asm("movupd (%%r8), %%xmm0" :);
    asm("movupd (%%r8), %%xmm1" :);
    asm("addpd %%xmm1, %%xmm0" :);
    asm("movupd %%xmm0, %0" : "=m"(ret) : : "memory", "%r8", "%xmm0", "%xmm1");

    return ret;
 }

  int main(int argc, char *argv[]) {
    const double    a = 1.0;
    double      b = 0.0;
    my_func(&a, &b);
    std::cout << "b:" << b << std::endl;
    b = my_func2(&a);
    std::cout << "b:" << b << std::endl;
  }

我得到的错误是特别的(当我使用gdb运行时):

Program received signal SIGBUS, Bus error.
0x00000000004008e1 in main (argc=<error reading variable: Cannot access memory at address 0x400fffffffffffec>, 
    argv=<error reading variable: Cannot access memory at address 0x400fffffffffffe0>) at asm_test.cpp:28
28      b = my_func2(&a);

我做错了什么?在my_func2的最后一行中,我指定内存也被破坏了,我不明白...... 在哪里可以找到如何使用臭名昭著的 AT&T 语法的良好指南?
我使用以下代码进行编译:g++ -g -o asm_test asm_test.cppg++版本g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 在 Ubuntu Linux scv 3.2.0-48-generic#74-Ubuntu SMP 6 月 6 日星期四 19:43:26 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux 上。

我找到了http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.htmlhttp://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html ,您还有什么可以推荐的更多吗?

谢谢,
埃玛

最佳答案

这里的错误是使用movupd时必须小心。使用此指令,您实际上复制了 128 位内存,复制出。

偶然,第一个函数也可以复制这些值,但第二个函数在 ret 变量中仅获得 64 位空间。正如预期的那样,这会破坏堆栈,导致未定义的行为?
movlpd(或 movhpd)替换 movupd,事情就会变得魅力

我还在破坏正确的寄存器吗?

使用 g++ -O3 -o asm_test asm_test.cpp 编译时,以下代码可以正常工作

  void my_func(const double *in, double *out) {
    asm ("mov %0, %%r8" : : "r"(in));
    asm ("movhpd (%%r8), %%xmm0" :);
    asm ("movhpd (%%r8), %%xmm1" :);
    asm ("addpd %%xmm1, %%xmm0" :);
    asm ("movhpd %%xmm0, (%0)" : : "r"(out) : "memory", "%r8", "%xmm0", "%xmm1");
  }

  double my_func2(const double *in) {
    double  ret;

    asm("mov %0, %%r8" : : "r"(in));
    asm("movlpd (%%r8), %%xmm0" :);
    asm("movlpd (%%r8), %%xmm1" :);
    asm("addpd %%xmm1, %%xmm0" :);
    asm("movlpd %%xmm0, %0" : "=m"(ret) : : "memory", "%r8", "%xmm0", "%xmm1");

    return ret;
  }

关于c++ - 内联 gcc 汇编和局部变量( double ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17519577/

相关文章:

c++ - 应该问什么问题来测试面试候选人对 C++ 引用资料的了解?

c - 使用 GCC 强制从链接的静态库中导出特定的可见符号(同时排除其他符号)

c++ - Windows 10 不为发布可执行文件加载 DLL

c++ - boolean 循环和 switch 语句

c++ - gcc -funit-at-a-time 导致编译失败

java - 如何检查 Java 代码的汇编输出?

c - 获取可执行文件中的函数位置

assembly - x64 指令编码和 ModRM 字节

c++ - 给定一个从 0 到 n 的整数 vector ,但不是全部包含在内,我如何有效地获取未包含的整数?

c++ - 为什么 __builtin_popcount 比我自己的位计数函数慢?