微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 一种实用的单片机多字节除法程序

一种实用的单片机多字节除法程序

时间:08-04 来源:互联网 点击:

在单片机的实际应用中,除法运算是以比较常见的运算。

以MCS-51单片机为例,虽然提供了除法指令,但只能进行单字节的运算。如果要进行多字节的除法运算,就得自己设计算法。目前,许多资料上都介绍了四字节除以二字节的算法,但它们主要有以下几点不足:
1. 只能求出商,不能求出余数;
2. 在被除数高二字节大于除数时,不能进行运算;
3. 商只有两个字节。 例如,被除数是0FFFFFFFFH,除数是0004H时,商数应该是3FFFFFFFH,余数是0003H。
但是,用以前的算法是无法进行运算的。 在实际运用中,参与运算的数是任意的,有时需要求出余数,有时商数要求有四个字节,因此,以前的算法在实际应用中受到了很大的限制。 为了满足实际运用中的需要,有一套新的四字节除以二字节的算法,克服了上述算法中的缺点,可以适合广泛的实际需要。下面以MCS-51汇编语言为例进行说明。 该算法增加了两字节的余数单元,并把被除数单元用来存放商数。运算时,首先判断除数是否为零,若为零时,则设溢出标志为1,然后退出。若除数不为零,则采用移位相减法进行运算。
首先,把进位位和余数单元清零。再将进位位、余数单元和被除数单元按顺序首尾相连,逐位进行向左循环移位,共移位32次。每移位一次,余数单元都和除数作一次减法运算,若够减,余数单元内容更新为两者之差,并且将被除数最末一位置为1;若不够减,则余数单元内容保持不变,且将被除数最末一位置为0。判断是否够减的方法是:在作减法之前,先保存进位位,再看作完减法后的进位位。仅在作减法之前进位位为0,并且作减法之后进位位为1时判为不够减,其余情况均视为够减。这样,等到全部运算结束时,商数为四个字节,存放在被除数单元中;余数为两个字节,存放在余数单元中。
例如,被除数是0FFFFFFFFH,除数是0004H时,运行新的算法,商数是3FFFFFFFH,存放在被除数单元中,余数是0003H,存放在余数单元中。 这个算法自然、流畅,运算结果商数为四个字节,余数为两个字节,尤其是在求除以某数的N次方时,只需连续调用N次该算法子程序就可以了,省去了繁琐的数据转存语句。该算法还可以依实际需要扩充为位数更高的多字节除数算法,也可以移植到其它的单片机平台上。

本算法已在AT89C51单片机上调试通过。下面给出算法的程序代码清单。

