单片机4字节除法c语言,一种实用的单片机多字节除法程序

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

以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 21h

divdhl data 22h

dlvdhh data 23h

divl data 24h ;定义除数单元

divh data 25h

templ data 26h ;定义余数单元

temph data 27h

divd: push acc

push b

mov a,divdh ;判除数是否为零

orl a,divl

jnz divd0

setb ov ;除数为零,置溢出标志

pop b

pop acc

ret

divd0: mov templ,#00h ;除数不为零,进行运算

mov temph,#00h

mov b,#20h ;置循环次数

divd1:clr c ;进位位、余数单元和

mov a,divdll ;被除数单元全体逐个

rlc a ;向左循环移位

mov divdll,a

mov a,divdlh

rlc a

mov divdlh,a

mov a,divdhl

rlc a

mov divdhl,a

mov a,divdhh

rlc a

mov divdhh,a

mov a,templ

rlc a

mov templ,a

xch a,temph

rlc a

xch a,temph

mov f0,c ;保存进位位

clr c

subb a,divl ;用余数减去除数

mov r7,a

mov a,temph

subb a,divh

jc divd2

mov templ,r7 ;够减,刷新余数单元

mov temph,a

inc divdll ;商上1

divd2: djnz b,divd1

clr ov

pop b

pop acc

ret

end

对于上述算法,其思想是正确的。但在DICE-51单片机仿真系统具体操作中还存在部分问题。下面我以DICE系列的DICE-51单片机仿真系统软件为例,给出四除三字节的算法的程序代码清单已在DICE-51单片机仿真系统软件调试通过。首先,因为DICE-51单片机仿真系统软件在做除法运算时,若产生借位,不能置位,所以要用CJNE比较指令进行置位运算。

;定义被除数单元

DIVDLL EQU 40H

DIVDLH EQU 41H

DIVDHL EQU 42H

DIVDHH EQU 43H

;定义除数单元

DIVDL EQU 44H

DIVDM EQU 45H

DIVDH EQU 46H

;定义余数单元

TEMPL EQU 50H

TEMPM EQU 51H

TEMPH EQU 52H

;定义辅助单元

FZ1 EQU 47H

FZ2 EQU 48H

DIV0: MOV A,DIVDH ;以下四行判断除数是否为零

ORL A,DIVDM

ORL A,DIVDL

JNZ DIV1 ;如果(A)不等于0,则跳转;否则顺序执行

SETB OV ;除数为零,置溢出标志位OV为1,程序结束

SJMP LOOP1

DIV1: MOV TEMPL,#00H ;余数单元清零

MOV TEMPM,#00H

MOV TEMPH,#00H

MOV B,#20H ;置循环次数32次

DIV2: CLR C ;进位位清零

MOV A,DIVDLL ;以下三行被除数最低字节左移一位(带进位)

RLC A

MOV DIVDLL,A

MOV A,DIVDLH ;以下三行被除数低16位高字节左移一位(带进位)

RLC A

MOV DIVDLH,A

MOV A,DIVDHL ;以下三行被除数高16位低字节左移一位(带进位)

RLC A

MOV DIVDHL,A

MOV A,DIVDHH ;以下三行被除数最高字节左移一位(带进位)

RLC A

MOV DIVDHH,A

MOV A,TEMPL ;以下三行余数低字节左移一位(带进位)

RLC A

MOV TEMPL,A

MOV A,TEMPM ;以下三行余数中间字节左移一位(带进位)

RLC A

MOV TEMPM,A

MOV A,TEMPH ;以下三行余数高字节左移一位(带进位)

RLC A

MOV TEMPH,A

MOV A,TEMPL ;把余数最低字节送到累加器A中

CLR C

SUBB A,DIVDL ;用余数减去除数

MOV R7,A ;低字节相减结果送R7保存

MOV A,TEMPL

CJNE A,DIVDL,LP ;通过比较运算实现因软件设计原因相减不能借位

;而产生的借位

LP1: MOV A,DIVDM

ADDC A,#00H

MOV FZ1,A ;计算除数中间字节与低字节相减产生的进位位之和

;将结果送FZ1保存

MOV A,TEMPM

CJNE A,FZ1,LP2 ;通过比较运算实现因软件设计原因相减不能借位

;而产生的借位

LP2: PUSH PSW ;对程序状态字PSW压栈保护

MOV F0,C ;将C的值送给F0保存

CLR C

MOV A,TEMPM

SUBB A,FZ1

MOV R6,A ;中间字节带进位相减结果送R6保存

MOV C,F0

POP PSW ;程序状态字PSW弹栈,恢复现场

MOV A,DIVDH

ADDC A,#00H

MOV FZ2,A ;计算除数高字节与中间字节相减产生的进位位之和

;将结果送FZ2保存

MOV A,TEMPH

CJNE A,FZ2,LP3 ;通过比较运算实现因软件设计原因相减不能借位

;而产生的借位

LP3: PUSH PSW ;对程序状态字PSW压栈保护

MOV F0,C

CLR C

MOV A,TEMPH

SUBB A,FZ2 ;高字节带进位相减结果送R5保存

MOV R5,A

MOV C,F0

POP PSW ;程序状态字PSW弹栈,恢复现场

JC DIV3 ;不够减,则跳转到DIV3

DIV4: MOV TEMPL,R7 ;够减,刷新余数单元

MOV TEMPM,R6

MOV TEMPH,R5

MOV R0,#DIVDLL ;够减,将被除数最低位置1

MOV A,@R0

INC A

XCH A,@R0

DIV3: DJNZ B,DIV2 ;判断B是否为零,若为零,循环结束;否则,跳转继续循环

CLR F0

LOOP1:NOP

RET

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值