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

📄 16位乘除法.asm

📁 PIC16位乘除法
💻 ASM
📖 第 1 页 / 共 5 页
字号:







4.2  3字节浮点数转换为定点整数
子程序的转换结果将采用补码表示。其转换数值范围:-32768~32767,入口条件和出口条件如下:
入口条件:ACCBHI、ACCBLO、EXPB
出口条件:ACCBHI、ACCBLO
    以下为子程序的清单。由于程序所需调用的子程序和所需通用寄存器单元地址和定点数转换为浮点数子程序相同,在此省略。使用时,将前面介绍的子程序拷入此处即可。
FtoD    CLRF         SIGN            ;清结果符号寄存器
    MOVF         ACCBHI,0
    BTFSS         ACCBHI,7    ;被转换数是否为负?
    GOTO         D1
    BSF             SIGN,7        ;是,SIGN.7置1
    CALL         NEG_B        ;被转换数取补
D1    BTFSS         EXPB,7        ;被转换数为正,再判阶码为负否?
    GOTO         D2
    CLRF         ACCBHI        ;为负,被转换数小于1,无法用定点数表示
    CLRF         ACCBLO
    RETLW         0
D2    MOVLW         .16            ;被转换数阶码减16(十进制数)
    SUBWF         EXPB,0
    BTFSS         STATUS,C    ;阶码小于16?
    GOTO         D3
        MOVLW         0XFF            ;阶码大于等于16,置ACCB为最大,返回
    MOVWF         ACCBHI
    MOVWF         ACCBLO
    RETLW         01
D3    CALL         FTOW3        ;调用子程序将浮点数转换为定点数
    BTFSC         SIGN,7        ;定点数为负?
    CALL         NEG_B        ;是,取补
    RETLW         0            ;否,返回
;****************************************
FTOW3    MOVLW         .15            ;EXPB=15(十进制数)?
    SUBWF         EXPB,0
    BTFSC         STATUS,Z
    RETLW         0            ;是,返回
    BCF             STATUS,C    ;否,ACCB继续右移,EXPB加1
    RRF             ACCBHI
    RRF             ACCBLO
    INCF         EXPB
    GOTO         FTOW3        ;重新判断EXPB=15?
【校验举例1】 19531(十进制)
化为十六进制数:4C4B0FH 
结果:4C4BH
【校验举例2】 2622(十进制)
化为十六进制数:51F00CH
结果:0A3EH
【例程】
MAIN        MOVLW        0X4B        ;被转换数4C4BH送ACCB
    MOVWF        ACCBLO
    MOVLW        0X4C
    MOVWF        ACCBHI
    MOVLW        0X0F
    MOVWF        EXPB
        CALL        FtoD            ;调用定点数至浮点数转换子程序
    END
 5  码制转换程序设计
 5.1   双字节定点数至5位BCD码转换程序
    入口条件:ACCBHI、ACCBLO
    出口条件:ACCCHI低半字节、ACCCLO、ACCDHI
以下为双字节定点数至5位BCD码转换程序清单。
    LIST            p=16f877
    INCLUDE        p16f877.inc
    ACCBLO         EQU     23        ;存放被转换的双字节整数低8位
    ACCBHI         EQU     24        ;存放被转换的双字节整数高8位
    ACCCLO         EQU     26        ;存放5位BCD码
    ACCCHI         EQU     27
    ACCDLO         EQU     28
    ACCDHI         EQU     29
    TEMP         EQU     2A        ;临时寄存器
    SIGN         EQU     2B        ;被转换数符号寄存器
    ORG            0X0000
START    GOTO        MAIN
    ORG            0X0100
;**********双字节数至BCD码子程序************
BtoBCD    CLRF        SIGN            ;初始化符号寄存器
    BTFSS        ACCBHI,7    ;被转换数为负?
    GOTO        LOOP1        ;否,转BtoBCD
    BSF            SIGN,7        ;是,存符号
    CALL        NEG_B        ;ACCB取补
LOOP1    BCF             STATUS,C    ;清进位位
    MOVLW         .16            ;移位计数器赋初值
    MOVWF         COUNT
    CLRF         ACCCHI        ;初始化出口寄存器
    CLRF         ACCCLO
    CLRF         ACCDHI
LOOP16    RLF             ACCBLO        ;ACCB左移一位至出口寄存器
    RLF             ACCBHI
    RLF             ACCDHI
    RLF             ACCCLO
    RLF             ACCCHI
    DECFSZ         COUNT         ;移位计数器=0?
    GOTO         ADJDEC        ;否,转ADJDEC
    RETLW         0            ;是,返回
ADJDEC    MOVLW         ACCDHI        ;指针指向ACCDHI
    MOVWF         FSR
    CALL         ADJBCD        ;调用BCD码校正子程序
    MOVLW         ACCCLO        ;指针指向ACCCLO
    MOVWF         FSR
    CALL         ADJBCD        ;调用BCD码校正子程序    
    MOVLW         ACCCHI        ;指针指向ACCCHI
    MOVWF         FSR
    CALL         ADJBCD        ;调用BCD码校正子程序
    GOTO         LOOP16        ;ACCB重新左移
