. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->CALL和RET指令
主题 : :  实验10   子程序2解决除法溢出问题      问题多多,请大虾指点!  [已解决] 回复[ 5次 ]   点击[ 404次 ]  
abcdwzxy
[帖 主] [ 发表时间:2009-05-18 21:05 ] 
荣誉值:0
信誉值:3
注册日期:2009-03-13 16:19
根据公式:    X/N=INT(H/N)*65536+[REM(H/N)*65536+L]/N
                H=INT(X/65536);L=REM(X/65536)

我的程序是这样的:
assume
  data segment
     dw 0000000
  data ends
  code segment
   start:mov ax,data
         mov ds,ax
         mov ax,4240H
         mov dx,000fH     '设置被除数'
         mov cx,0aH       '设置除数'
         call divdw
         mov ax,4c00H
         int 21H
         
    divdw:mov bx,65536
          div bx          '计算X/65536,AX中放商(既公式中的H),DX中放余数(既公式中的L)'
          mov ds:[0],ax   '将H放在DS:[0]内存单元'
          mov ds:[2],dx   '将L放在DS:[2]内存单元'

          mov dx,0        '设置被除数,DX=0 高16位,AX低16位为H'
          div cx          '计算H/N,除数在CX中,计算后AX中为H/N的商,DX中为H/N的余数'
          
          mov ds:[4],ax   '将H/N的商放在DS:[4]内存单元'
          mov ds:[6],dx   '将H/N的余数放在DS:[6]内存单元'

          mul bx          '计算INT(H/N)*65536,结果的高16位放在DX中,低16位放在AX中'
  
          mov ds:[8],dx   '将INT(H/N)*65536结果的高16位放在DS:[8]内存单元'
          mov ds:[a],ax   '将INT(H/N)*65536结果的低16位放在DS:[A]内存单元'

          mov ax,ds:[6]   '将DS:[6]内存单元中的H/N的余数取出放在AX中'

          mul bx          '计算REM(H/N)*65536,结果的高16位放在DX中,低16位放在AX中'
 
          mov ds:[c],dx   '将REM(H/N)*65536结果的高16位放入DS:[C]内存单元'
          mov ds:[e],ax   '将REM(H/N)*65536结果的低16位放入DS:[E]内存单元'

          add ax,ds:[2]   '将REM(H/N)*65536与L相加,结果放在AX中'
          mov ds:[e],ax
           
          div cx          '计算[REM(H/N)*65536+L]/N'
 
          mov cx,dx       '结果的余数放入CX中'
          add ax,ds:[a]   'AX中放入结果的低16位'
          mov dx,ds:[8]   'DX中放入结果的高16位'
          ret
code ends
end start

这个程序我编译和连接都通过了,但是用DEBUG跟踪是会出现问题,得不到预想中的结果;
我分析了一下,在这个程序执行过中,
在  add ax,ds:[2]这条指令执行是参生了加法溢出,既REM(H/N)*65536与L相加后会参生溢出的情况(用DEBUG跟踪是看到的),但是附注的公式证明却证明了不会参生溢出情况;

还有一个问题是公式中的那个数65536  我觉得有点问题,65536刚好大于65535(FFFFH)既在BX中放不下;


请教各位该问题该如何解决啊  谢谢!!
zhenglxd
[第1楼] [ 回复时间:2009-05-21 13:51 ] 
荣誉值:30
信誉值:0
注册日期:2009-04-09 10:05
你这个可怜的babby
不要死套公式啦

不过这个东西解释起来超级麻烦。。。
我试着解释下!

防溢出关键 就是将一个会溢出的除法 分成若干个不会溢出的除法来做
就本题的范围防止的溢出 是防止寄存器的值超过寄存器限制
我们知道就本题的范围来说 什么样的情况会溢出? 因为 除数的范围是 1~ffff 而被除数的范围是
无限的 如果除数过小 比如=1 而被除法=1百万 那么自然会溢出了,不仅是被除数溢出而且也是结果溢出
那么怎么让他不溢出呢?将一个会溢出的除法 编程多次不会溢出的除法来做

1百万/1 = 50万/1+50万/1=10万/1*10。。。 依次类退

这个仅仅是思路在汇编中 具体就是 不同的被除数位数和除数分别除法

高位被除数 和除数如果有商 那么这个结果 一定是除法的最终结果的高位(将商保存)
如果没有那么必定会有余数,余数就被作为低位被除数的高为然后在进行除法
得出的结果加上最高为的商 就是最终结果
实际上对于一个非常大的数字高位来说 如果他和被除数有商 那么这个商 只能放在结果的高位中,(因为转换到低位的话 16位寄存器会放不下) 不管这个结果是几,他反正是最终的结果的最高位
而他如果有余数那么余数肯定不能丢弃啊 所以余数作为 低位数的高位来进行除法
#######################################################
就好比 10万零1 除以 10    我的寄存器只能存放 10万怎么办? 因为被除数超过寄存器所以
高位为 0001 低位为0

做除法时候 1/10 余下1 那么最终最高位结果为0 余下的1 跑到低位的除法高位数中
这样就成了一个普通的 16位被除数除法了
此问题已结贴!
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved