⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄

📁 该文件里包含了大量的常用经典的程序代码,可以为51编程者带来事半功倍的效果,
💻
📖 第 1 页 / 共 3 页
字号:
       
       
          (二)      MCS-51  浮点运算子程序库及其使用说明


    本浮点子程序库有三个不同层次的版本,以便适应不同的应用场合:
    
    1.小型库(FQ51A.ASM):只包含浮点加、减、乘、除子程序。
    
    2.中型库(FQ51B.ASM):在小型库的基础上再增加绝对值、倒数、比较、平方、
开平方、数制转换等子程序。
    
    3.大型库(FQ51.ASM):包含本说明书中的全部子程序。
    为便于读者使用本程序库,先将有关约定说明如下:
    
    1.双字节定点操作数:用[R0]或[R1]来表示存放在由R0或R1指示的连续单元中的数
据,地址小的单元存放高字节。如果[R0]=1234H,若(R0)=30H,则(30H)=12H,(31H)=34H。
    
    2.二进制浮点操作数:用三个字节表示,第一个字节的最高位为数符,其余七位为
阶码(补码形式),第二字节为尾数的高字节,第三字节为尾数的低字节,尾数用双字节
纯小数(原码)来表示。当尾数的最高位为1时,便称为规格化浮点数,简称操作数。在
程序说明中,也用[R0]或[R1]来表示R0或R1指示的浮点操作数,例如:当[R0]=-6.000时,
则二进制浮点数表示为83C000H。若(R0)=30H,则(30H)=83H,(31H)=0C0H,(32H)=00H。
    
    3.十进制浮点操作数:用三个字节表示,第一个字节的最高位为数符,其余七位为
阶码(二进制补码形式),第二字节为尾数的高字节,第三字节为尾数的低字节,尾数用
双字节BCD码纯小数(原码)来表示。当十进制数的绝对值大于1时,阶码就等于整数
部分的位数,如 876.5 的阶码是03H,-876.5 的阶码是 83H;当十进制数的绝对值小于1
时,阶码就等于 80H 减去小数点后面零的个数,例如 0.00382 的阶码是 7EH,-0.00382
的阶码是 0FEH。在程序说明中,用[R0]或[R1]来表示R0或R1指示的十进制浮点操作数。例
如有一个十进制浮点操作数存放在30H、31H、32H中,数值是 -0.07315,即-0.7315乘以10
的-1次方,则(30H)=0FFH,31H=73H,(32H)=15H。若用[R0]来指向它,则应使(R0)=30H。
    
    4.运算精度:单次定点运算精度为结果最低位的当量值;单次二进制浮点算术运算
的精度优于十万分之三;单次二进制浮点超越函数运算的精度优于万分之一;BCD码浮
点数本身的精度比较低(万分之一到千分之一),不宜作为运算的操作数,仅用于输入或
输出时的数制转换。不管那种数据格式,随着连续运算的次数增加,精度都会下降。
    
    5.工作区:数据工作区固定在A、B、R2~R7,数符或标志工作区固定在PSW和23H单
元(位1CH~1FH)。在浮点系统中,R2、R3、R4和位1FH为第一工作区,R5、R6、R7和位1EH
为第二工作区。用户只要不在工作区中存放无关的或非消耗性的信息,程序就具有较好的
透明性。
    
    6.子程序调用范例:由于本程序库特别注意了各子程序接口的相容性,很容易采用
积木方式(或流水线方式)完成一个公式的计算。以浮点运算为例:
    计算   y = Ln √ | Sin (ab/c+d) |
    已知:a=-123.4;b=0.7577;c=56.34;d=1.276; 它们分别存放在30H、33H、36H、
39H开始的连续三个单元中。用BCD码浮点数表示时,分别为a=831234H;b=007577H;
c=025634H;d=011276H。
    求解过程:通过调用BTOF子程序,将各变量转换成二进制浮点操作数,再进行各
