汇编浮点运算指令集(转载)
浮点执⾏环境的寄存器主要是8个通⽤数据寄存器和⼏个专⽤寄存器,它们是状态寄存器、控制寄存器、标记寄存器等
8个浮点数据寄存器(FPU Data Register),编号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-Point Format)所⽰,分成指数、有效数字和符号位三个部分。
·  符号(Sign)——表⽰数据的正负,在最⾼有效位(MSB)。负数的符号位为1,正数的符号为0。
· 指数(Exponent)——也被称为阶码,表⽰数据以2为底的幂。指数采⽤偏移码(Biased Exponent)表⽰,恒为整数。
· 有效数字(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位扩展精度这种数据类
型,80x87 FPU主要在内部使⽤它存贮中间结果,以保证最终数值的精度。
浮点处理单元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位数据;它们可以⽤于定义单精度、双精度和扩展精度浮点数。为了区别于整数定义,MASM 6.11建议采⽤REAL4、REAL8、REAL10定义单、双、扩展精度浮点数,但不能出现纯整数(其实,整数后⾯补个⼩数点就可以了)。相应的数据属性依次是dword、qword、tbyte。另外,实常数可以⽤E表⽰10的幂。
·  初始化浮点处理单元
每当执⾏⼀个新的浮点程序时,第⼀条指令都应该是初始化FPU的指令finit。该指令清除浮点数据寄存器栈和异常,为程序提供⼀个“⼲净”的初始状态。否则,遗留在浮点寄存器栈中的数据可能会产⽣堆栈溢出。另⼀⽅⾯,浮点指令程序段结束,也最好清空浮点数据寄存器。
浮点传送程序
.model small
.8087                ;识别浮点指令
.stack
.data
f32d      dd 100.25            ;单精度浮点数:42C88000 h
f64d      dq -0.2109375        ;双精度浮点数:BFCB000000000000 h
f80d      dt 100.25e9          ;扩展精度浮点数:4023BABAECD400000000 h
i16d      dw 100                ;字整数:0064 h
i32d      dd -1234              ;短整数:FFFFFB2E h
i64d      dq 123456h            ;长整数:0000000000123456 h
b80d      dt 123456h            ;BCD码数:00000000000000123456 h
ib32      dd ?
bi80      dt ?
.code
.startup
start1:    finit                ;初始化FPU
fld f32d              ;压⼊单精度浮点数f32d
fld f64d              ;压⼊双精度浮点数f64d
fld f80d              ;压⼊扩展精度浮点数f80d
fld st(1)            ;压⼊当前st(1),即f64d
fild i16d            ;压⼊字整数i16d
fild i32d            ;压⼊短整数i32d
fild i64d            ;压⼊长整数i64d
fbld b80d            ;压⼊BCD码数b80d
start2:    fist dword ptr ib32  ;将栈顶(现为b80d)以短整数保存
fxch                  ;st(0)与st(1)互换,现栈顶为i64d
fbstp tbyte ptr bi80  ;将栈顶弹出成BCD码数
start3:    .exit 0
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. 数据传递和对常量的操作指令
指令格式
指令含义执⾏的操作FLD src
装⼊实数到st(0)st(0) <- src (mem32/mem64/mem80)FILD src
装⼊整数到st(0)st(0) <- src (mem16/mem32/mem64)FBLD src 装⼊BCD 数到st(0)
st(0) <- src (mem80) FLDZ 将0.0装⼊st(0)
st(0) <- 0.0FLD1将1.0装⼊st(0)
st(0) <- 1.0FLDPI 将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) FST dest 保存实数st(0)到dest dest <- st(0) (mem32/mem64)
FSTP dest  dest <- st(0) (mem32/mem64/mem80);然后再执⾏
⼀次出栈操作
FIST dest 将st(0)以整数保存到dest dest <- st(0) (mem32/mem64)
FISTP dest  dest <- st(0) (mem16/mem32/mem64);然后再执⾏
⼀次出栈操作
FBST dest 将st(0)以BCD 保存到dest dest <- st(0) (mem80)
FBSTP dest
dest <- st(0) (mem80);然后再执⾏⼀次出栈操作2.⽐较指令
指令格式
指令含义执⾏的操作FCOM
实数⽐较将标志位设置为 st(0) - st(1) 的结果标志位FCOM op 实数⽐较将标志位设置为 st(0) - op (mem32/mem64)的结果标
志位
FICOM op 和整数⽐较将Flags 值设置为st(0)-op 的结果op (mem16/mem32)
FICOMP op 和整数⽐较将st(0)和op ⽐较 op(mem16/mem32)后;再执⾏⼀次
出栈操作
FTST 零检测 将st(0)和0.0⽐较
FUCOM st(i)  ⽐较st(0) 和st(i)                  [486]
FUCOMP st(i)      ⽐较st(0) 和st(i),并且执⾏⼀次出栈操作
FUCOMPP st(i)    ⽐较st(0) 和st(i),并且执⾏两次出栈操作
FXAM
Examine: Eyeball st(0) (set condition codes)3.运算指令
指令格式
指令含义执⾏的操作加法
FADD
加实数st(0) <-st(0) + st(1)FADD src
st(0) <-st(0) + src (mem32/mem64)FADD st(i),st
st(i) <- st(i) + st(0)FADDP st(i),st
st(i) <- st(i) + st(0);然后执⾏⼀次出栈操作FIADD src
加上⼀个整数st(0) <-st(0) + src (mem16/mem32)减法
FSUB
减去⼀个实数st(0) <- st(0) - st(1)FSUB src
st(0) <-st(0) - src (reg/mem)FSUB st(i),st
st(i) <-st(i) - st(0)FSUBP st(i),st
st(i) <-st(i) - st(0),然后执⾏⼀次出栈操作FSUBR st(i),st
⽤⼀个实数来减st(0) <- st(i) - st(0)FSUBRP st(i),st
st(0) <- st(i) - st(0),然后执⾏⼀次出栈操作FISUB src
减去⼀个整数st(0) <- st(0) - src (mem16/mem32)FISUBR src
⽤⼀个整数来减st(0) <- src - st(0) (mem16/mem32)乘法
FMUL
乘上⼀个实数st(0) <- st(0) * st(1)FMUL st(i)
st(0) <- st(0) * st(i)FMUL st(i),st
st(i) <- st(0) * st(i)FMULP st(i),st
st(i) <- st(0) * st(i),然后执⾏⼀次出栈操作FIMUL src
乘上⼀个整数st(0) <- st(0) * src (mem16/mem32)除法
FDIV
除以⼀个实数st(0) <-st(0) /st(1)FDIV st(i)
st(0) <- st(0) /t(i)
FDIV st(i),st  st(i) <-st(0) /st(i)FDIVP st(i),st
st(i) <-st(0) /st(i),然后执⾏⼀次出栈操作FIDIV src
除以⼀个整数st(0) <- st(0) /src (mem16/mem32)FDIVR st(i),st
⽤实数除st(0) <- st(i) /st(0)FDIVRP st(i),st
FDIVRP st(i),st FIDIVR src  ⽤整数除st(0) <- src /st(0) (mem16/mem32)
FSQRT 平⽅根st(0) <- sqrt st(0)
FSCALE 2的st(0)次⽅st(0) <- 2 ^ st(0)
FXTRACT
Extract exponent:st(0) <-exponent of st(0); and gets pushed
st(0) <-significand of st(0)
FPREM
取余数st(0) <-st(0) MOD st(1)FPREM1取余数(IEEE ),同FPREM ,但是使⽤IEEE 标准[486]
FRNDINT 取整(四舍五⼊)
st(0) <- INT( st(0) ); depends on RC flag  FABS 求绝对值
st(0) <- ABS( st(0) ); removes sign FCHS 改变符号位(求负数)
st(0) <-st(0) F2XM1计算(2 ^ x)-1
st(0) <- (2 ^ st(0)) - 1FYL2X  计算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
初始化FPU  FSTSW AX
保存状态字的值到AX AX <- MSW FSTSW dest 保存状态字的值到dest dest <-MSW (mem16)
FLDCW src
从src 装⼊FPU 的控制字FPU CW <-src (mem16)FSTCW dest 将FPU 的控制字保存到dest dest <- FPU CW
FCLEX 清除异常
FSTENV dest
保存环境到内存地址dest 处保存状态字、控制字、标志字和异常指针的值FLDENV src
从内存地址src 处装⼊保存的环境 FSAVE dest
保存FPU 的状态到dest 处 94字节 FRSTOR src 从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) <-?
FFREE st(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)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。