第59部分- Linux x86 64位汇编内联汇编使用浮点值

第59部分- Linux x86 64位汇编内联汇编使用浮点值

FPU堆栈方式使用寄存器在内联汇编中有一点区别。

内联汇编中:

  • f引用任何可用的浮点寄存器
  • t引用顶部的浮点寄存器
  • u引用第二个浮点寄存器

在获取输出值的时候不能使用约束f,必须声明约束t或者u来指定输出值所在的fpu寄存器。

示例

#include <stdio.h>

int main()
{
   float angle = 90;
   float radian, cosine, sine;

   radian = angle / 180 * 3.14159;

   asm("fsincos";//求解sin和cos值,此时st0是radian值,结果存放于st0和st1
       :"=t"(cosine), "=u"(sine);//输出是st0和st1
       :"0"(radian));

   printf("The cosine is %f, and the sine is %f\n", cosine, sine);
   return 0;
}

gcc -o sincostest sincostest.c

反汇编:

gcc -o sincostest.s -S sincostest.c

有代码片段:

        flds    -20(%rbp)

#APP

# 11 "sincostest.c" 1

        fsincos

# 0 "" 2

#NO_APP

        fxch    %st(1)

        fstps   -20(%rbp)

        fstps   -8(%rbp)

先使用了flds加载,最后将st0和st1都通过fstps进行了弹出操作。保持了fpu寄存器的干净。

 

示例二

如果FPU堆栈执行的操作没有被清除,就必须在改动的寄存器列表中指定适当的FPU寄存。

#include <stdio.h>

int main()
{
   int radius = 10;
   float area;

   asm("fild %1\n\t"
       "fimul %1\n\t"
       "fldpi\n\t"
       "fmul %%st(1), %%st(0)"
       : "=t"(area)
       :"m"(radius)
       : "%st(1)");

   printf("The result is %f\n", area);
   return 0;
}

gcc -o areatest areatest.c

把半径值放在一个内存radius位置中,通过fild加载radius中到st0中。

然后将内存radius位置和st0相乘,存在st0中。加载π到st0中,原半径相乘值移动到st1中。将st0和st1相乘。将st0结果复制给area变量。这里我们看到st0作为了输出寄存器使用,但是st1没有在输入和输出中标记出来,所以需要在改动的寄存器列表中列出它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值