如何使用内联汇编指定直接浮点数?

当我尝试编译此代码时:

#include  main(int argc, char *argv[]) { double y = 0; __asm__ ("fldl $150;" "fsqrt;" "fstl %0;" : : "g" (y) ); printf("%f\n", y); return 0; } 

我收到此错误:

 sqrt.c: Assembler messages: sqrt.c:6: Error: suffix or operands invalid for `fld' 

为什么这不起作用? 为什么我不能将数字“150”推入堆栈进行浮点运算?

我不知道支持立即使用的文字浮点常量的汇编语言。 通常的方法是声明包含浮点常量的初始化存储并引用它:

 const1: dq 1.2345 ... fldl const1 

对于您提供的示例,可以更直接地执行此操作:

 printf ("%f\n", sqrt (150)); 

否则,这必须是一个人为复杂的项目,也许是家庭作业。

尝试这样的事情

 push $0x???????? push $0x???????? fldl (%esp) addl $8,%esp 

其中???????被替换为双常数的IEEE表示。 该方法的优点在于它在正常和位置无关(PIC,即共享库)代码中同样有效。

fld指令的唯一有效操作数是存储器或浮点堆栈寄存器。

(另外,你已经指定了y作为asm块的输入操作数,而它应该是一个输出。可能更安全地将其限制为内存( "m" ,而不是"g" )。)

如果你真的想用内联汇编这样做:

 #include  int main(void) { double y; const double k = 150.0; __asm__ ("fldl %1;" "fsqrt;" "fstl %0;" : "=m" (y) : "m" (k) ); printf("%f\n", y); return 0; } 

aarch64支持它

 #include  #include  int main(void) { register double d0 __asm__ ("d0"); __asm__ ("fmov d0, #1.5" : : : "%d0"); assert(d0 == 1.5); __asm__ ( "fmov d1, #2.5;" "fadd d0, d0, d1" : : : "%d0", "%d1"); assert(d0 == 4.0); } 

编译并运行:

 aarch64-linux-gnu-gcc -static -std=gnu99 reg_var_float.c qemu-aarch64 ./a.out 

它永远不会让我开心,GNU GAS如何为每个拱门提供微妙的不同语法。

在Ubuntu 18.04上测试过。 GitHub上游 。

通过让PHP为您预处理文字,您可以绕过许多拒绝支持浮点文字的汇编程序。 (rawSingleHex取自此处 )。 在完美的世界中,C预处理器就足够了,但目前还不是这样。

  #include  int main(int argc, char **argv) { float y = 0; __asm__ ("pushl $\n" "fsqrt\n" "fstl %0\n" : : "g" (y)); printf("%f\n", y); return 0; } 

运行php生成c文件,并运行c编译器来编译你的程序:P