种运算,最后调用FTOB子程序,还原成十进制形式,供输出使用。程序如下:
TEST:	MOV  	R0,#39H   ;指向BCD码浮点操作数d
	LCALL	BTOF      ;将其转换成二进制浮点操作数
	MOV  	R0,#36H   ;指向BCD码浮点操作数c
	LCALL	BTOF      ;将其转换成二进制浮点操作数
	MOV  	R0,#33H   ;指向BCD码浮点操作数b
	LCALL	BTOF      ;将其转换成二进制浮点操作数
	MOV  	R0,#30H   ;指向BCD码浮点操作数a
	LCALL	BTOF      ;将其转换成二进制浮点操作数
	MOV  	R1,#33H   ;指向二进制浮点操作数b
	LCALL	FMUL      ;进行浮点乘法运算
	MOV  	R1,#36H   ;指向二进制浮点操作数c
	LCALL	FDIV      ;进行浮点除法运算
	MOV  	R1,#39H   ;指向二进制浮点操作数d
	LCALL	FADD      ;进行浮点加法运算
	LCALL	FSIN      ;进行浮点正弦运算
	LCALL	FABS      ;进行浮点绝对值运算
	LCALL	FSQR      ;进行浮点开平方运算
	LCALL	FLN       ;进行浮点对数运算
	LCALL	FTOB      ;将结果转换成BCD码浮点数
STOP:	LJMP	STOP
	END
    运行结果,[R0]=804915H,即y=-0.4915,比较精确的结果应该是-0.491437。

    (1)  标号:  FSDT    功能:浮点数格式化

入口条件:待格式化浮点操作数在[R0]中。
出口信息:已格式化浮点操作数仍在[R0]中。
影响资源:PSW、A、R2、R3、R4、位1FH    堆栈需求:  6字节

FSDT:	LCALL	MVR0	;将待格式化操作数传送到第一工作区中
	LCALL	RLN	;通过左规完成格式化
	LJMP	MOV0	;通过左规完成格式化

    (2)  标号:  FADD    功能:浮点数加法

入口条件:被加数在[R0]中,加数在[R1]中。
出口信息:OV=0时,和仍在[R0]中,OV=1时,溢出。
影响资源:PSW、A、B、R2~R7、位1EH、1FH  堆栈需求:  6字节

FADD:	CLR	F0	;设立加法标志
	SJMP	AS	;计算代数和

    (3)  标号:  FSUB    功能:浮点数减法

入口条件:被减数在[R0]中,减数在[R1]中。
出口信息:OV=0时,差仍在[R0]中,OV=1时,溢出。
影响资源:PSW、A、B、R2~R7、位1EH、1FH    堆栈需求:6字节

FSUB:	SETB	F0	;设立减法标志
AS:	LCALL	MVR1	;计算代数和。先将[R1]传送到第二工作区
	MOV	C,F0	;用加减标志来校正第二操作数的有效符号
	RRC	A
	XRL	A,@R1
	MOV	C,ACC.7
ASN:	MOV	1EH,C	;将第二操作数的有效符号存入位1EH中
	XRL	A,@R0	;与第一操作数的符号比较
	RLC	A
	MOV	F0,C	;保存比较结果
	LCALL	MVR0	;将[R0]传送到第一工作区中
	LCALL	AS1	;在工作寄存器中完成代数运算
MOV0:	INC	R0	;将结果传回到[R0]中的子程序入口
	INC	R0
	MOV	A,R4	;传回尾数的低字节
	MOV	@R0,A
	DEC	R0
	MOV	A,R3	;传回尾数的高字节
	MOV	@R0,A
	DEC	R0
	MOV	A,R2	;取结果的阶码
	MOV	C,1FH	;取结果的数符
	MOV	ACC.7,C	;拼入阶码中
	MOV	@R0,A
	CLR	ACC.7	;不考虑数符
	CLR	OV	;清除溢出标志
	CJNE	A,#3FH,MV01;阶码是否上溢?
	SETB	OV	;设立溢出标志
MV01:	MOV	A,@R0	;取出带数符的阶码
	RET
MVR0:	MOV	A,@R0	;将[R0]传送到第一工作区中的子程序
	MOV	C,ACC.7	;将数符保存在位1FH中
	MOV	1FH,C
	MOV	C,ACC.6	;将阶码扩充为8bit补码
	MOV	ACC.7,C
	MOV	R2,A	;存放在R2中
	INC	R0
	MOV	A,@R0	;将尾数高字节存放在R3中
	MOV	R3,A
	INC	R0
	MOV	A,@R0	;将尾数低字节存放在R4中
	MOV	R4,A
	DEC	R0	;恢复数据指针
	DEC	R0
	RET
