第10章的实验二的问题:这类溢出问题总结起来就是说如果除法的商太大(寄存器溢出),应该如何解决?我在网上各地收集了众家高手的只言片语,如下:
1.如何判断溢出:
如果被除数高位的数值比除数大,那么会产生溢出。比如dx:0010H,ax:2343H,除数cx:0004H,dx>cx,会产生溢出。
2.公式理解:
解决此类溢出王爽的书中提到的公式是 X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N
在汇编中,我们的寄存器是16位的,当我们的除数是16位的时候,我们的除法的被除数就会默认为是32位的,高位在dx中(公式中的H),低位在ax中(公室中的L)。 由于我们在计算过程中,如果被除数过大,而除数过小,比如dx=00ffH,ax=ffffH,而除数为cx=1,这样,我们计算除法的时候,商的值就超出了存放的寄存器的最大值ffffH,溢出了。我们就无法得到正确的商。所以,我们换了一中计算角度,我们把高位和低位分开来进行除法计算,我们先保存ax中的值,然后把dx放入ax中,dx置0,这样,我们进行出发操作,商的值就不会超过FFFFH,不会溢出,我们就能得到dx这个高位数据计算的商和余数,假设商为a,余数为b,但是,我们得到的这个商是用dx计算出来的,dx中的1代表的是1*65536,所以a应该代表的数值是a*65536,而余数b代表的数值应该是b*65536,然后我们再把之前保存的ax中的值放回到ax中,然后加上b*65536H,再次进行除法计算,得到新的商,假设为c和余数x,此时余数x没有什么意义了,因为我们只要的是商。最后,我们就得出了dx=*H,ax=*H,除数为cx=*的商了。(刺猬注:最后的余数x是保存在cx,作者说x没意义,不知为何)
说明:
1.X/N:求x除以N的商
2.int(H/N):高位除以N的商
3.65536:高位和低位的进制
4.rem(H/N):高位除以N的余数
5.rem(H/N)*65536+L:高位和低位相加
6.+[rem(H/N)*65536+L]/N:再次求商
其实我们熟悉的10进制的计算方式,也是符合这个公式的。
3.代码
Divdw:
push bx ;子程序用到的寄存器入栈
push ax ;被除数的低16位入栈
mov ax,dx
mov dx,0
div cx ;先用被除数的高16位除以除数
mov bx,ax ;将int(H/N)存储到bx中,rem(H/N)自动存储到dx
pop ax ;被除数的低16位出栈
div cx ;用被除数的低16位除以除数
mov cx,dx ;将余数存储到cx
mov dx,bx ;将商的高16位存储到dx,商的低16位自动存储到ax
pop bx ;子程序用到的寄存器出栈
ret