汇编FPU浮点运算解析.docx

上传人:b****6 文档编号:6165209 上传时间:2023-01-04 格式:DOCX 页数:11 大小:19.30KB
下载 相关 举报
汇编FPU浮点运算解析.docx_第1页
第1页 / 共11页
汇编FPU浮点运算解析.docx_第2页
第2页 / 共11页
汇编FPU浮点运算解析.docx_第3页
第3页 / 共11页
汇编FPU浮点运算解析.docx_第4页
第4页 / 共11页
汇编FPU浮点运算解析.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

汇编FPU浮点运算解析.docx

《汇编FPU浮点运算解析.docx》由会员分享,可在线阅读,更多相关《汇编FPU浮点运算解析.docx(11页珍藏版)》请在冰豆网上搜索。

汇编FPU浮点运算解析.docx

汇编FPU浮点运算解析

浮点执行环境的寄存器主要是8个通用数据寄存器和几个专用寄存器,它们是状态寄存器、控制寄存器、标记寄存器等

8个浮点数据寄存器(FPUDataRegister),编号FPR0~FPR7。

每个浮点寄存器都是80位的,以扩展精度格式存储数据。

当其他类型数据压入数据寄存器时,PFU自动转换成扩展精度;相反,数据寄存器的数据取出时,系统也会自动转换成要求的数据类型。

     8个浮点数据寄存器组成首尾相接的堆栈,当前栈顶ST(0)指向的FPRx由状态寄存器中TOP字段指明。

数据寄存器不采用随机存取,而是按照“后进先出”的堆栈原则工作,并且首尾循环。

向数据寄存器传送(Load)数据时就是入栈,堆栈指针TOP先减1,再将数据压入栈顶寄存器;从数据寄存器取出(Store)数据时就是出栈,先将栈顶寄存器数据弹出,再修改堆栈指针使TOP加1。

浮点寄存器栈还有首尾循环相连的特点。

例如,若当前栈顶TOP=0(即ST(0)=PFR0),那么,入栈操作后就使TOP=7(即使ST(0)=PFR7),数据被压入PFR7。

所以,浮点数据寄存器常常被称为浮点数据栈。

     为了表明浮点数据寄存器中数据的性质,对应每个FPR寄存器,都有一个2位的标记(Tag)位,这8个标记tag0~tag7组成一个16位的标记寄存器。

 在计算机中,实数的浮点格式(Floating-PointFormat)所示,分成指数、有效数字和符号位三个部分。

· 符号(Sign)——表示数据的正负,在最高有效位(MSB)。

负数的符号位为1,正数的符号为0。

· 指数(Exponent)——也被称为阶码,表示数据以2为底的幂。

指数采用偏移码(BiasedExponent)表示,恒为整数。

· 有效数字(Significand)——表示数据的有效数字,反映数据的精度。

有效数字一般采用规格化(Normalized)形式,是一个纯小数,所以也被称为尾数(Mantissa)、小数或分数(Fraction)。

     80x87支持三种浮点数据类型:

单精度、双精度和扩展精度;它们的长度依次为32、64和80位,即4、8和10个字节;它们遵循美国IEEE(电子电气工程师协会)定义的国际标准浮点格式。

· 单精度浮点数(32位短实数)——由1位符号、8位指数、23位有效数组成。

· 双精度浮点数(64位长实数)——由1位符号、11位指数、52位有效数组成。

· 扩展精度浮点数(80位临时实数)——由1位符号、15位指数、64位有效数组成。

很多计算机中并没有80位扩展精度这种数据类型,80x87FPU主要在内部使用它存贮中间结果,以保证最终数值的精度。

浮点处理单元FPU具有自己的指令系统,共有几十种浮点指令,可以分成传送、算术运算、超越函数、比较、FPU控制等类。

浮点指令归属于ESC指令,其前5位的操作码都是11011b,它的指令助记符均以F开头。

1.浮点传送类指令

   浮点数据传送指令完成主存与栈顶st(0)、数据寄存器st(i)与栈顶之间的浮点格式数据的传送。

浮点数据寄存器是一个首尾相接的堆栈,所以它的数据传送实际上是对堆栈的操作,有些要改变堆栈指针TOP,即修改当前栈顶。

2.算术运算类指令

   这类浮点指令实现浮点数、16/32位整数的加、减、乘、除运算,它们支持的寻址方式相同。

这组指令还包括有关算术运算的指令,例如求绝对值、取整等。

3.超越函数类指令

   浮点指令集中包含有进行三角函数、指数和对数运算的指令。

4.浮点比较类指令

   浮点比较指令比较栈顶数据与指定的源操作数,比较结果通过浮点状态寄存器反映。

5.FPU控制类指令

   FPU控制类指令用于控制和检测浮点处理单元FPU的状态及操作方式。

采用浮点指令的汇编语言程序格式,与整数指令源程序格式是类似的,但有以下几点需要注意:

· 使用FPU选择伪指令

     由于汇编程序MASM默认只识别8086指令,所以要加上.8087/.287/.387等伪指令选择汇编浮点指令;有时,还要加上相应的.238/.386等伪指令。

