【问题标题】:returning a double in the floating stack using __asm in Visual Studio在 Visual Studio 中使用 __asm 在浮动堆栈中返回双精度
【发布时间】:2012-01-27 20:19:44
【问题描述】:

我正在使用 MS Visual Studio(2005,但这应该不重要)。 我有一个函数,它的主体(必须)在内联汇编中实现:

double f(double x)
{
    __asm{ ...body code... }
}

汇编代码以包含在 ST0 中的返回结果结束。 使用的调用约定是 __cdecl,因此约定是在 ST0 中返回一个返回双精度值。因此,在 __asm{...body code...} 代码完成后,该函数已准备好让其返回的堆栈清理代码运行并返回。但是,上面的代码当然不会编译,因为没有“return dblVal;”陈述。可以通过将代码更改为:

double f(double x)
{
    double dRet;
    __asm{ ...body code... }
    __asm{ fst dRet }
    return dRet;
}

但这有两个缺点: (1) 存储到 dRet 之后立即是 fld dRet,这完全是浪费和不必要的(这在 monte-carlo 例程中被无数次使用,所以每个循环都很重要) (2) 更重要的是,ST0 中的值已经在 body 中仔细计算到 64 位尾数精度,我需要保留,fst 后跟 fld 完全杀死了这个。

如何告诉 VisualStudio 编译器要返回的双精度值已经在 ST0 中? 我可以明确地编写退出代码:

double f(double x)
{
    __asm{ ...body code... }
    __asm{ __asm leave
           __asm ret
         }
    return 0.0; //dummy code that is never executed, to make the compiler happy
}

但是必须知道编译器生成的入口代码(事实上,上面的退出代码是错误的)。所以我们可以更进一步,编写入口代码和退出代码:

__declspec ( naked ) double f(double x)
{
    __asm{ ...entry code...}
    __asm{ ...body code... }
    __asm{ ...exit code... }
    return 0.0; //dummy code that is never executed, to make the compiler happy
}

但这一切都非常丑陋。那么,如何让编译器去处理入口代码和出口代码,并告诉它返回值已经在 ST0 中呢?

【问题讨论】:

  • 你为什么要声明一个函数,然后将内部全部放入内联汇编中?为什么不完全跳过 C 声明,只让函数存在于实际汇编中,而不是 C 文件中的内联汇编?
  • 可维护性:它是一个非常大的应用程序的一部分,我只是没有时间实际集成。
  • 但你是对的,最好只使用适当的组装。我只是没有时间做所有的工作(主要是学习),这会给其他开发人员增加更多的困惑,他们已经在担心汇编指令的情况下运行,更不用说为汇编程序创建一个模块了(和将程序集设置到项目中等)

标签: c++ visual-c++ return-value inline-assembly calling-convention


【解决方案1】:

实际上,我的问题的答案是,我在上面问题的陈述中对一件事有误:

double f(double x)
{
    __asm{ ...body code... }
}

没有任何 return 语句,在正文中使用 __asm 语句,编译得很好,没有任何错误或警告。编译器(正确地)假设我已安排适当地传递/返回返回值。编译器正确地生成进入和退出代码,并且很高兴将其余的留给我。去想 - 为什么我认为我已经测试过并发现编译错误?叹。打扰大家了。

【讨论】:

    【解决方案2】:

    你唯一的选择是裸函数,但是它们不需要 C 的 return 语句,也不需要你做堆栈帧。但是,除非您有充分的理由使用 asm,否则您最好在 C 中使用它,原因有很多,主要是可移植性,另一个是针对特定目标的优化,例如 SIMD。

    【讨论】:

    • 我确实有充分的理由使用汇编:我需要以 80 位精度完成一系列计算,并且需要非常快地完成。 SIMD 绝对不是我们需要的——我们需要更高的精度,而不是更低的精度。
    猜你喜欢
    • 1970-01-01
    • 2019-04-30
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-06
    相关资源
    最近更新 更多