当我尝试编译此代码时:
#include <stdio.h>
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”推入堆栈进行浮点运算?
答案 0 :(得分:9)
我不知道支持立即使用的文字浮点常量的汇编语言。通常的方法是声明包含浮点常量的初始化存储并引用它:
const1: dq 1.2345
...
fldl const1
对于您提供的示例,可以更直接地执行此操作:
printf ("%f\n", sqrt (150));
否则,这必须是一个人为的复杂项目,也许是家庭作业。
答案 1 :(得分:5)
尝试这样的事情
push $0x????????
push $0x????????
fldl (%esp)
addl $8,%esp
其中???????被替换为双常数的IEEE表示。这种方法的优点是它在正常和位置无关(PIC,即共享库)代码中同样有效。
答案 2 :(得分:1)
fld
指令的唯一有效操作数是内存或浮点堆栈寄存器。
(另外,您已将y
指定为asm
块的输入操作数,而它应该是输出。可能更安全地将其限制为内存("m"
,而不是也是"g"
)。)
如果你真的想用内联汇编来做这件事:
#include <stdio.h>
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;
}
答案 3 :(得分:1)
GNU GAS ARM程序集支持
例如在ARMv8中:
main.c
#include <assert.h>
int main(void) {
float my_float = 1.5;
__asm__ (
"fmov s0, 1.0;"
"fadd %s[my_float], %s[my_float], s0;"
: [my_float] "+w" (my_float)
:
: "s0"
);
assert(my_float == 2.5);
}
编译并运行:
aarch64-linux-gnu-gcc -o main.out -static -std=gnu99 main.c
qemu-aarch64 ./main.out
ARMv8 floating point output inline assembly
中提到了%s
修饰符
它在ARMv7上也可以使用。
但是,由于某种原因,它仅适用于浮点指令,例如fmov
,例如以下ARMv7尝试组装失败:
mov r0, 1.5
有错误:
Error: garbage following instruction -- `mov r0,1.5'
大概是因为它使用了mov
指令,该指令作用于通用寄存器而不是浮点寄存器。
但是,这也许无关紧要,因为在大多数情况下,您只想在浮点寄存器上执行浮点运算,然后先执行fcmp
,然后执行vmrs
,如下所示:
vmov s0, 1.5
vmov s1, 2.5
fadds s2, s0, s1
vmov s3, 4.0
/* Compare two floating point registers. Stores results in fpscr:
* (floating point status and control register).
*/
vcmp.f32 s2, s3
/* Move the nzcv bits from fpscr to apsr */
vmrs apsr_nzcv, fpscr
/* This branch uses the Z bit of apsr, which was set accordingly. */
beq theyre_equal
GNU GAS对每个拱门的语法都有细微的不同,这让我永不过时!
但是我找不到十六进制浮点文字语法:How to use hexadecimal floating point literals in GNU GAS?
在Ubuntu 18.04上测试。
答案 4 :(得分:-1)
通过让PHP为您预处理文字,您可以绕过许多拒绝支持浮点文字的汇编程序。 (rawSingleHex取自here)。在完美的世界中,C预处理器就足够了,但目前还不是这样。
<?php
function rawSingleHex($num) {
return '0x' . strrev(unpack('h*', pack('f', $num))[1]);
}
?>
#include <stdio.h>
int main(int argc, char **argv) {
float y = 0;
__asm__ ("pushl $<?php echo rawSingleHex(150);?>\n"
"fsqrt\n"
"fstl %0\n" : : "g" (y));
printf("%f\n", y);
return 0;
}
运行php生成c文件,并运行c编译器来编译你的程序:P