汇编语言实验10除法溢出问题

如果被除数高位的数值等于或大于除数,那么会产生溢出。

用十进制理解
假设有十制制的寄存器
被除数是两位的寄存器
除数是一位的寄存器
结果是一位的寄存器

高位低位
24
2
12

24除以2
24的高位为2,低位为4
除数等于2

被除数高位的数值等于除数 2=2
结果是12,有两位,溢出了,因为结果是一位的寄存器

高位低位
24
1
24

24除以1
24的高位为2,低位为4
除数等于1

被除数高位的数值大于除数 2>1
结果是24,有两位,溢出了,因为结果是一位的寄存器

高位低位
24
3
08

24除以3
24的高位为2,低位为4
除数等于3

被除数高位的数值小于除数 2<3
结果是08,只有一位,没有溢出,因为结果是一位的寄存器

结论:如果被除数高位的数值等于或大于除数,那么会产生溢出。

汇编语言实验10,解决除法溢出问题

思路:

  1. 高位与除数相除
  2. 低位与除数相除
  3. 然后再将结果相加

比如54除以3
54的高位为5,低位为4
除数等于3

第一步
5除以3

第一步
5
3
1

结果等于1,余数为2

第二步
余数*10 +低位4 = 形成一个新的数24
24再除以3

高位低位
24
3
08

结果等于8
并且,24除以3这个除法,不可能溢出,因为第一个除法得出的余数肯定小于除数,即2<3
第三步
第一步的结果1 * 10
加上第二步的结果
10 + 8 = 18
再多用一个寄存器放置18前面的1就行了,原本是只有一位的寄存器

这是十进制思路,将二位寄存器改成32位,将一位寄存器改成16位,将十进制改成2进制,是一模一样的
即32位被除数,如果被除数高16位大于或等于除数,结果必然溢出
于是分成高16位去做除法,得出商和余数
将余数乘以2^16=65536,再加上低16位,组成新的32位再做除法,得出商和余数(新的32位数不可能溢出)
将高16位商乘以2^16=65536加上低16位商,即得出结果
程序中只需要将高16位商放一个寄存器
低16位的商放一个寄存器
最终余数放一个寄存器

名称:divdw

;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。

;参数:(ax)=dword型数据的低16位;

;      (dx)=dword型数据的高16位;

;      (cx)=除数。

;返回:(dx)=结果的高16位;

;      (ax)=结果的低16位;

;      (cx)=余数。

divdw:

     push si
     

     push ax; 1. 先将低16位保存起来,等下AX要变成高16位的数字

     mov ax,dx;2. 将高16位数据放到低16位

     mov dx,0 3.高位置0   也就是本来数字是54,现在变成了05  
     ;前面3步即先保存54的4,然后将54的5放到4原来的位置,再将5原来位置变为0,即54现在变成05

     div cx        ;4. (第一次除法)

     mov si,ax;5. 第一次除法的商保存起来,因为下一个除法要用到dx和ax,此时余数在dx,不用变动

     pop ax 6.将低16位放置到AX,所以和余数dx组成了一个新的数字

     div cx        ;7.(第二次除法)
     
	
	;下面三步满足题目要求
     mov cx,dx     ;8.第二步除法后余数在DX,但题目要求余数入cx

     mov dx,si     ;9.将之前保存在si的高位商放在dx,也是题目要求

 	;10.题目要求低16位结果入AX,但第二次除法后,商本来就在AX,所以省略了这步了

     pop si

     ret

 

code ends

end start

原文公式:
X/N = int (H/N)*65536 +[rem(H/N) * 65536 +L] /N

int (H/N)*65536其实就是高16位除以N,取商 再乘以65536(十进制里十位除以除数,商乘以10 ,5/3=1余2 1*10=10)
[rem(H/N) * 65536 +L] /N高16位的除以N,取余,再乘以65536,再加上低16位除以N(十进制里十位除以除数,余数乘以10,再加上个位,然后除以除数 2*10+4=24 24/3 = 8)
两者相加(10+8=18)

54除以3
先5除以3,商得1,余数2
2乘以10再加4,等于24
24除以3等于8,余数为0
1乘以10等于10
10加8等于18
所以54除以3等于18,余数为0

二进制32位数除以16位除数
高16位除以除数,得高位商和高位余数
高位余数乘以2的16次方再加上低16位,等于一个新的32位数
新的32位数除以除数得到新商和新余数
高位商乘以2的16次方加上新商得到真正的商
新余数为真正的余数
所以X/N = int (H/N)*65536 +[rem(H/N) * 65536 +L] /N

  • 1
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值