汇编语言浮点数算术运算指令


下表列出了基本算术运算操作。所有算术运算指令支持的内存操作数类型与 FLD (加载)和 FST(保存)一致,因此,操作数可以是间接操作数、变址操作数和基址-变址操作数等等。

FCHS 修改符号
FADD 源操作数与目的操作数相加
FSUB 从目的操作数中减去源操作数
FSUBR 从源操作数中减去目的操作数
FMUL 源操作数与目的操作数相乘
FDIV 目的操作数除以源操作数
FDIVR 源操作数除以目的操作数

FCHS 和 FABS

FCHS( 修改符号 ) 指令将 ST(0) 中浮点数值的符号取反。FABS ( 绝对值 ) 指令清除 ST(0) 中数值的符号,以得到它的绝对值。这两条指令都没有操作数:

FCHS
FABS

FADD、FADDP、FIADD

FADD(加法)指令格式如下,其中,m32fp 是 REAL4 内存操作数,m64fp 即是 REAL8 内存操作数,i 是寄存器编号:

FADD
FADD m32fp
FADD m64fp
FADD ST(0), ST(i)
FADD ST(i) , ST(0)

无操作数

如果 FADD 没有操作数,则 ST(0)与 ST(1)相加,结果暂存在 ST(l)。然后 ST(0) 弹出堆栈,把加法结果保留在栈顶。假设堆栈已经包含了两个数值,下图展示了 FADD 的操作:

寄存器操作数

从同样的栈开始,如下所示将 ST(0) 加到 ST(1):

内存操作数

如果使用的是内存操作数,FADD 将操作数与 ST(0) 相加。示例如下:

fadd mySingle       ; ST(0) += mySingle
fadd REAL8 PTR[esi]   ; ST(0) += [esi]

FADDP

FADDP(相加并出栈)指令先执行加法操作,再将 ST(0) 弹出堆栈。MASM 支持如下格式:

FADDP ST(i),ST(0)

下图演示了 FADDP 的操作过程:

FIADD

FIADD(整数加法)指令先将源操作数转换为扩展双精度浮点数,再与 ST(0) 相加。指令语法如下:

FIADD ml6int
FIADD m32int

示例:

.data
myInteger DWORD 1
.code
fiadd myInteger          ; ST(0) += myInteger

FSUB、FSUBP、FISUB

FSUB 指令从目的操作数中减去源操作数,并把结果保存在目的操作数中。目的操作数总是一个 FPU 寄存器,源操作数可以是 FPU 寄存器或者内存操作数。该指令操作数类型与 FADD 指令一致:

FSUB
FSUB m32fp
FSUB m64fp
FSUB ST(0), ST(i)
FSUB ST(i), ST(0)

FSUB 的操作与 FADD 相似,只不过它进行的是减法而不是加法。比如,无参数 FSUB 实现 ST(1) - ST(0),结果暂存于 ST(1)。然后 ST(0) 弹出堆栈,将减法结果留在栈顶。若 FSUB 使用内存操作数,则从 ST(0) 中减去内存操作数,且不再弹出堆栈。

fsub mySingle       ; ST(0) -= mySingle
fsub array[edi*8]   ; ST(0) -= array[edi*8]

FSUBP

FSUBP(相减并出栈)指令先执行减法,再将 ST(0) 弹出堆栈。MASM 支持如下格式:

FSUBP ST(i),ST(0)

FISUB

FISUB(整数减法)指令先把源操作数转换为扩展双精度浮点数,再从 ST(0) 中减去该操作数:

FISUB m16int
FISUB m32int

FMUL、FMULP、FIMUL

FMUL 指令将源操作数与目的操作数相乘,乘积保存在目的操作数中。目的操作数总是一个 FPU 寄存器,源操作数可以为寄存器或者内存操作数。其语法与 FADD 和 FSUB 相同:

FMUL
FMUL m32fp
FMUL m64fp
FMUL ST(0), ST(i)
FMUL ST(i), ST(0)

除了执行的是乘法而不是加法外,FMUL 的操作与 FADD 相同。比如,无参数 FMUL 将 ST(O) 与 ST(1) 相乘,乘积暂存于 ST(1)。然后 ST(0) 弹出堆栈,将乘积留在栈顶。同样,使用内存操作数的 FMUL 则将内存操作数与 ST(0) 相乘:

fmul mySingle    ; ST(0) *= mySingle

FMULP

FMULP(相乘并出栈)指令先执行乘法,再将 ST(0) 弹出堆栈。MASM 支持如下格式:

FMULP ST(i),ST(O)

FIMUL 与 FIADD 相同,只是它执行的是乘法而不是加法:

FIMUL ml6int
FIMUL m32int

FDIV、FDIVP、FIDIV

FDIV 指令执行目的操作数除以源操作数,被除数保存在目的操作数中。目的操作数总是一个寄存器,源操作数可以为寄存器或者内存操作数。其语法与 FADD 和 FSUB 相同:

FDIV
FDIV m32fp
FDIV m64fp
FDIV ST(O), ST(i)
FDIV ST(i), ST(O)

除了执行的是除法而不是加法外,FDIV 的操作与 FADD 相同。比如,无参数 FDIV 执行 ST(1) 除以 ST(0)。然后 ST(0) 弹出堆栈,将被除数留在栈顶。使用内存操作数的 FDIV 将 ST(0) 除以内存操作数。下面的代码将 dblOne 除以 dblTwo,并将商保存到 dblQuot:

.data
dblOne REAL8 1234.56
dblTwo REAL8 10.0
dblQuot REAL8 ?
.code
fid dblOne           ; 加载到 ST (0)
fdiv dblTwo         ; ST(0) 除以 dblTwo
fstp dblQuot       ; 将 ST(0) 保存到 dblQuot

若源操作数为 0,则产生除零异常。若源操作数等于正、负无穷,零或 NaN,则使用一些特殊情况。

FIDIV

FIDIV 指令先将整数源操作数转换为扩展双精度浮点数,再执行与 ST(0) 的除法。其语法如下:

FIDIV ml6int
FIDIV m32int