汇编中浮点栈寄存器st0~st7浮点计算fld压栈再计算的过程运行原理

您所在的位置:网站首页 控制寄存器与普通寄存器的区别 汇编中浮点栈寄存器st0~st7浮点计算fld压栈再计算的过程运行原理

汇编中浮点栈寄存器st0~st7浮点计算fld压栈再计算的过程运行原理

#汇编中浮点栈寄存器st0~st7浮点计算fld压栈再计算的过程运行原理| 来源: 网络整理| 查看: 265

目录 为什么浮点数不能用普通的数学指令计算结论 用普通的数学计算add无法实现浮点数加法.必须使用浮点数计算指令fadd来进行浮点数加法计算.fpu的概念浮点数计算需要先用fld指令压栈用fld 指令压入浮点栈fld指令 浮点栈 St0 到 St7 8个浮点栈寄存器fadd 浮点数加法浮点数计算完以后从寄存器中取出存入内存的出栈操作fst指令和fstp指令把所有上面的指令全部用起来的示例在od中的运行 之前一直有个疑惑,为什么浮点数要单独有一套计算法则,普通的加减乘除不行吗?经过1天在od中实战研究,终于明白了.

为什么浮点数不能用普通的数学指令计算

浮点数的加法是 fadd,普通的加法是add. add只能进行整数加法.计算机里的浮点数,并没有小数点,也是普通的01组合. 数学里十进制的5.5 在计算机里面没办法表示小数点,只能引入浮点数的计算规则.因为篇幅优先,这里不介绍了. 在内存中5.5的表示方法是:40 B0 00 00 . 数学中的2.0用浮点数表示是40 00 00 00.如果用add来相加 执行结果就是 40B00000 + 40000000 = 80B00000 80B00000 表示的浮点数并不是 5.5+2 = 7.5. 而是 00403010 -1.616305e-38. 这个结果是计算不对的. 下面代码来验证,使用add指令计算结果 403000地址里面存的是 5.5 403004地址里存的是2.0 分别存入eax和ebx以后相加,然后存入到eax中,再存入到403010地址中,如下:

mov eax,dword ptr ds:[403000] mov ebx,dword ptr ds:[403004] add eax,ebx mov dword ptr ds:[403010],eax

下图是查看od中的运行结果,发现执行add以后加法结果不是想要的浮点数,因为5.5+2.0=7.5 , 7.5在内存中是:40 F0 00 00,而不是80 B0 00 00 所以证明add无法进行正确的浮点数计算

在这里插入图片描述 把地址403010里面用32位浮点数表示为:-1.616305e-38

如下图中od截图: 在这里插入图片描述

结论 用普通的数学计算add无法实现浮点数加法.必须使用浮点数计算指令fadd来进行浮点数加法计算. fpu的概念

(float Point Unit)浮点运算单元 通过上面的汇编指令add已经发现,普通的数学计算add不能进行浮点数计算.在80486 cpu之前,计算机需要专门购买 fpu进行浮点数计算.但是在486以后,cpu有了专门的fpu,可以进行浮点数计算.跟普通的数学计算不同. fpu进行浮点数计算,要先把 数字压入到浮点栈.浮点栈.

浮点数计算需要先用fld指令压栈用fld 指令压入浮点栈 fld指令 fld相当于push,作用是把数据压入到浮点栈寄存器st0中,因为st0是浮点栈的栈顶,所以每次fld压栈,都是压入到st0中,然后之前st0寄存器的内容会向下移动到st1中.st1中的内容进入st2中…一直到st6的内容进入到st7中.st7之前的内容消失,被st6覆盖格式: fld 操作数例如下面代码把地址403004的内容压入到浮点寄存器st0: fld dword ptr ds:[403004] 浮点栈 St0 到 St7 8个浮点栈寄存器 st0 ,st1,st2,st3,st4,st5,st6,st7总共8个寄存器每个寄存器的宽度大小事80个二进制位.可以放进去双精度浮点数,因为双精度浮点数是64位,80-64 = 16,其他16位用来干别的.

浮点计算跟普通的数学计算指令不一样,例如普通的加法add,可以用寄存器和立即数机型加法.但是浮点数计算必须是先把浮点数压入到浮点栈中, fadd 加法只能把 浮点栈寄存器当做操作数.

fadd 浮点数加法

本来浮点数计算有加减乘除等,但是为了讲清楚浮点计算运行过程,这里只讲解加法.其他的运行原理也一样 格式 fadd 浮点寄存器1 ,浮点寄存器2 例如 fadd st0,st1. 执行的过程是把st0和st1相加,然后存入到左边的寄存器,这里左边是st0,所以加法结果存入到st0

例如:下面代码, 把5.5和2.0压入浮点栈,然后相加,再存入到st0中

mov dword ptr ds:[403000],40B00000 //40B00000是浮点数5.5 mov dword ptr ds:[403004],40000000 //40000000是浮点数2.0 fld dword ptr ds:[403004] //把2.0压入st0 fld dword ptr ds:[403000] //把5.5压入st0, 2.0被移动到st1 fadd st0,st1

注意: fadd 2个操作数必须都是浮点栈寄存器,不能是立即数,或者是内存中的数据,例如下面代码,右边的操作数,是[403004] 数据段中的值,这个语法错误,不能执行 fadd st,dword prt ds:[403004]

浮点数计算完以后从寄存器中取出存入内存的出栈操作 fst指令和fstp指令 这2个指令的作用都是从浮点栈的栈顶st0取出数据存入到内存中.区别: – fst取出栈顶的数据后,栈顶不变化. – fstp取出栈顶的数据后,栈顶出栈,其他st1~st7寄存器向栈顶移动.相当于pop指令出栈 把所有上面的指令全部用起来的示例在od中的运行

其中add是为了验证 add正确计算浮点数

mov dword ptr ds:[403000],40B00000 //把5.5写入内存 mov dword ptr ds:[403004],40000000 //把2.0写入内存 fld dword ptr ds:[403004] //2.0压入浮点栈 fld dword ptr ds:[403000] //5.5压入浮点栈 fadd st0,st1 //浮点栈中st0 + st1 ,5.5+ 2.0 ,然后存入st0 fstp dword ptr ds:[403010] //把st0计算结果7.5出栈,然后存入内存[403010]中 mov dword ptr ds:[403010],0 //把 内存清零 mov eax,dword ptr ds:[403000] //把浮点数5.5压入寄存器eax mov ebx,dword ptr ds:[403004] //把浮点数2.0压入 ebx add eax,ebx //让eax和ebx相加得到错误的浮点数计算结果,因为add会把操作数看做整形计算 004010FC A3 10304000 mov dword ptr ds:[403010],eax //把得到的计算结果 存入到内存中

下图gif中显示了od中执行代码每一部的过程,可以看到每次执行fld以后,都会在右边的浮点栈中进行push压栈操作.每次压入都是到栈顶st0,之前的st0,向下移动到st1 执行fadd st,st(1)的时候,是把st0和st1进行相加,然后存入到st0 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3