c++ - 内联汇编; float 的位运算;这里出了什么问题?

标签 c++ gcc assembly inline-assembly

这段简单的代码是我的问题:

扩展汇编 (gcc);英特尔语法(-masm=intel);平台 - x86

它应该做什么:返回一个长度为 1 且符号 (+-) 与 x 相同的 float 。

    float signf(float x)
    {
      float r = 1;
      asm volatile (
            "and %1,0x80000000;"
            "or %0,%1;"
            :"=r"(r):"r"(x));
      return r;
    }

用公平掷骰选择的任意随机数调用它会得到:

    signf of -1352353.3253: -5.60519e-045

最佳答案

你的内联 asm 的实际问题是你声明了 r仅作为输出,因此编译器将优化初始化。你应该使用 "+r"约束而不是 "=r"它应该有效。

更好的优化版本可能如下所示:

float signf(float x)
{
    float r;
    __asm__  __volatile__ (
            "and %0, 0x80000000;"
            "or %0, 0x3f800000;"
            :"=r"(r):"0"(x));
    return r;
}

注意该函数涉及float->int->float转换(通过内存),可能会影响性能。

上述代码的C版本是:

float signf(float x)
{
    union { float f; int i; } tmp, res;
    tmp.f = x;
    res.f = 1;
    res.i |= tmp.i & 0x80000000;
    return res.f;
}

这为我生成了相同的代码(使用 gcc 4.4.5)。

简单的 C 方法 return x < 0 ? -1 : 1;无需转换或内存访问(加载操作数除外)即可生成完整的 FPU 代码,因此性能可能更好。它还使用 fcmov如果可用以避免分支。需要一些基准测试。

关于c++ - 内联汇编; float 的位运算;这里出了什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14281114/

相关文章:

c++ - 为游戏优化 LAN 服务器

ubuntu - LPSolve、Python 和 Ubuntu?

c - 函数 localtime() 是如何使用的?

assembly - 为什么 Bochs 上的分页不起作用并且获取物理地址不可用错误

assembly - "mov (%ebx,%eax,4),%eax"是如何工作的?

assembly - arm64缓存可以从EL0刷新吗?

c++ - g++ 是否在函数模板重载方面表现不佳?

c++ - 另一个 : Passing Vector of Structs to Function - C++, MinGW

c++ - 如何在类中创建不可变的静态公共(public)对象?

c - 注入(inject)的 64 位 shellcode 不会执行系统调用