· 定义浮点数据

     我们知道,数据定义伪指令dd(dword)/dq(qword)/dt(tbyte)依次说明32/64/80位数据;它们可以用于定义单精度、双精度和扩展精度浮点数。

为了区别于整数定义,MASM6.11建议采用REAL4、REAL8、REAL10定义单、双、扩展精度浮点数,但不能出现纯整数(其实,整数后面补个小数点就可以了)。

相应的数据属性依次是dword、qword、tbyte。

另外,实常数可以用E表示10的幂。

· 初始化浮点处理单元

     每当执行一个新的浮点程序时,第一条指令都应该是初始化FPU的指令finit。

该指令清除浮点数据寄存器栈和异常,为程序提供一个“干净”的初始状态。

否则,遗留在浮点寄存器栈中的数据可能会产生堆栈溢出。

另一方面,浮点指令程序段结束,也最好清空浮点数据寄存器。

浮点传送程序

 

          .modelsmall

          .8087                ;识别浮点指令

          .stack

          .data

f32d      dd100.25            ;单精度浮点数:

42C88000h

f64d      dq-0.2109375        ;双精度浮点数:

BFCB000000000000h

f80d      dt100.25e9          ;扩展精度浮点数:

4023BABAECD400000000h

i16d      dw100               ;字整数:

0064h

i32d      dd-1234             ;短整数:

FFFFFB2Eh

i64d      dq123456h           ;长整数:

0000000000123456h

b80d      dt123456h           ;BCD码数:

00000000000000123456h

ib32      dd?

bi80      dt?

          .code

          .startup

start1:

   finit                ;初始化FPU

          fldf32d             ;压入单精度浮点数f32d

          fldf64d             ;压入双精度浮点数f64d

          fldf80d             ;压入扩展精度浮点数f80d

          fldst

(1)            ;压入当前st

(1),即f64d

          fildi16d            ;压入字整数i16d

          fildi32d            ;压入短整数i32d

          fildi64d            ;压入长整数i64d

          fbldb80d            ;压入BCD码数b80d

start2:

   fistdwordptrib32  ;将栈顶(现为b80d)以短整数保存

          fxch                 ;st(0)与st

(1)互换,现栈顶为i64d

          fbstptbyteptrbi80 ;将栈顶弹出成BCD码数

start3:

   .exit0

          end

 对下面的指令先做一些说明:

st(i):

代表浮点寄存器,所说的出栈、入栈操作都是对st(i)的影响

src,dst,dest,op等都是指指令的操作数,src表示源操作数,dst/dest表示目的操作数

mem8,mem16,mem32,mem64,mem80等表示是内存操作数,后面的数值表示该操作数的内存位数(8位为一字节)

x<-y表示将y的值放入x,例st(0)<-st(0)-st

(1)表示将st(0)-st

(1)的值放入浮点寄存器st(0)

1.数据传递和对常量的操作指令

指令格式

指令含义

执行的操作

FLDsrc

装入实数到st(0)

st(0)<-src(mem32/mem64/mem80)

FILDsrc

装入整数到st(0)

st(0)<-src(mem16/mem32/mem64)

FBLDsrc

装入BCD数到st(0)

st(0)<-src(mem80)

FLDZ

将0.0装入st(0)

st(0)<-0.0

FLD1

将1.0装入st(0)

st(0)<-1.0

FLDPI

将pi装入st(0)

st(0)<-?

(ie,pi)

FLDL2T

将log2(10)装入st(0)

st(0)<-log2(10)

FLDL2E

将log2(e)装入st(0)

st(0)<-log2(e)

FLDLG2

将log10

(2)装入st(0)

st(0)<-log10

(2)

FLDLN2

将loge

(2)装入st(0)

st(0)<-loge

(2)

FSTdest

保存实数st(0)到dest

dest<-st(0)(mem32/mem64)

FSTPdest

dest<-st(0)(mem32/mem64/mem80);然后再执行一次出栈操作

FISTdest

将st(0)以整数保存到dest

dest<-st(0)(mem32/mem64)

FISTPdest

dest<-st(0)(mem16/mem32/mem64);然后再执行一次出栈操作

FBSTdest

将st(0)以BCD保存到dest

dest<-st(0)(mem80)

FBSTPdest

dest<-st(0)(mem80);然后再执行一次出栈操作2.比较指令

指令格式

指令含义

执行的操作

FCOM

实数比较

将标志位设置为st(0)-st

(1)的结果标志位

FCOMop

实数比较

将标志位设置为st(0)-op(mem32/mem64)的结果标志位

FICOMop

和整数比较

将Flags值设置为st(0)-op的结果op(mem16/mem32)

FICOMPop

和整数比较

将st(0)和op比较op(mem16/mem32)后;再执行一次出栈操作

FTST

零检测

将st(0)和0.0比较

FUCOMst(i)

比较st(0)和st(i)[486]

FUCOMPst(i)

比较st(0)和st(i),并且执行一次出栈操作

FUCOMPPst(i)

