首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >浮点数比较技巧:内联程序集

浮点数比较技巧:内联程序集
EN

Stack Overflow用户
提问于 2014-03-09 07:38:24
回答 1查看 1.5K关注 0票数 1

很久以前,我使用这个简单的x86汇编程序技巧来获得0或1,这是浮点数比较的结果:

代码语言:javascript
复制
fld [value1]
fcom [value2]
fnstsw ax
mov al, ah
and eax, 1

如果比较结果仅影响从2组值中选择一个值,则此技巧允许避免分支。它在奔腾时代很快,现在它可能没有那么快,但谁知道。

现在我主要使用C++,使用Intel C++编译器或GCC C++编译器进行编译。

谁能帮我把这段代码改写成2个内置的汇编器版本(英特尔和GCC)?

所需的函数原型是:内联int compareDoublesIndexed( const double value1,const double value2 ){.}

也许使用SSE2操作更有效率。你的观点?

我试过这个:

代码语言:javascript
复制
__asm__(
    "fcomq %2, %0\n"
    "fnstsw %ax\n"
    "fsubq %2, %0\n"
    "andq $L80, %eax\n"
    "shrq $5, %eax\n"
    "fmulq (%3,%eax), %0\n"
    : "=f" (penv)
    : "0" (penv), "F" (env), "r" (c)
    : "eax" );

但是我在Intel C++编译器中得到了错误:浮点输出约束必须指定一个寄存器。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-09 13:17:56

正如你提到的,奔腾时代以来的情况发生了变化:

  • 现在SSE是浮点(而不是x87 )的首选指令集,甚至对于标量操作也是如此。
  • 优化编译器现在非常好。

因此,首先检查编译器生成了什么,您可能会感到惊喜。我在下面的代码中尝试了g++和-O3

fcmp.cpp:

代码语言:javascript
复制
int compareDoublesIndexed( const double value1, const double value2 ) {
    return value1 < value2 ? 1 : 0;
}

这就是编译器生成的内容。

代码语言:javascript
复制
0000000000400690 <_Z21compareDoublesIndexeddd>:
  400690:       31 c0                   xor    %eax,%eax
  400692:       66 0f 2e c8             ucomisd %xmm0,%xmm1
  400696:       0f 97 c0                seta   %al
  400699:       c3                      retq   

这就是它的意思

代码语言:javascript
复制
  xor     %eax,%eax        ; EAX = 0
  ucomisd %xmm0,%xmm1      ; compare value2 (in %xmm1) with value1 (in %xmm0)
  seta    %al              ; AL = value2 > value1 ? 1 : 0

因此,编译器通过使用seta指令避免了条件分支(如果结果在上面,则将字节设置为'1‘,否则设置为'0’)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22279619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档