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

📄 floating-point0favr.asm

📁 AVR单片机浮点数运算程序
💻 ASM
字号:
;****	数据处理	*********************************
DataTrans:
	push	R13				;保护浮点运算使用寄存区
	push	R14
	push	R15
	push	R16
	push	R17
	push	R18
	push	R19
	push	R20
	push	R21
	push	R22
	push	R23
	push	R24
	push	R25
	push	R26
	push	R27
	push	R28
	push	R29
	ldi		YH,HIGH(DataStack)
	ldi		YL,LOW(DataStack)

;****	数据处理	*********************************

	pop		R29
	pop		R28
	pop		R27
	pop		R26
	pop		R25
	pop		R24
	pop		R23
	pop		R22
	pop		R21
	pop		R20
	pop		R19
	pop		R18
	pop		R17
	pop		R16
	pop		R15
	pop		R14
	pop		R13

	ret

;****	四字节浮点数运算程序

;INT2FP 16 位整数转换成四字节浮点数运算子程
;	入口 r17:r16 出口r19:r18:r17:r16
;	使用的寄存器r16,r17,r18,r19,r20,r26
;LONG2FP 32 位长整数转换成四字节浮点数运算子程
;	入口r19:r18:r17:r16 出口r19:r18:r17:r16
;	使用的寄存器r16,r17,r18,r19,r20,r26
;FP2INT 四字节浮点数转换成16 位整数运算子程
;	入口 r19:r18:r17:r16 出口r19:r18
;	使用的寄存器r16,r17,r18,r19,r20,r26
;FP2LONG 四字节浮点数转换成32 位长整数运算子程
;	入口r19:r18:r17:r16 出口r19:r18:r17:r16
;	使用的寄存器r16,r17,r18,r19,r20,r26
;ADD32F 四字节浮点加法运算子程
;	入口r19:r18:r17:r16 + r24:r23:r22:r21 出口r19:r18:r17:r16
;	使用的寄存器r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r28,r29
;	使用的SRAM Y-5 Y-4 Y-3 Y-2 Y-1
;SUB32F 四字节浮点减法运算子程
;	入口r19:r18:r17:r16 - r24:r23:r22:r21 出口r19:r18:r17:r16
;	使用的寄存器r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r28,r29
;	使用的SRAM Y-5 Y-4 Y-3 Y-2 Y-1
;DIV32F 四字节浮点除法运算子程
;	入口r19:r18:r17:r16 / r24:r23:r22:r21 出口r19:r18:r17:r16
;	使用的寄存器r13,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r28,r29
;	使用的SRAM Y-1
;MPY32F 四字节浮点乘法运算子程
;	入口r19:r18:r17:r16 * r24:r23:r22:r21 出口r19:r18:r17:r16
;	使用的寄存器r13,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r28,r29
;	使用的SRAM Y-1

INT2FP: 					; 16 位整数转换成四字节浮点数运算子程
	CLR		R18
	SBRC	R17,7 			; R17:R16 为待转换的整数
	COM		R18
	CLR 	R19 			; 16 位整数按数符位扩展成32 位长整数
	SBRC 	R18,7 			; 为正R19,R18 清零
	COM 	R19 			; 为负R19,R18 置为$FFFF
LONG2FP: 					; 32 位长整数转换成四字节浮点数运算子程
	CLR 	R20 			; 清符号位R20
	AND 	R19,R19 		; 先判+/-
	BRPL 	LONG2FP_1 		; 为正跳至LONG2FP_1
	RCALL 	QUBU 			; 为负调QUBU 子程取补
	COM 	R20 			; 符号位R20 取反
LONG2FP_1:
	MOV 	R26,R16 		; 再判R19:R18:R17:R16 是否全零
	OR 		R26,R17
	OR 		R26,R18
	OR 		R26,R19
	BRNE 	LONG2FP_2		; 不为零跳至LONG2FP_2
	RJMP 	JGW0 			; 为零跳至JGW0 结果为零
LONG2FP_2:
	LDI 	R26,$16 		; 令R26 = 22
	RJMP 	LONG2FP_4
LONG2FP_3:
	INC 	R26
	LSR 	R19
	ROR 	R18
	ROR 	R17
	ROR 	R16
LONG2FP_4:
	AND 	R19,R19 		; 判高位是否为零
	BRNE 	LONG2FP_3 		; 不为零右移一位阶码加 1