;************* BCD码校正子程序**************
ADJBCD     MOVLW         00X03        ;LSD+3>7?
    ADDWF         INDF,0
    MOVWF         TEMP
    BTFSC         TEMP,3
    MOVWF         INDF         ;是,LSD=LSD+3
    MOVLW         0X30            ;否,MSD+3>7?
    ADDWF         INDF,0
    MOVWF         TEMP
    BTFSC         TEMP,7
    MOVWF         INDF            ;是,MSD=MSD+3
    RETLW         0            ;返回
【校验举例1】 -23808(十进制)
化为十六进制数:A300
结果:023808(BCD),SIGN=80
【校验举例2】 12306(十进制)
化为十六进制数: 3012
结果:012306(BCD),SIGN=00
【例程】
MAIN        MOVLW        0X00            ;双字节整数送ACCB
    MOVWF        ACCBLO
    MOVLW        0XA3
    MOVWF        ACCBHI
    CALL        BtoBCD        ;调子程序,将二进制数转换成BCD码
    END
 
 5.2  3字节浮点数至5位压缩BCD码转换程序
 
图2.6  浮点数至5位压缩BCD码转换程序
程序通过3个步骤将一个3字节浮点数转换成5位压缩BCD码(压缩BCD码是指将两个BCD码分别存放在一个8位字节的高半字节和低半字节中)。首先,判断浮点数的符号,如果是负数,存符号位,并将之取补。其次,调用浮点数乘法或除法子程序,对浮点数进行连续的乘以10或除以10的操作,把浮点的阶码控制在+12≤EXPB<+16之间,即使得浮点数转换成定点数后,数值在4095(FFFH)和32767(7FFFH)之间。再次,调用浮点数至定点数子程序,将浮点数转换成双字节定点数。最后,调用定点数至BCD码子程序,将双字节无符号数转换成5位压缩BCD码,从而完成浮点数至压缩BCD码的转换。此外,乘以10或除以10的次数可以用来确定小数点的位置。在子程序中,乘以10或除以10的次数分别存在C_MUL和C_DIV单元中,但二者不可能同时大于0(二者不可能同时小于0,但可以同时等于0)。其中,当C_MUL>0时(此时,C_DIV必然等于0),表示小数点从BCD码的最后往前移动C_MUL位;当C_DIV>0时(此时,C_MUL必为0),表示小数点由BCD码的最后往后移动C_DIV位。转换后的BCD码的符号存于FPOL单元的第7位。
在该子程序中要调用大量的子程序,如浮点数乘法子程序、浮点数除法子程序、浮点数至定点数转换子程序和定点数至BCD码转换子程序等。在此由于篇幅的原因都予以省略,需要这些子程序的读者,请参阅前面相关章节。
浮点数至压缩BCD码转换程序的入口条件和出口条件如下:
入口条件:ACCBHI、ACCBLO、EXPB
出口条件:5位压缩BCD码存于ACCCHI低半字节、ACCCLO和ACCDHI中,符号保存于FPOL寄存器的第7位,小数点位置存于C_MUL和C_DIV中。
以下为本子程序的程序清单。

    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        ;临时寄存器
    SIGN         EQU     2B        ;临时寄存器
    COUNT         EQU     2F        ;临时寄存器
    C_MUL         EQU     2C        ;存放小数点位置
    C_DIV         EQU     2D        ;存放小数点位置
    FPOL         EQU     2E        ;存放被转换数的符号
    ORG            0X0000
START    GOTO        MAIN
    ORG            0X0100
;*************浮点数到BCD码子程序****************
FtoBCD    CLRF         C_MUL        ;清小数点位数寄存器
    CLRF         C_DIV
    CLRF         ACCAHI        ;求取结果符号,存于FPOL.7
    CALL         S_SIGN
    MOVF         SIGN ,0
    MOVWF        FPOL
    MOVLW         50            ;ACCA赋初值,ACCA=10(十进制)
    MOVWF         ACCAHI
    CLRF         ACCALO
    MOVLW         04
    MOVWF         EXPA
MUl5    BTFSS        EXPB,7        ;阶码EXPB<0?
    GOTO        MUl2        ;否,转MU12
MUl1    CALL         F_mpy        ;是,ACCA×10
    INCF         C_MUL        ;小数点左移寄存器加1
    GOTO         MUl5        ;重新判断阶码是否小于零
MUl2    MOVLW         .12            ;阶码EXPB<12?
    SUBWF         EXPB,0
    BTFSC         STATUS,C
    GOTO         MUl4        ;否,转MU14
MUl3    CALL         F_mpy        ;是,ACCA×10
    INCF         C_MUL        ;小数点左移寄存器加1
    GOTO         MUL2        ;重判阶码值
MUl4    MOVLW         .16            ;阶码EXPB>16?
    SUBWF         EXPB,0
    BTFSS        STATUS,C
    GOTO         NEXT        ;否,表示阶码12≤EXPB<16,求取BCD码值
DIV1    CALL         FDIV            ;是,EXPB÷10
    INCF         C_DIV        ;小数点右移寄存器加1
    GOTO         MUl4        ;重新判断阶码值
NEXT    CALL         FTOW3        ;调子程序,将浮点数转换为定点数
    CALL         BtoBCD        ;调双字节数到BCD码子程序,求BCD码
    MOVF         ACCCHI        ;ACCCHI=0?
    BTFSS         STATUS,Z
    RETLW         0            ;否,返回
    MOVLW         04            ;是,结果左移4次,保证ACCCHI不为零
    MOVWF         TIMES
    BCF             STATUS,C
MUl6    RLF             ACCDHI
    RLF            ACCCLO
    RLF             ACCCHI
    DECFSZ         TIMES
    GOTO         MUl6
    MOVF         C_DIV        ;C_DIV=0?
    BTFSC         STATUS,Z
    GOTO         TEMUL        ;是,转判断C_MUL
    DECF         C_DIV        ;否,小数点右移寄存器减1
    RETLW         0
TEMUL    INCF         C_MUL        ;小数点左移寄存器加1
    RETLW         0    
【校验举例1】 -5.8125(十进制)
化为浮点数:A30003
结果:058120(BCD),C_MUL=4,C_DIV=0,FPOL=A3
【校验举例2】 0.00048881(十进制)
化为浮点数:4012F6
结果:048870(BCD),C_MUL=08,C_DIV=0,FPOL=40
【例程】
MAIN    MOVLW        0X00            ;将被转换数的尾数赋给ACCB
    MOVWF        ACCBLO
    MOVLW        0XA3
    MOVWF        ACCBHI
    MOVLW        0X03            ;将被转换数的阶码赋给EXPB
    MOVWF        EXPB
    CALL        FtoBCD        ;调用子程序开始转换
    END
 6  定点数开方子程序
    从数值计算方法可知,方程G(X)=0可以由牛顿迭代法来求解。牛顿迭代法的一个重要应用就是开平方,就是通过对以下方程求解得到M的平方根:
 
函数G(X)在X0点用一阶泰勒级数展开可得:
 
如果Y是方程G(X)=0的根,那么G(Y)=0,即:
 
忽略高阶项,而只取前两项,就可以得到根Y的近似值,即
 
把此方程写成离散形式的迭代方程为:
 
 
又因为: ,所以 ,代入迭代方程可得:
 
这里M的平方根初值取M/2。如果在此之前知道M的平方根的范围,则可以取一个比M/2更好的初值开始迭代,可以减少迭代的次数。
如果被开方数是定点数格式,代入的迭代初值也是定点数格式,并且用定点除法(定点数的除2操作可以由右移一位得到)和定点加法进行迭代运算,则就是定点数开方。
定点数开方只能得到结果的整数部分,如代入FFFFH和FF10H的开方结果都是一样的,为FFH。如果想要得到比较精确的结果,可以先对被开方数乘以一个系数,待得到结果后,再除以相应的系数。如果被开方数太大,则不能使用此法,若想得到比较精确的结果,可以采用后面介绍的“浮点数开方”。
以下为定点数开方的程序清单(其中包含校验程序部分)。该程序中包含定点数加法程序和定点数除法程序。

    LIST            p=16f877
    INCLUDE        p16f877.inc
;****************************************
;此子程序是求16位二进制数平方根的子程序,需要调用16/16位除法子程序和
;加法子程序,虽然前面有了,但标号有些不同,为了易于阅读和理解,也把它列在后面。
;入口条件:16位二进制数存放在NUMHI和NUMLO单元中。
;出口条件:8位二进制数存放在SQRTLO单元中。
;迭代次数由LUPCNT的地址值决定。
;用指令CALL        SQRT实现定点数开方程序调用
;****************************************
     ACCALO        EQU        0X20
    ACCAHI        EQU        ACCALO+1
    EXPA        EQU        ACCALO+2
    ACCBLO        EQU        ACCALO+3
    ACCBHI        EQU        ACCALO+4
    EXPB        EQU        ACCALO+5    
    ACCCLO        EQU        ACCALO+6
    ACCCHI        EQU        ACCALO+7
    ACCDLO        EQU        ACCALO+8
    ACCDHI        EQU        ACCALO+9
    TEMP        EQU        ACCDHI+1
    SIGN            EQU        ACCDHI+2
    SQRTLO        EQU        ACCALO
    SQRTHI        EQU        ACCAHI
    NUMLO        EQU        ACCDHI+4
    NUMHI        EQU        ACCDHI+5
    COUNT    EQU    ACCDHI+6    ;此方法定义的数据块为连续层断,只要
                ;将第一行改变,就可以将数据整块搬动到
                ;新的地方,为调试带来方便,是比较推
                ;崇的一种寄存器定义方法
    LUPCNT    EQU    .10    
;****************************************
        ORG            0X00
        GOTO        MAIN
        ORG            0X10
;****************************************
INIT        MOVLW        LUPCNT
    MOVWF        COUNT

⌨️ 快捷键说明

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