【发布时间】: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