LONG2FP_5:
	AND 	R18,R18 		; 判次高位是否为零
	BRNE 	LONG2FP_7
	SUBI 	R26,$08 		; 为零阶码减 8
	MOV 	R18,R17 		; 数左移 8 位
	MOV 	R17,R16
	LDI 	R16,$00 		; 低位以 $00 填充
	RJMP 	LONG2FP_5
LONG2FP_6:
	DEC 	R26
	ADD 	R16,R16
	ADC 	R17,R17
	ADC 	R18,R18
LONG2FP_7:
	BRPL 	LONG2FP_6 		; R18 第7 为0 再左移一位
	MOV 	R19,R26 		; 阶码减 1 直到R18 第7 位为1
	RJMP 	GGH
FP2INT: 					; 四字节浮点数转换成16 位整数运算子程
	LDI 	R26,$0E 		; 令R26 = 14
	RJMP 	FP2LONG_1 		; 跳至FP2LONG_1
FP2LONG: 					; 四字节浮点数转换成32 位长整数运算子程
	LDI 	R26,$1E 		; 令R26 = 30
FP2LONG_1:
	RCALL 	FP2LONG_11 		; 调FP2LONG_11 子程
	BREQ 	FP2LONG_4 		; 相等即阶码为 0 按 0 处理
	SUB 	R26,R19 		; R26(14)- 阶码差值
	BREQ 	FP2LONG_2 		; 为 0 则跳至FP2LONG_2
	BRPL 	FP2LONG_5 		; 为正 则跳至FP2LONG_5 无溢出
FP2LONG_2: 					; 有溢出
	AND 	R20,R20 		; 符号为正
	BRMI 	FP2LONG_3 		; 符号为负则跳至FP2LONG_3
	LDI 	R16,$FF
	LDI 	R17,$FF
	LDI 	R18,$FF
	LDI 	R19,$7F
	RET 					; 正向溢出结果置为 $7F FF FF FF
FP2LONG_3:
	LDI 	R16,$00
	LDI 	R17,$00
	LDI 	R18,$00
	LDI 	R19,$80
	RET 					; 负向溢出结果置为 $80 00 00 00
FP2LONG_4:
	LDI 	R16,$00
	LDI 	R17,$00
	LDI 	R18,$00
	LDI 	R19,$00
	RET 					; 结果为 0 置为 $00 00 00 00
FP2LONG_5: 					; 无溢出
	INC 	R19 			; 阶码差值 + 1
	BRMI 	FP2LONG_4 		; 为负即( 阶码 < $7E) 按零处理
	LDI 	R19,$00 		; 清R19
	SUBI 	R26,$08 		;R26(14- 阶码差值) -8
	BRPL 	FP2LONG_7 		; 为正转FP2LONG_7
	SUBI 	R26,$F8 		; 不够减则加 8
	MOV 	R19,R18 		;左移 8 位
	MOV 	R18,R17
	MOV 	R17,R16
	LDI 	R16,$7F 		; 低位以 $7F 填充
	RJMP 	FP2LONG_8 		; 跳至 FP2LONG_8
FP2LONG_6:
	MOV 	R16,R17 		; 右移 8 位
	MOV 	R17,R18
	LDI 	R18,$00 		; 高位以 $00 填充
	SUBI 	R26,$08 		; R26-8
FP2LONG_7:
	CPI 	R26,$08 		; R26 值与 8 相比较
	BRCC 	FP2LONG_6 		; 有借位跳至FP2LONG_6
FP2LONG_8: 					;无借位
	AND 	R26,R26
	BREQ 	FP2LONG_10
FP2LONG_9:
	LSR 	R19 			; 右移一位
	ROR 	R18
	ROR 	R17
	ROR 	R16
	DEC 	R26 			;R26-1, 不为 0 跳至FP2LONG_9
	BRNE 	FP2LONG_9 		; 直到R26 为 0 为止
FP2LONG_10: 				; 考虑符号位
	SBRC 	R20,7
	RJMP 	QUBU 			; 为负则跳至QUBU 取补 返回
	RET 					; 为正返回
FP2LONG_11:
	MOV 	R20,R19 		; 取浮点数数符存于R20 最高位
	ANDI 	R20,$80
	ADD 	R18,R18 		; 将阶码移至R19
	ADC 	R19,R19
	SUBI 	R19,$80 		; 阶码减 $80 存于R19
	SEC
	ROR 	R18 			; 恢复尾数最高位 1
	CPI 	R19,$80 		; 阶码差值与 $80 相比较
	RET