MVR1:	MOV	A,@R1	;将[R1]传送到第二工作区中的子程序
	MOV	C,ACC.7	;将数符保存在位1EH中
	MOV	1EH,C
	MOV	C,ACC.6	;将阶码扩充为8bit补码
	MOV	ACC.7,C
	MOV	R5,A	;存放在R5中
	INC	R1
	MOV	A,@R1	;将尾数高字节存放在R6中
	MOV	R6,A
	INC	R1
	MOV	A,@R1	;将尾数低字节存放在R7中
	MOV	R7,A
	DEC	R1	;恢复数据指针
	DEC	R1
	RET
AS1:	MOV	A,R6	;读取第二操作数尾数高字节
	ORL	A,R7
	JZ	AS2	;第二操作数为零,不必运算
	MOV	A,R3	;读取第一操作数尾数高字节
	ORL	A,R4
	JNZ	EQ
	MOV	A,R6	;第一操作数为零,结果以第二操作数为准
	MOV	R3,A
	MOV	A,R7
	MOV	R4,A
	MOV	A,R5
	MOV	R2,A
	MOV	C,1EH
	MOV	1FH,C
AS2:	RET
EQ:	MOV	A,R2	;对阶,比较两个操作数的阶码
	XRL	A,R5
	JZ	AS4	;阶码相同,对阶结束
	JB	ACC.7,EQ3;阶符互异
	MOV	A,R2	;阶符相同,比较大小
	CLR	C
	SUBB	A,R5
	JC	EQ4
EQ2:	CLR	C	;第二操作数右规一次
	MOV	A,R6	;尾数缩小一半
	RRC	A
	MOV	R6,A
	MOV	A,R7
	RRC	A
	MOV	R7,A
	INC	R5	;阶码加一
	ORL	A,R6	;尾数为零否?
	JNZ	EQ	;尾数不为零,继续对阶
	MOV	A,R2	;尾数为零,提前结束对阶
	MOV	R5,A
	SJMP	AS4
EQ3:	MOV	A,R2	;判断第一操作数阶符
	JNB	ACC.7,EQ2;如为正,右规第二操作数
EQ4:	CLR	C
	LCALL	RR1	;第一操作数右规一次
	ORL	A,R3	;尾数为零否?
	JNZ	EQ	;不为零,继续对阶
	MOV	A,R5	;尾数为零,提前结束对阶
	MOV	R2,A
AS4:	JB	F0,AS5	;尾数加减判断
	MOV	A,R4	;尾数相加
	ADD	A,R7
	MOV	R4,A
	MOV	A,R3	
	ADDC	A,R6
	MOV	R3,A
	JNC	AS2
	LJMP	RR1	;有进位,右规一次
AS5:	CLR	C	;比较绝对值大小
	MOV	A,R4
	SUBB	A,R7
	MOV	B,A
	MOV	A,R3
	SUBB	A,R6
	JC	AS6
	MOV	R4,B	;第一尾数减第二尾数
	MOV	R3,A
	LJMP	RLN	;结果规格化
AS6:	CPL	1FH	;结果的符号与第一操作数相反
	CLR	C	;结果的绝对值为第二尾数减第一尾数
	MOV	A,R7
	SUBB	A,R4
	MOV	R4,A
	MOV	A,R6
	SUBB	A,R3
	MOV	R3,A
RLN:	MOV	A,R3	;浮点数规格化
	ORL	A,R4	;尾数为零否?
	JNZ	RLN1
	MOV	R2,#0C1H;阶码取最小值
	RET     	
RLN1:	MOV	A,R3
	JB	ACC.7,RLN2;尾数最高位为一否?
	CLR	C	;不为一,左规一次
	LCALL	RL1
	SJMP	RLN	;继续判断
RLN2:	CLR	OV	;规格化结束
	RET
RL1:	MOV	A,R4	;第一操作数左规一次
	RLC	A	;尾数扩大一倍
	MOV	R4,A
	MOV	A,R3
	RLC	A
	MOV	R3,A
	DEC	R2	;阶码减一
	CJNE	R2,#0C0H,RL1E;阶码下溢否?
	CLR	A
	MOV	R3,A	;阶码下溢,操作数以零计
	MOV	R4,A
	MOV	R2,#0C1H