比较st(0)和st(i),并且执行两次出栈操作

FXAM

Examine:

Eyeballst(0)(setconditioncodes)3.运算指令

指令格式

指令含义

执行的操作

加法

FADD

加实数

st(0)<-st(0)+st

(1)

FADDsrc

st(0)<-st(0)+src(mem32/mem64)

FADDst(i),st

st(i)<-st(i)+st(0)

FADDPst(i),st

st(i)<-st(i)+st(0);然后执行一次出栈操作

FIADDsrc

加上一个整数

st(0)<-st(0)+src(mem16/mem32)

减法

FSUB

减去一个实数

st(0)<-st(0)-st

(1)

FSUBsrc

st(0)<-st(0)-src(reg/mem)

FSUBst(i),st

st(i)<-st(i)-st(0)

FSUBPst(i),st

st(i)<-st(i)-st(0),然后执行一次出栈操作

FSUBRst(i),st

用一个实数来减

st(0)<-st(i)-st(0)

FSUBRPst(i),st

st(0)<-st(i)-st(0),然后执行一次出栈操作

FISUBsrc

减去一个整数

st(0)<-st(0)-src(mem16/mem32)

FISUBRsrc

用一个整数来减

st(0)<-src-st(0)(mem16/mem32)

乘法

FMUL

乘上一个实数

st(0)<-st(0)*st

(1)

FMULst(i)

st(0)<-st(0)*st(i)

FMULst(i),st

st(i)<-st(0)*st(i)

FMULPst(i),st

st(i)<-st(0)*st(i),然后执行一次出栈操作

FIMULsrc

乘上一个整数

st(0)<-st(0)*src(mem16/mem32)

除法

FDIV

除以一个实数

st(0)<-st(0)/st

(1)

FDIVst(i)

st(0)<-st(0)/t(i)

FDIVst(i),st

st(i)<-st(0)/st(i)

FDIVPst(i),st

st(i)<-st(0)/st(i),然后执行一次出栈操作

FIDIVsrc

除以一个整数

st(0)<-st(0)/src(mem16/mem32)

FDIVRst(i),st

用实数除

st(0)<-st(i)/st(0)

FDIVRPst(i),st

FDIVRPst(i),st

FIDIVRsrc

用整数除

st(0)<-src/st(0)(mem16/mem32)

FSQRT

平方根

st(0)<-sqrtst(0)

FSCALE

2的st(0)次方

st(0)<-2^st(0)

FXTRACT

Extractexponent:

st(0)<-exponentofst(0);andgetspushed

st(0)<-significandofst(0)

FPREM

取余数

st(0)<-st(0)MODst

(1)

FPREM1

取余数(IEEE),同FPREM,但是使用IEEE标准[486]FRNDINT

取整(四舍五入)

st(0)<-INT(st(0));dependsonRCflag

FABS

求绝对值

st(0)<-ABS(st(0));removessign

FCHS

改变符号位(求负数)

st(0)<-st(0)

F2XM1

计算(2^x)-1

st(0)<-(2^st(0))-1

FYL2X

计算Y*log2(X)

st(0)为Y;st

(1)为X;将st(0)和st

(1)变为st(0)*log2(st

(1))的值

FCOS

余弦函数Cos

st(0)<-COS(st(0))

FPTAN

正切函数tan

st(0)<-TAN(st(0))

FPATAN

反正切函数arctan

st(0)<-ATAN(st(0))

FSIN

正弦函数sin

st(0)<-SIN(st(0))

FSINCOS

sincos函数

st(0)<-SIN(st(0)),并且压入st

(1)

st(0)<-COS(st(0))FYL2XP1

计算Y*log2(X+1)

st(0)为Y;st

(1)为X;将st(0)和st

(1)变为st(0)*log2(st

(1)+1)的值

处理器控制指令

FINIT

初始化FPUFSTSWAX

保存状态字的值到AX

AX<-MSW

FSTSWdest

保存状态字的值到dest

dest<-MSW(mem16)FLDCWsrc

从src装入FPU的控制字

FPUCW<-src(mem16)

FSTCWdest

将FPU的控制字保存到dest

dest<-FPUCWFCLEX

清除异常

FSTENVdest

保存环境到内存地址dest处保存状态字、控制字、标志字和异常指针的值

FLDENVsrc

从内存地址src处装入保存的环境FSAVEdest

保存FPU的状态到dest处94字节FRSTORsrc

从src处装入由FSAVE保存的FPU状态

FINCSTP

增加FPU的栈指针值

st(6)<-st(5);st(5)<-st(4),...,st(0)<-?

FDECSTP

减少FPU的栈指针值

st(0)<-st

(1);st

(1)<-st

(2),...,st(7)<-?

FFREEst(i)

标志寄存器st(i)未被使用

FNOP

空操作,等同CPU的nop

st(0)<-st(0)

WAIT/FWAIT

同步FPU与CPU:

停止CPU的运行,直到FPU完成当前操作码

FXCH

交换指令,交换st(0)和st

(1)的值

st(0)<-st

(1)

st

(1)<-st(0)

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1