ADD32F_1: 					; 存储结果
	MOV 	R20,R25
	MOV 	R19,R24
	MOV 	R18,R23
	MOV 	R17,R22
	MOV 	R16,R21
ADD32F_2:
	RJMP 	GGH 			; 跳至GGH 处理结果
SUB32F: 					; 四字节浮点减法运算子程
	SUBI 	R24,$80 		; 减数取反视为浮点加法运算
ADD32F: 					; 四字节浮点加法运算子程
	RCALL 	YCL 			; 调YCL 子程
	CPI	 	R24,$80 		; 先判加数是否为 0
	BREQ 	ADD32F_2 		; 为 0 则和为被加数 跳至ADD32F_2
	CPI 	R19,$80 		; 再判被加数是否为 0
	BREQ 	ADD32F_1 		; 为 0 则和为加数 跳至ADD32F_1
ADD32F_3:
	MOV 	R26,R19 		; 转存被加数阶码
	SUB 	R26,R24 		;R26= 被加数阶码 减 加数阶码
	BRVS 	ADD32F_2 		; 溢出跳至ADD32F_2 即加数可忽略
	BRMI 	ADD32F_4 		; 为负跳至ADD32F_4
	BRNE 	ADD32F_5 		; 不等跳至ADD32F_5
	CP 		R16,R21
	CPC 	R17,R22
	CPC 	R18,R23
	BRCC 	ADD32F_5
ADD32F_4:
	RCALL 	ADD32F_16 		; 调ADD32F_16 被加数和加数相交换
	RJMP 	ADD32F_3 		; 跳至ADD32F_3
ADD32F_5:
	CPI 	R26,$18 		;阶码差值与 24 相比较
	BRCS 	ADD32F_6 		;C=1 跳至ADD32F_6 即 < 24
	CLR 	R21 			; > 24 加数清 0
	CLR 	R22
	CLR 	R23
ADD32F_6:
	CPI 	R26,$08 		; 阶码差值与 8 相比较
	BRCS 	ADD32F_7 		;C=1 跳至ADD32F_7 ( 直至 < 8)
	MOV 	R21,R22 		; 加数尾数右移 8 位
	MOV 	R22,R23 		; 高 8 位清 0
	CLR 	R23
	SUBI 	R26,$08 		; 阶码差值再减 8
	RJMP 	ADD32F_6 		; 跳至ADD32F_6
ADD32F_7:
	AND 	R26,R26
	BREQ 	ADD32F_9 		; 直至R26=0 跳至ADD32F_9
ADD32F_8:
	LSR 	R23 			; 加数尾数右移 1 位
	ROR 	R22
	ROR 	R21
	DEC 	R26 			; 阶码差值减 1
	BRNE 	ADD32F_8 		; 不为 0 跳至ADD32F_8
ADD32F_9:
	MOV 	R26,R20 		; 被加数和加数是否同号
	EOR 	R26,R25
	BRMI 	ADD32F_10 		; 异号跳至ADD32F_10
	RCALL 	ADD32F_13 		; 同号调ADD32F_13 子程尾数相加
	BRCC 	ADD32F_2 		; C=0, 无溢出跳至ADD32F_2
	ROR 	R18 			; C=1, 溢出尾数右移 1 位
	ROR 	R17
	ROR 	R16
	SUBI 	R19,$FF 		; 阶码加 1
	BRVC 	ADD32F_2 		; 无溢出跳至ADD32F_2 处理结果
	RJMP 	JGZD 			; 溢出跳至JGZD 出结果
ADD32F_10:
	RCALL 	ADD32F_14 		;调ADD32F_14 子程尾数相减
	BRNE 	ADD32F_11 		; 不等跳至ADD32F_11
	RJMP 	JGW0 			; 跳至JGW0 出结果
ADD32F_11:
	BRCC 	ADD32F_12 		;C=0, 够减跳至ADD32F_12
	RCALL 	ADD32F_15 		;C=1, 不够减调ADD32F_15 子程取补
ADD32F_12:
	AND 	R18,R18 		; 判R18 最高位是否位 1
	BRMI 	ADD32F_2 		; 为 1 跳至ADD32F_2 处理结果
	ADD 	R16,R16 		; 为 0 尾数左移一位
	ADC 	R17,R17
	ADC 	R18,R18
	SUBI 	R19,$01 		; 阶码减 1
	BRVC 	ADD32F_12 		; 无溢出跳至ADD32F_12
	RJMP 	JGZD 			; 溢出跳至JGZD 出结果
ADD32F_13: 					; 尾数相加
	ADD 	R16,R21
	ADC 	R17,R22
	ADC 	R18,R23
	RET
ADD32F_14: 					; 尾数相减
	SUB 	R16,R21
	SBC 	R17,R22
	SBC 	R18,R23
	RET
ADD32F_15: 					; 结果取补
	COM 	R17
	COM 	R18
	NEG 	R16
	SBCI 	R17,$FF
	SBCI 	R18,$FF
	RET
ADD32F_16: 					; 两个数相交换
	ST 		-Y,R21
	ST 		-Y,R22
	ST 		-Y,R23
	ST 		-Y,R24
	ST 		-Y,R25
	MOV 	R24,R19
	MOV 	R21,R16
	MOV 	R22,R17
	MOV 	R23,R18
	MOV 	R25,R20
	LD 		R20,Y+
	LD 		R19,Y+
	LD 		R18,Y+
	LD 		R17,Y+
	LD 		R16,Y+
	RET
YCL:
	MOV 	R20,R19
	LDI 	R26,$80
	ADD 	R18,R18
	ADC 	R19,R19 		; 将阶码移至R19
	EOR 	R19,R26 		; 阶码减 $80 存于R19
	ADD 	R26,R26
	ROR 	R18 			; 恢复尾数最高位 1
	ANDI 	R20,$80 		; 取浮点数数符存于R20 最高位
	MOV 	R25,R24
	LDI 	R26,$80
	ADD 	R23,R23 		; 将阶码移至R24
	ADC 	R24,R24
	EOR 	R24,R26 		; 阶码减 $80 存于R24
	ADD 	R26,R26
	ROR 	R23 			; 恢复尾数最高位 1
	ANDI 	R25,$80 		; 取浮点数数符存于R25 最高位
	CPI 	R19,$80
	RET
GGH: 						; 规格化
	ADD 	R18,R18 		; 隐含尾数最高位为 1
	LDI 	R26,$80 		; 考虑符号位
	EOR 	R26,R19 ;
	ADD 	R20,R20
	ROR 	R26 			; 右移R26,R18
	ROR 	R18
	MOV 	R19,R26 		;R26移至R19
	RET
DIV32F_1:
	ST 		-Y,R26 			; 转存R26
	CLR 	R13 			; 清R15:R14:R13
	CLR 	R14
	CLR 	R15
	LDI 	R26,$18 		; 令R26=$18(24)
DIV32F_2:
	CP 		R16,R21 		; 被除数( 余数) 与除数两尾数相比
	CPC 	R17,R22
	CPC 	R18,R23
	BRCS 	DIV32F_3 		; 被除数( 余数) < 除数
	SUB 	R16,R21 		; 余数 = 被除数 - 除数
	SBC 	R17,R22
	SBC 	R18,R23
	SEC
	RJMP 	DIV32F_4
DIV32F_3:
	CLC 					; 清除进位位
DIV32F_4:
	ADC 	R13,R13 		; 商左移一位并加上进位位
	ADC 	R14,R14
	ADC 	R15,R15
	ADD 	R16,R16 		; 余数左移一位
	ADC 	R17,R17
	ADC 	R18,R18
	DEC 	R26 			; R26-1
	BRNE 	DIV32F_2 		; 循环 24 次
	MOV 	R16,R13 		; 取出商
	MOV 	R17,R14
	MOV 	R18,R15
	LD 		R26,Y+ 			; 恢复R26
	RET
DIV32F: 					; 四字节浮点除法运算子程
	AND 	R24,R24
	BREQ 	DIV32F_7 		; 跳至DIV32F_7 出结果
	AND 	R19,R19 		; 判被除数是否为 0
	BREQ 	JGW0 			; 为 0 则结果为 0
	RCALL 	YCL 			; 调YCL 子程
	BREQ 	JGW0 			; 跳至JGW0 结果为 0
	EOR 	R20,R25 		; 取商的符号位存于R20
	SEC
	SBC 	R19,R24 		; 取出商的阶码
	BRVS 	JGZD 			; 溢出跳至JGZD
	LSR 	R23 			; 无溢出
	ROR 	R22 			; 将被除数与除数得尾数
	ROR 	R21 			; 右移一位最高位置 0
	LSR 	R18
	ROR 	R17
	ROR 	R16
	RCALL 	DIV32F_1 		; 调DIV32F_1 子程进行运算
	AND 	R18,R18 		; 判R18 最高位是否为 0
	BRMI 	DIV32F_5 		; 为 1
	ADD 	R16,R16 		; 为 0 左移被除数尾数
	ADC 	R17,R17
	ADC 	R18,R18
	SUBI 	R19,$01 		; 阶码减 1
	BRVS 	JGZD 			; 溢出 跳至JGZD