RL1E:	CLR	OV
	RET
RR1:	MOV	A,R3	;第一操作数右规一次
	RRC	A	;尾数缩小一半
	MOV	R3,A
	MOV	A,R4
	RRC	A
	MOV	R4,A
	INC	R2	;阶码加一
	CLR	OV	;清溢出标志
	CJNE	R2,#40H,RR1E;阶码上溢否?
	MOV	R2,#3FH	;阶码溢出
	SETB	OV
RR1E:	RET

    (4)  标号:  FMUL    功能:浮点数乘法

入口条件:被乘数在[R0]中,乘数在[R1]中。
出口信息:OV=0时,积仍在[R0]中,OV=1时,溢出。
影响资源:PSW、A、B、R2~R7、位1EH、1FH    堆栈需求:6字节

FMUL:	LCALL	MVR0	;将[R0]传送到第一工作区中
	MOV	A,@R0
	XRL	A,@R1	;比较两个操作数的符号
	RLC	A
	MOV	1FH,C	;保存积的符号
	LCALL	MUL0	;计算积的绝对值
	LJMP	MOV0	;将结果传回到[R0]中
MUL0:	LCALL	MVR1	;将[R1]传送到第二工作区中
MUL1:	MOV	A,R3	;第一尾数为零否?
	ORL	A,R4
	JZ	MUL6
	MOV	A,R6	;第二尾数为零否?
	ORL	A,R7
	JZ	MUL5
	MOV	A,R7	;计算R3R4×R6R7-→R3R4
	MOV	B,R4
	MUL	AB
	MOV	A,B
	XCH	A,R7
	MOV	B,R3
	MUL	AB
	ADD	A,R7
	MOV	R7,A
	CLR	A
	ADDC	A,B
	XCH	A,R4
	MOV	B,R6
	MUL	AB
	ADD	A,R7
	MOV	R7,A
	MOV	A,B
	ADDC	A,R4
	MOV	R4,A
	CLR	A
	RLC	A
	XCH	A,R3
	MOV	B,R6
	MUL	AB
	ADD	A,R4
	MOV	R4,A
	MOV	A,B
	ADDC	A,R3
	MOV	R3,A
	JB	ACC.7,MUL2;积为规格化数否?
	MOV	A,R7	;左规一次
	RLC	A
	MOV	R7,A
	LCALL	RL1
MUL2:	MOV	A,R7
	JNB	ACC.7,MUL3
	INC	R4
	MOV	A,R4
	JNZ	MUL3
	INC	R3
	MOV	A,R3
	JNZ	MUL3
	MOV	R3,#80H
	INC	R2
MUL3:	MOV	A,R2	;求积的阶码
	ADD	A,R5
MD:	MOV	R2,A	;阶码溢出判断
	JB	ACC.7,MUL4
	JNB	ACC.6,MUL6
	MOV	R2,#3FH	;阶码上溢,设立标志
	SETB	OV
	RET
MUL4:	JB	ACC.6,MUL6
MUL5:	CLR	A	;结果清零(因子为零或阶码下溢)
	MOV	R3,A
	MOV	R4,A
	MOV	R2,#41H
MUL6:	CLR	OV
	RET

    (5)  标号:  FDIV    功能:浮点数除法

入口条件:被除数在[R0]中,除数在[R1]中。
出口信息:OV=0时,商仍在[R0]中,OV=1时,溢出。
影响资源:PSW、A、B、R2~R7、位1EH、1FH   堆栈需求:  5字节

FDIV:	INC	R0
	MOV	A,@R0
	INC	R0
	ORL	A,@R0
	DEC	R0
	DEC	R0
	JNZ	DIV1
	MOV	@R0,#41H;被除数为零,不必运算
	CLR	OV
	RET
DIV1:	INC	R1
	MOV	A,@R1
	INC	R1  	
	ORL	A,@R1
	DEC	R1
	DEC	R1  	
	JNZ	DIV2	
	SETB	OV	;除数为零,溢出
	RET     	
DIV2:	LCALL	MVR0	;将[R0]传送到第一工作区中
	MOV	A,@R0
	XRL	A,@R1	;比较两个操作数的符号
	RLC	A
	MOV	1FH,C	;保存结果的符号
	LCALL	MVR1	;将[R1]传送到第二工作区中
	LCALL	DIV3	;调用工作区浮点除法
	LJMP	MOV0	;回传结果