divdll data  20h ;定义被除数单元divdlh data 21hdivdhl data 22hdlvdhh data 23hdivl data 24h ;定义除数单元divh data 25htempl data 26h ;定义余数单元temph data 27hdivd: push accpush bmov a,divdh ;判除数是否为零orl a,divljnz divd0setb ov ;除数为零,置溢出标志pop bpop accretdivd0: mov templ,#00h ;除数不为零,进行运算mov temph,#00hmov b,#20h ;置循环次数divd1:clr c ;进位位、余数单元和mov a,divdll ;被除数单元全体逐个rlc a ;向左循环移位mov divdll,amov a,divdlhrlc amov divdlh,amov a,divdhlrlc amov divdhl,amov a,divdhhrlc amov divdhh,amov a,templrlc amov templ,axch a,temphrlc axch a,temphmov f0,c ;保存进位位clr csubb a,divl ;用余数减去除数mov r7,amov a,temphsubb a,divh jc    divd2 mov templ,r7 ;够减,刷新余数单元mov temph,ainc divdll ;商上1divd2: djnz b,divd1clr ovpop bpop accretend对于上述算法,其思想是正确的。
但在DICE-51单片机仿真系统具体操作中还存在部分问题。
下面我以DICE系列的DICE-51单片机仿真系统软件为例,
给出四除三字节的算法的程序代码清单已在DICE-51单片机仿真系统软件调试通过。
首先,因为DICE-51单片机仿真系统软件在做除法运算时,若产生借位,不能置位,
所以要用CJNE比较指令进行置位运算。;定义被除数单元divDLL    EQU    40HdivDLH    EQU    41HdivDHL    EQU    42HdivDHH    EQU    43H;定义除数单元divDL     EQU    44HdivDM     EQU    45HdivDH     EQU    46H;定义余数单元TEMPL     EQU    50HTEMPM     EQU    51HTEMPH     EQU    52H;定义辅助单元FZ1       EQU    47HFZ2       EQU    48Hdiv0:  MOV   A,divDH             ;以下四行判断除数是否为零ORL   A,divDMORL   A,divDLJNZ   div1                      ;如果(A)不等于0,则跳转;否则顺序执行SETB  OV                       ;除数为零,置溢出标志位OV为1,程序结束SJMP  LOOP1div1: MOV   TEMPL,#00H         ;余数单元清零MOV   TEMPM,#00HMOV   TEMPH,#00H MOV   B,#20H                   ;置循环次数32次div2: CLR   C                              ;进位位清零MOV   A,divDLL       ;以下三行被除数最低字节左移一位(带进位)RLC   AMOV   divDLL,AMOV   A,divDLH      ;以下三行被除数低16位高字节左移一位(带进位)RLC   AMOV   divDLH,AMOV   A,divDHL      ;以下三行被除数高16位低字节左移一位(带进位)RLC   AMOV   divDHL,AMOV   A,divDHH       ;以下三行被除数最高字节左移一位(带进位)RLC   AMOV   divDHH,AMOV   A,TEMPL       ;以下三行余数低字节左移一位(带进位)                    RLC   AMOV   TEMPL,AMOV   A,TEMPM       ;以下三行余数中间字节左移一位(带进位)RLC   AMOV   TEMPM,AMOV   A,TEMPH       ;以下三行余数高字节左移一位(带进位)RLC   AMOV   TEMPH,AMOV   A,TEMPL       ;把余数最低字节送到累加器A中CLR   C                               SUBB  A,divDL        ;用余数减去除数MOV   R7,A            ;低字节相减结果送R7保存MOV   A,TEMPLCJNE  A,divDL,LP     ;通过比较运算实现因软件设计原因相减不能借位;而产生的借位LP1:   MOV   A,divDM                         ADDC  A,#00HMOV   FZ1,A         ;计算除数中间字节与低字节相减产生的进位位之和;将结果送FZ1保存MOV   A,TEMPMCJNE  A,FZ1,LP2      ;通过比较运算实现因软件设计原因相减不能借位;而产生的借位LP2:      PUSH  PSW            ;对程序状态字PSW压栈保护MOV   F0,C              ;将C的值送给F0保存CLR   CMOV   A,TEMPMSUBB  A,FZ1   MOV   R6,A            ;中间字节带进位相减结果送R6保存MOV   C,F0POP   PSW             ;程序状态字PSW弹栈,恢复现场MOV   A,divDHADDC  A,#00HMOV   FZ2,A       ;计算除数高字节与中间字节相减产生的进位位之和;将结果送FZ2保存MOV   A,TEMPHCJNE  A,FZ2,LP3     ;通过比较运算实现因软件设计原因相减不能借位;而产生的借位LP3:      PUSH  PSW                     ;对程序状态字PSW压栈保护MOV   F0,CCLR   CMOV   A,TEMPHSUBB  A,FZ2                       ;高字节带进位相减结果送R5保存MOV   R5,AMOV   C,F0POP   PSW                          ;程序状态字PSW弹栈,恢复现场JC    div3                  ;不够减,则跳转到div3div4:    MOV   TEMPL,R7             ;够减,刷新余数单元                       MOV   TEMPM,R6MOV   TEMPH,R5MOV   R0,#divDLL               ;够减,将被除数最低位置1MOV   A,@R0INC   AXCH   A,@R0div3:  DJNZ  B,div2      ;判断B是否为零,若为零,循环结束;否则,跳转继续循环CLR   F0LOOP1:NOPRET

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top