DIV32F_5: 					; 无溢出
	MOV 	R26,R16
	LSR 	R26
	BRCS 	DIV32F_6 		; 进位位为 1 跳至DIV32F_6
	AND 	R16,R16
	BRPL 	DIV32F_6 		; 为正跳至DIV32F_6
	AND 	R17,R17
	BRPL 	DIV32F_6 		; 为正跳至DIV32F_6
	LDI 	R26,$01 		; 尾数加 1
	ADD 	R16,R26
	CLR 	R26
	ADC 	R17,R26
	ADC 	R18,R26
DIV32F_6:
	RJMP 	GGH
DIV32F_7:
	RJMP 	JGW0
JGZD: 						; 结果置为 $7FFFFFFF
	LDI 	R26,$7F
	MOV 	R19,R26
	OR 		R18,R26
	LDI 	R26,$FF
	MOV 	R16,R26
	MOV 	R17,R26
	RET
JGW0: 						; 结果置为 $00000000
	CLR 	R16
	CLR 	R17
	CLR 	R18
	CLR 	R19
	CLR 	R20
	RET
MPY32F: 					; 四字节浮点乘法运算子程
	RCALL 	YCL 			; 调YCL 子程 并判乘数是否为 0
	BREQ 	JGW0 			; 被乘数为 0 跳至JGW0 结果为 0
	CPI 	R24,$80 		; 判乘数是否为 0
	BREQ 	JGW0 			; 乘数为 0 跳至JGW0 结果为 0
	EOR 	R20,R25 		; 符号位相异或
	SEC
	ADC 	R19,R24 		; 恢复阶码存于R19
	BRVS 	JGZD 			; 溢出跳至JGZD
	RCALL 	MPY32F_2 		; 无溢出调MPY32F_2 子程
	AND 	R18,R18 		; 判R18 最高位是否为 1
	BRMI 	MPY32F_1 		; 为负即R18 最高位为1 跳至MPY32F_1
	DEC 	R19 			; 为正即R18 最高位为 0 阶码减 1
	ADD 	R15,R15 		; 尾数左移一位
	ADC 	R16,R16
	ADC 	R17,R17
	ADC 	R18,R18 		; 直至R18 最高位为 1 止
MPY32F_1:
	SUBI 	R19,$FF 		; 阶码加 1
	BRVS 	JGZD 			; 溢出跳至JGZD
	RJMP 	GGH 			; 跳至GGH 出结果
MPY32F_2:
	ST 		-Y,R24 			; 转存R24
	CLR 	R13 			; 清R26 R15 R14 R13
	CLR 	R14
	CLR 	R15
	CLR 	R26
	LDI 	R24,$18 		; 令R24=$18 24
MPY32F_3:
	ADD 	R13,R13 		; 积的尾数在R18:R17:R16:R15:R14:R13
	ADC 	R14,R14
	ADC 	R15,R15
	ADC 	R16,R16 		; 尾数左移
	ADC 	R17,R17
	ADC 	R18,R18
	BRCC 	MPY32F_4 		; 无进位R24 减 1 不加乘数
	ADD 	R13,R21 		; 有进位R24 减 1 加乘数到尾数低位
	ADC 	R14,R22
	ADC 	R15,R23
	ADC 	R16,R26
	ADC 	R17,R26
	ADC 	R18,R26
MPY32F_4:
	DEC 	R24 			; 循环 24 次
	BRNE 	MPY32F_3
	LD 		R24,Y+ 			; 恢复R24
	RET 					; 取高 24 位
QUBU: 						; 取补运算
	COM 	R16
	COM 	R17
	COM 	R18
	COM 	R19
	SUBI 	R16,$FF
	SBCI 	R17,$FF
	SBCI 	R18,$FF
	SBCI 	R19,$FF
	RET

⌨️ 快捷键说明

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