DIV3:	CLR	C	;比较尾数的大小
	MOV	A,R4
	SUBB	A,R7
	MOV	A,R3
	SUBB	A,R6
	JC	DIV4
	LCALL	RR1	;被除数右规一次
	SJMP	DIV3
DIV4:	CLR	A	;借用R0R1R2作工作寄存器
	XCH	A,R0	;清零并保护之
	PUSH	ACC
	CLR	A
	XCH	A,R1
	PUSH	ACC
	MOV	A,R2
	PUSH	ACC
	MOV	B,#10H	;除法运算,R3R4/R6R7-→R0R1
DIV5:	CLR	C
	MOV	A,R1
	RLC	A
	MOV	R1,A
	MOV	A,R0
	RLC	A
	MOV	R0,A
	MOV	A,R4
	RLC	A
	MOV	R4,A
	XCH	A,R3
	RLC	A
	XCH	A,R3
	MOV	F0,C
	CLR	C
	SUBB	A,R7
	MOV	R2,A
	MOV	A,R3
	SUBB	A,R6
	ANL	C,/F0
	JC	DIV6
	MOV	R3,A
	MOV	A,R2
	MOV	R4,A
	INC	R1
DIV6:	DJNZ	B,DIV5
	MOV	A,R6	;四舍五入
	CLR	C
	RRC	A
	SUBB	A,R3
	CLR	A
	ADDC	A,R1	;将结果存回R3R4
	MOV	R4,A
	CLR	A
	ADDC	A,R0
	MOV	R3,A
	POP	ACC	;恢复R0R1R2
	MOV	R2,A
	POP	ACC
	MOV	R1,A
	POP	ACC
	MOV	R0,A
	MOV	A,R2	;计算商的阶码
	CLR	C
	SUBB	A,R5
	LCALL	MD	;阶码检验
	LJMP	RLN	;规格化

    (6)  标号:  FCLR      功能:浮点数清零

入口条件:操作数在[R0]中。
出口信息:操作数被清零。
影响资源:A    堆栈需求:  2字节

FCLR:	INC	R0
	INC	R0
	CLR	A
	MOV	@R0,A
	DEC	R0
	MOV	@R0,A
	DEC	R0
	MOV	@R0,#41H
	RET 	

    (7)  标号:  FZER    功能:浮点数判零

入口条件:操作数在[R0]中。
出口信息:若累加器A为零,则操作数[R0]为零,否则不为零。
影响资源:A    堆栈需求:  2字节

FZER:	INC	R0
	INC	R0
	MOV	A,@R0
	DEC	R0
	ORL	A,@R0
	DEC	R0
	JNZ	ZERO
	MOV	@R0,#41H
ZERO:	RET 	

    (8)  标号:  FMOV    功能:浮点数传送

入口条件:源操作数在[R1]中,目标地址为[R0]。
出口信息:[R0]=[R1],[R1]不变。
影响资源:A   堆栈需求:  2字节

FMOV:	INC	R0
	INC	R0
	INC	R1
	INC	R1
	MOV	A,@R1
	MOV	@R0,A
	DEC	R0
	DEC	R1
	MOV	A,@R1
	MOV	@R0,A
	DEC	R0
	DEC	R1
	MOV	A,@R1
	MOV	@R0,A
	RET

    (9)  标号:  FPUS    功能:浮点数压栈

入口条件:操作数在[R0]中。
出口信息:操作数压入栈顶。
影响资源:A、R2、R3    堆栈需求:  5字节

FPUS:	POP	ACC	;将返回地址保存在R2R3中
	MOV	R2,A
	POP	ACC
	MOV	R3,A
	MOV	A,@R0	;将操作数压入堆栈
	PUSH	ACC
	INC	R0
	MOV	A,@R0
	PUSH	ACC
	INC	R0
	MOV	A,@R0
	PUSH	ACC
	DEC	R0
	DEC	R0
	MOV	A,R3	;将返回地址压入堆栈
	PUSH	ACC
	MOV	A,R2
	PUSH	ACC
	RET		;返回主程序

    (10)  标号:  FPOP    功能:浮点数出栈

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -