汇编语言中div运算如果被除数为32位,除数则为16位,被除数放在DX和AX中,商放在AX中,余数放在DX中。如果被除数为16位,除数则为8位,被除数放在AX中,商放在ah,余数放在al。

但会产生一个问题,那就是当除出来的商大于AX或者AH的时候,就会产生除法溢出的错误。例如1000/1,被除数可以放在16位的AX中,1可以放在8位的寄存器中,得到的商为1000,超过了AH能容纳的最大值,因此会造成除法溢出的问题。

王爽的书中提供一个公式,可以避免除法溢出的问题

子程序要求


名称:divdw
功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型
参数:(ax)=dword型数据的低16位
  (dx)=dword型数据的高16位
  (cx)=除数
返回:(ax)=商的低16位
  (dx)=商的高16位
  (cx)=余数

公式


X:被除数,范围:[0, FFFFFFFF]

N:除数,范围:[0, FFFF]

H:X高16位,范围:[0, FFFF]

L:X低16位,范围:[0, FFFF]

int():描述性运算符,取商,比如,int(38/10)=3

rem():描述性运算符,取余数,比如,rem(38/10)=8

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

分析


首先来看看公式中的65536,很多新手的话可能不能理解这个65536是什么意思,其实65536就是10000H,相当于2^16,也就是说是乘以2^16,意思就是左移16位。

式中int(H/N)和rem(H/N)代表着X的高16位的商和余数。

等式右边的int(H/N)*65536表示将H/N的商作为最终结果商的高位字。

rem(H/N)*65536+L表示将H/N的余数左移16位,形成一个新的dword数据的高16位,L作为低16位。

最后的结果是DX中存放int(H/N)的结果,AX中存放(rem(H/N)*65536+L)/N的商,CX中存放(rem(H/N)*65536+L)/N的余数。

子程序


  ;子程序描述
  ;名称: divdw
  ;功能: 进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型.
  ;参数: (dx)=dword型数据的高16位 (ax)=dword型数据的低16位 (cx)=除数
  ;返回: (dx)=结果的高16位 (ax)=结果的低16位        (cx)=余数
  ;应用举例: 计算1000000/10(F4240H/0AH) 
  divdw:
    push ax ;被除数的低16位入栈
    mov ax,dx
    mov dx,0
    mov cx,10
    div cx  ;得到的结果商放在AX中,余数放在DX中
    mov cx,ax;暂时保存商
    pop ax  ;取出低16位的值
    push cx ;保存商入栈
   
    mov cx,10
    div cx
   
    mov cx,dx   ;余数放入cx中
    pop dx  ;商的高16位存入dx中,ax中的结果就为商的低16位

  ret

posted on 2013-03-19 11:38  曾经的你|  阅读(2557)  评论(0编辑  收藏  举报