📄 16位乘除法.asm
字号:
CHEK_A BTFSC ACCAHI,7 ;ACCA为负?
CALL NEG_A ;ACCA为负,取补(NEG_A子程序请参见
;16×16位定点数乘法子程序NEG_A)
RETURN ;ACCA和ACCB均为负,返回
【校验举例1】 -23775÷(-240)=99.0625(十进制)
化为十六进制数:A321H÷FF10H;
结果:(商)0063H,(余数)000FH(十六进制)。
【校验举例2】 769÷3856=0.199429(十进制)
化为十六进制数:0301H÷0F10H;
结果:(商)0000H,(余数)0301H(十六进制)。
【例程】
MAIN MOVLW 0X01 ;被除数0301H送ACCB
MOVWF ACCBLO
MOVLW 0X03
MOVWF ACCBHI
MOVLW 0X10 ;除数0F10H送ACCA
MOVWF ACCALO
MOVLW 0X0F
MOVWF ACCAHI
CALL D_div ;调用双字节除法子程序,求商
END
3 3字节浮点四则运算子程序
3.1 浮点数加(减)法子程序
以下为浮点加(减)运算例程:
LIST p=16f877
INCLUDE p16f877.inc
ACCALO EQU 20 ;存放加数或减数的尾数
ACCAHI EQU 21
EXPA EQU 22 ;存放加数或减数阶码
ACCBLO EQU 23 ;存放被加数或被减数尾数以及和或差
ACCBHI EQU 24
EXPB EQU 25 ;存放被加数或被减数阶码
ACCCLO EQU 26 ;临时寄存器
ACCCHI EQU 27 ;临时寄存器
ACCDLO EQU 28 ;临时寄存器
ACCDHI EQU 29 ;临时寄存器
TEMP EQU 2A ;临时寄存器
TEMP1 EQU 30 ;临时寄存器
TIMES EQU 31 ;临时寄存器
ORG 0X000
START GOTO MAIN
ORG 0X0100
;**************浮点减法子程序****************
F_sub CALL NEG_A ;求ACCA的补码,将减法转换为补码加法
;***********浮点加法子程序**************
F_add CALL SUBADJ ;调子程序判断EXPB和EXPA的大小
BTFSC STATUS,Z ;参与运算的两个数阶码相等?
GOTO PADD ;是,求尾数的和
BTFSC STATUS,C ;EXPB>EXPA?
CALL F_swap ;是,ACCB与ACCA互换
MOVF EXPA,0 ;否,求取两者的差值
SUBWF EXPB
SCLOOP CALL SHFTSR ;ACCB右移规格化
INCFSZ EXPB ;EXPB=EXPA?
GOTO SCLOOP ;否,继续右移
MOVF EXPA,0 ;是,存和(差)的阶码
MOVWF EXPB
PADD MOVF ACCAHI,0 ;ACCAHI或ACCBHI
IORWF ACCBHI,0
MOVWF SIGN ;存于SIGN寄存器
MOVF ACCBHI,0 ;暂存ACCBHI
MOVWF EXPA
CALL D_add ;尾数相加
BTFSS SIGN,7 ;ACCA和ACCB有负数?
BTFSC ACCBHI,7 ;否,把和的最高位和次高位同时进位?
GOTO ADD2 ;否,转ADD2
BTFSS ACCAHI,7 ;ACCA为负吗?
GOTO ADD3 ;ACCA和ACCB不同时为负,转ADD3
BTFSS EXPA,7 ;是,ACCB为负吗?
GOTO ADD3
BSF STATUS,C ;ACCA和ACCB同为负,带负号右移
RRF ACCBHI
RRF ACCBLO
INCF EXPB
ADD3 CLRF ACCCHI ;和(差)规格化
CLRF ACCCLO
CALL F_norm
RETURN ;子程序返回
ADD2 BCF STATUS,C ;最高位次高位不同时进位,ACCB右移
INCF EXPB
GOTO SHFTR
SHFTSR BCF STATUS,C ;ACCB带符号右移子程序
BTFSC ACCBHI,7
BSF STATUS,C
SHFTR RRF ACCBHI
RRF ACCBLO
RETURN ;子程序返回
;********* ACCB、ACCA互换子程序************
F_swap MOVF ACCAHI,0 ;ACCAHI、ACCBHI互换
MOVWF TEMP
MOVF ACCBHI,0
MOVWF ACCAHI
MOVF TEMP,0
MOVWF ACCBHI
MOVF ACCALO,0 ;ACCALO、ACCBLO互换
MOVWF TEMP
MOVF ACCBLO,0
MOVWF ACCALO
MOVF TEMP,0
MOVWF ACCBLO
MOVF EXPA,0 ;EXPA、EXPB互换
MOVWF TEMP
MOVF EXPB,0
MOVWF EXPA
MOVF TEMP,0
MOVWF EXPB
RETURN
;*************比较EXPB、EXPA大小子程序*************
SUBADJ MOVF EXPA,0 ;EXPA异或EXPB,结果送C_DIV
XORWF EXPB,0
MOVWF C_DIV
MOVF EXPA,0 ;EXPB-EXPA
SUBWF EXPB,0
BTFSS C_DIV,7 ;EXPA和EXPB同号?
RETURN ;是,进位位的值真确反映两者的大小,返回
BTFSS STATUS,C ;否,进位位的值取反
GOTO CHANGEC
BCF STATUS,C
RETURN
CHANGEC BSF STATUS,C
RETURN
;***********浮点数规格化子程序****************
F_norm MOVF ACCBHI ;ACCB=0?
BTFSS STATUS,Z
GOTO C_norm
MOVF ACCBLO
BTFSC STATUS,Z
RETURN ;是,不需规格化,返回
C_norm BTFSC ACCBHI,7 ;否。ACCB为负?
GOTO C_norm2
C_norm1 BTFSC ACCBHI,6 ;为正。规格化完毕?
RETURN ;ACCBHI.6=1,规格化结束
CALL SHFTSL ;否。ACCB左移
DECF EXPB ;EXPB减1
GOTO C_norm1 ;重新判断规格化完毕否?
C_norm2 BTFSS ACCBHI,6 ;ACCB为负。规格化完毕否?
RETURN ;ACCBHI.6=0,规格化结束
BCF STATUS,C
CALL SHFTSL ;否,ACCB左移
BSF ACCBHI,7 ;加符号
DECF EXPB ;EXPB减1
GOTO C_norm2 ;重新判断规格化完毕否?
SHFTSL BCF STATUS ,C ;ACCB左移子程序
RLF ACCCLO
RLF ACCCHI
RLF ACCBLO
RLF ACCBHI
RETURN
【校验举例1】 0.0019531+(-0.00016594)=0.00178716
化为十六进制数:4000F8+A900F4
结果:7520F7
【校验举例2】 0.26222+3.5025=3.76478
化为十六进制数: 4321FF+701502
结果:787902
【例程】
MAIN MOVLW 0X21 ;被加数的尾数4321H送ACCB
MOVWF ACCBLO
MOVLW 0X43
MOVWF ACCBHI
MOVLW 0XFF ;被加数的阶码FFH送EXPB
MOVWF EXPB
MOVLW 0X15 ;加数尾数7015H送ACCA
MOVWF ACCALO
MOVLW 0X70
MOVWF ACCAHI
MOVLW 0X02 ;加数阶码送EXPA
MOVWF EXPA
CALL F_add ;调用浮点数加法子程序,求和
END
3.2 浮点数乘法子程序
以下为浮点数乘法的程序清单。
LIST p=16f877
INCLUDE p16f877.inc
ACCALO EQU 20 ;存放乘数尾数
ACCAHI EQU 21
EXPA EQU 22 ;存放乘数阶码
ACCBLO EQU 23 ;存放被乘数尾数和乘积高16位
ACCBHI EQU 24
EXPB EQU 25 ;存放被乘数阶码
ACCCLO EQU 26 ;存放乘积低16位
ACCCHI EQU 27
ACCDLO EQU 28 ;临时寄存器
ACCDHI EQU 29 ;临时寄存器
TEMP EQU 2A ;临时寄存器
TEMP1 EQU 30 ;临时寄存器
TIMES EQU 31 ;临时寄存器
SIGN EQU 2B ;存放乘积符号
COUNT EQU 2F ;临时寄存器
ACCEHI EQU 30 ;临时寄存器
ACCELO EQU 31 ;临时寄存器
ORG 0X0000
START GOTO MAIN
ORG 0X0100
;***浮点乘法子程序,入口地址(ACCB、EXPB)×(ACCA、EXPA),出口地址ACCB、EXPB ***
F_mpy CALL S_SIGN ;求取乘积的符号,并对负数取补
CALL SETUP ;调用子程序将ACCB的值送ACCD
CLRF ACCCHI ;清ACCC
CLRF ACCCLO
MLOOP BCF STATUS,C ;清进位位
RRF ACCDHI ;ACCD右移
RRF ACCDLO
BTFSC STATUS,C ;判断是否需要相加
CALL D_add ;加乘数至ACCB
BCF STATUS,C ;清进位位
RRF ACCBHI ;右移部分乘积
RRF ACCBLO
RRF ACCCHI
RRF ACCCLO
DECFSZ TEMP ;乘法完成否?
GOTO MLOOP ;否,继续循环
MOVF EXPA,0 ;是,乘数与被乘数阶码相加,得积的阶码
ADDWF EXPB
MOVF ACCBHI ;ACCBHI=0?
BTFSS STATUS,Z
GOTO FINUP ;否,转FINUP
MOVF ACCBLO ;ACCB=0?
BTFSS STATUS ,Z
GOTO SHFT08 ;否,只有ACCBHI=0,转SHFT08
MOVF ACCCHI,0 ;ACCB=0,将乘积左移15位
MOVWF ACCBHI
MOVF ACCCLO,0
MOVWF ACCBLO
BCF STATUS,C
RRF ACCBHI
RRF ACCBLO
MOVLW .15 ;乘积阶码减15(十进制数)
SUBWF EXPB
GOTO FINUP
SHFT08 MOVF ACCBLO,0 ;只有ACCBHI=0,乘积左移7位
MOVWF ACCBHI
MOVF ACCCHI,0
MOVWF ACCBLO
BCF STATUS,C
RRF ACCBHI
RRF ACCBLO
MOVLW .7 ;乘积阶码减7
SUBWF EXPB
FINUP CALL F_norm ;对乘积进行规格化
BTFSS SIGN,7 ;确定乘积的符号
GOTO OVER ;为正,乘法结束
COMF ACCCLO ;为负,乘积取补
INCF ACCCLO
BTFSC STATUS,Z
DECF ACCCHI
COMF ACCCHI
BTFSC STATUS,Z
NEG_B DECF ACCBLO
COMF ACCBLO
BTFSC STATUS,Z
DECF ACCBHI
COMF ACCBHI
OVER RETURN ;乘法结束,子程序返回
;********浮点乘除法运算确定结果符号子程序***********
S_SIGN MOVF ACCAHI,0 ;ACCAHI异或ACCBHI,结果送SIGN
XORWF ACCBHI,0
MOVWF SIGN
BTFSS ACCBHI,7 ;ACCB为负?
GOTO CHEK_A ;否,检查ACCA
COMF ACCBLO ;是,ACCB取补
INCF ACCBLO
BTFSC STATUS,Z
DECF ACCBHI
COMF ACCBHI
CHEK_A BTFSC ACCAHI,7 ;ACCA为负?
CALL NEG_A ;ACCA取补
RETURN ;返回
;*********浮点运算结果规格化子程序*************
F_norm MOVF ACCBHI ;ACCB=0?
BTFSS STATUS,Z
GOTO C_norm
MOVF ACCBLO
BTFSC STATUS,Z
RETURN ;是,不需规格化,返回
C_norm BTFSC ACCBHI,7 ;否。ACCB为负?
GOTO C_norm2
C_norm1 BTFSC ACCBHI,6 ;为正。规格化完毕?
RETURN ;ACCBHI.6=1,规格化结束
CALL SHFTSL ;否。ACCB左移
DECF EXPB ;EXPB减1
GOTO C_norm1 ;重新判断规格化完毕否?
C_norm2 BTFSS ACCBHI,6 ;ACCB为负。规格化完毕否?
RETURN ;ACCBHI.6=0,规格化结束
BCF STATUS,C
CALL SHFTSL ;否,ACCB左移
BSF ACCBHI,7 ;加符号
DECF EXPB ;EXPB减1
GOTO C_norm2 ;重新判断规格化完毕否?
SHFTSL BCF STATUS ,C ;ACCB左移子程序
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -