我正在尝试转换这段代码,以便与g ++使用的AT&T程序集一起工作:
double sqrt13(double n)
{
__asm{
fld n
fsqrt
}
}
基于此链接:https://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html: 我尝试过:
double raiz (double n)
__asm__ ( "fld n\n\t"
"fsqrt\n\t" );
但我一直收到:
/tmp/cc2AQhHj.s|662|Error: junk `n' after expression|
同一错误消息在此文件的其他行中发生了四次以上
我下载了一个名为“ intel2gas”的程序,他对我说代码应该是这样的:
__asm__ volatile__ (
"fld %0\n"
"fsqrt\n"
:"=m"(n)
:
:"memory", "esi", "edi", "eax", "ebx", "ecx", "edx"
);
将其放入函数中并尝试运行它,我收到:
|39|error: expected ‘(’ before ‘volatile__’|
|42|error: expected ‘)’ before ‘:’ token|
|45|error: ‘volatile__’ was not declared in this scope|
加一个 | 46 |警告:函数中没有return语句,返回non-void |
那么,有什么建议吗?
答案 0 :(得分:4)
intel2gas
显然没有实现MSVC的支持,即在asm中的EAX(或ST0)中保留返回值,然后退出非void
函数的末尾。即使内联包含__asm
块的函数,MSVC仍将其视为实际返回值。在GNU C内联汇编中,仅当您使用输出或读/写约束时,寄存器值才是输出。
这就是为什么您得到warning: no return statement in function returning non-void
并破坏代码的原因。
正如@MichaelPetch指出的那样,您应该使用t
约束(x87堆栈的顶部)向编译器询问x87 FP寄存器堆栈上的输入浮点数。
double raiz (double n) {
__asm__ ("fsqrt"
: "+t"(n) // read-write operand: top of x87 stack
);
return n;
}
不需要 asm volatile
:即使没有使用输出,asm块也不需要运行任何副作用,并且输出是输入的纯函数。 (除非您要更改x87的舍入模式或精度)。
最好让编译器对其进行优化,或者在多次运行之间进行CSE。
作为独立功能,它将(on Godbolt)编译为
# gcc8.2 -O3 -ffast-math -m32 uses x87 by default, not SSE2
_Z4raizd:
fld QWORD PTR [esp+4]
# start of inline asm
fsqrt
# end of inline asm.
ret