问题描述
用div做除法的时候可能产生除法溢出。由于有这样的问题,在进行除法运算的时候要注意除数和被除数的值,比如1000000/10就不能用div指令来计算。那么怎么办?我们用下面的子程序divdw解决
实验效果
实验要求
子程序描述
名称:divdw
功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
参数:(ax)=dword型数据的低16位
(dx)=dword型数据的高16位
(cx)=除数
返回:(dx)=结果的高16位,(ax)=结果的低16位
(cx)=余数
数学公式说明
书上给出提示公式:X/N = int(H/N)*65536+[rem(H/N)*65536+L]/N,到底什么意思呢?刚开始博主也是一脸懵逼。
其实书上说了 int(H/N)表示取H/N的商,商用16位才能包的住,然后 int(H/N)*65536,并不是真正的将商*65536,65536=2^16,刚好表示将商往左移16位,H/N的商为X/N结果的高16位!
[rem(H/N)*65536+L]/N 又是什么意思呢?rem(H/N)表示H/N的余数,然后右移16位 将原数据的低16位放到低位,构成32位的被除数!由于int(H/N)*65536铁定是整数且没有余数为X/N结果的高16位,那么结果的低16位和余数就在[rem(H/N)*65536+L]/N 中产生!后半部分除法运算的结果作为X/N的低16位,余数作为X/N的余数。
实验代码
;实验10 问题2 解决除法溢出的问题
;用div做除法的时候可能产生除法溢出。由于有这样的问题,在进行除法运算的时候要注意除数和被除数的值
;比如1000000/10就不能用div指令来计算。那么怎么办?我们用下面的子程序divdw解决。
assume cs:code
code segment
start:
mov ax,4240h
mov dx,000fh
mov cx,0ah
call divdw
mov ax,4c00h
int 21h
;名称:divdw
;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; (cx)=除数
;返回:(dx)=结果的高16位,(ax)=结果的低16位
;(cx)=余数
;核心公式X/N = INT(H/N)*65536+[REM(H/N)*65536+L]/N
;X:被除数,N(cx):除数,H(dx):X的高16位,L(ax):X的低16位
divdw:
push bx ;寄存器不够用,将bx拿来用
push ax ;临时存放低16位(L)
;计算 INT(H/N)*65536 32位除16位,商16位存放在AX中 是整个X/N结果的高16位,余数16位在DX中 刚好作为 [REM(H/N)*65536+L]的高16位
mov ax,dx
mov dx,0
div cx
mov bx,ax ;不能直接放到dx中,后面还要用到dx
;计算 [REM(H/N)*65536+L]/N,商16位存放AX中 刚好作为X/N结果的低位,余数16位放DX中-> 放到CX中去
pop ax ;被除数低16位还原(L),刚好作为 [REM(H/N)*65536+L]的低16位
div cx
mov cx,dx ;余数16位放-> CX中去
mov dx,bx ;将结果高16位放->DX中去
pop bx ;还原bx
ret
code ends
end start