吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1837|回复: 0
收起左侧

[其他转载] 浮点数

[复制链接]
a870861633 发表于 2019-12-19 20:46
#### X87(第一代)
vs系列需要选择使用x87
否则默认使用SSE2
![](index_files/de7c5918-eca6-4aad-a222-c455aaa18f2a.png)


FPU: 8个80位浮点寄存器(数据),16位状态寄存器,16位控制寄存器,16为标识寄存器。
     使用FPU指令对这些寄存器进行操作,这些寄存器构成一个循环栈,st7栈底,st0栈顶,
     当一个值被压入时,被存入st0,原来st0中的值被存入st7


![](index_files/d74874d3-ad5c-4eae-bc97-a27846591e23.png)


| 指令|含义 |例子|
|-------|------|------|
| fld | 将浮点值压入寄存器栈,源操作数可以是ST(i)或内存地址|fld b、fld st(1)|
| fld1 | 将浮点值1压入寄存器栈|fld1|
| fldz | 将浮点值0压入寄存器栈|fld0|
| fadd | 源操作数和目标操作数相加源操作数可以是内存地址或者FPU寄存器,目标操作数必须是FPU寄存器|fadd st(0),st(1)|
| faddp | ST(i)和ST(0)相加,计算结果存入ST(0)中|faddp st(1), st(0)|
| fstp | 拷贝ST(0)到ST(i)或内存位置,并且进行弹栈操作|fstp ret|




使用例子加法代码
```c
    float a = 3.14f;
    float b = 1.14f;
    int ret1;
    float ret2;
    __asm
    {
        //
        fld a
        fld b
        fld st(1)
        //fadd st(0),st(1)
        faddp st(1), st(0)
        //fistp  ret1
        fstp  ret2
    }
```




#### MMX(并行)


MMX: 将8个FPU寄存器重命名为8个64位MMX寄存器,即mm0到mm7。取消了栈结构。
     57条MMX指令,加快了整形浮点运算,但是对于复杂浮点运算无帮助




有符号饱和模式 127+1=127
无符号饱和模式 255+1=255
环绕模式      255+1=255




| 指令|含义 |例子|
|-------|------|------|
| movd | 复制MMX寄存器中的低位双字到一个通用寄存器或内存中,也可以把通用寄存器或内存中的数据复制到MMX寄存器的低位双字中|movd mm0,a movd b,mm0|
| movq | 把一个MMX寄存器的内容复制到另一个MMX寄存器中,这个指令也能被用来把一个内存区域中的内容复制到一个MMX寄存器中,或者把MMX寄存器中的内容复制到内存中|movq mm0,a movq b,mm0|
| paddb | 用mmx里面的一字节分别加|paddb mm0,mm1|
| paddsb | 有符号饱和模式、用mmx里面的一字节分别加|paddsb mm0,mm1|
| paddusb | 无符号饱和模式、用mmx里面的一字节分别加|paddusb mm0,mm1|


```c
  char ary1[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  char ary2[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  char ary3[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  __asm
  {
    movq  MM0, ary1
    movq  MM1, ary2
    paddb MM0, MM1   //环绕
    paddusb MM0, MM1 //饱和
    }
```
执行结构很容易看到是分别按字节并行加的 1+1=2 2+2=4 ....
![](index_files/f75f5b24-1d20-4a81-a617-66c54a4d95dd.png)




**C语言使用MMX指令**
+ 首先包上头文件#include <mmintrin.h> //MMX指令集
进头文件看指令都封装成函数了
![](index_files/911eedb7-20a7-489a-8b7c-b2b43c6b6916.png)
```c
void mmx_add(char *ary, int size)
{
  __m64 sum;
  sum.m64_i64 = 0x0101010101010101L;


  __m64 *p = (__m64 *)ary;
  for (int i = 0; i < size; i++)
    _m_paddb(p, sum);
}
```
#### 3DNOW
AMD才有的指令
被intel SSE所取代


#### SSE


8个128位寄存器(从xmm0到xmm7),MXSCR寄存器,EFLAGS寄存器,专有指令(复杂浮点运算)
并且 MMX是xmm的低64位


SSE的发展:
SSE SSE1  SSE2  SSE3 SSE4 SSE4.1 SSE4.2 SSE5.0(AVX)


SSE指令
  SSE: MOVSS ADDSS ADDSD  ADDPS  ADDPD


头文件:
    #include <xmmintrin.h>  //sse
    #include <emmintrin.h>  //sse2
    #include <pmmintrin.h>  //sse3








```c
float sse_add(float *ary, int size)
{
  __m128 sum = { 0.0f, 0.0f, 0.0f, 0.0f };
  __m128 *p = (__m128*)ary;
  for (int i = 0; i < size; i++)
    sum = _mm_add_ps(sum, p);


  return sum.m128_f32[0] + sum.m128_f32[1] + sum.m128_f32[2] + sum.m128_f32[3];
}
```
#### VAX(SSE 5.0)


//AVX: VMOVSS VADDSS
```c
#include <intrin.h>    //all
#include <immintrin.h>  //avx
```


```c
float avx_add(float *ary, int size)
{
  __m256 sum = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
  __m256 *p = (__m256*)ary;
  for (int i = 0; i < size; i++)
    sum = _mm256_add_ps(sum, p);


  return sum.m256_f32[0];
}


```

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-7 08:24

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表