这段简单的代码是我的问题:
扩展汇编 (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/