【问题标题】:Loading double to FPU with GCC (Inline assembler)使用 GCC(内联汇编器)将 double 加载到 FPU
【发布时间】:2012-06-22 23:25:27
【问题描述】:

我一直在尝试使用 GCC 内联汇编将 double 加载到带有 FLD 的 FPU。

由于不太熟悉 AT&T 语法,也没有在网络上找到任何内容,因此非常感谢您的帮助。 我的意图是将a的地址加载到EAX,然后执行FLD [EAX]...

double atl(double a, int adr) {
    __asm ("movl ptr %0,%%eax"::"r"(a));
    __asm ("fld qword (%eax)");
    //.... some other code here
    __asm("movl ptr %0,%%eax"::"r"(a));
    __asm("fst qword (%eax)");
    return a;
}

【问题讨论】:

  • 请注意,如果您不使用asm volatile,则允许编译器在不考虑任何语义的情况下重新排序装配线。
  • 谢谢,我没想到。现在 asm 代码似乎并不能正常工作,您有什么建议吗? gcc 表示第一行和最后一行的操作数无效。
  • 您也不应该假设寄存器内容从一个asm 保留到另一个。如果您有一系列必须一起运行的指令,请创建一个 asm,并将它们全部包含在内。

标签: gcc assembly double gnu-assembler fpu


【解决方案1】:

最简单的方法是使用constraint "m",从内存位置加载/保存:

#include <stdio.h>
int main (void) {
    double a = 0.78539816339744;
    asm ("fldl %0;"
         "fsin;"
         "fstpl %0" : "+m"(a));
    printf("sin(45°) = %f\n", a);
    return 0;
}

modifier "+" 告诉编译器您希望在该内存位置输入输入并输出到同一位置。

GCC 可以对你的行重新排序,但它会知道该行的语义,并会进行相应的优化。

一个更困难的例子,使用从其他变量加载而不是写入:

#include <stdio.h>
int main (void) {
    double sin_a, cos_a, a = 0.5;
    asm ("fldl %2;"
         "fsincos;"
         "fstpl %1;"
         "fstpl %0;" : "=m"(sin_a), "=m"(cos_a) : "m"(a));
    printf("sin(29°) = %f, cos(29°) = %f\n", sin_a, cos_a);
    return 0;
}

现场演示:http://ideone.com/SuvpM

PS:不过,我无法让 GCC 加载 double 值,所以我不知道我的回答是否对您有用。 :-(

更新:

知道了:您需要附加 s(对于单 [32 位],如 flds,浮点加载单)、l(对于双 [64 位])或 t (对于 long double [80 bits])明确。我的 GCC 4.6.3 假定每个内存操作数都有一个值……

【讨论】:

  • 哇,非常感谢!现在一些加载双精度对我来说是如何工作的,至少我没有收到任何错误,并且该值可以在后续的汇编代码中使用。
  • @MarcelL 我解决了双重加载/存储问题。查看我的更新。
  • 这里可能缺少"t" clobber 约束?
猜你喜欢
  • 2012-10-20
  • 2019-05-11
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-07
  • 1970-01-01
相关资源
最近更新 更多