您的位置:首页 > 其它

编写解决除法溢出问题的子程序

2012-02-22 02:30 330 查看
用div指令做除法,很可能出现除法溢出,如

mov bh,1

mov ax,1000

div bh

在8位除法中,结果的商为1000,很显然al中放不下。

同样16位除法也会出现这种情况。

现编写一个子程序来解决除法溢出问题,题目要求来自王爽著《汇编语言》。

子程序描述

名称:divdw

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

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

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

(cx)=除数

返回:(dx)=结果的高16位,(ax)=dword型结果的低16位,(cx)=余数

应用举例:计算1000000/10(F4240H/0AH)

结果应为:(dx)=001H,(ax)=86A0H,(cx)=0

解决除法溢出问题的核心思想是公式公式X/N = int(H/N)*65536+[rem(H/N)*65536+L]/N,该公式右边肯定不会导致溢出,关于推导请参考图书附注5

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

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

H是X高16位,L是X低16位,范围都是[0,FFFF]

int(),取商 ,rem()取余

assume cs:code
stack segment
db 16 dup (0)
stack ends
code segment
start: mov ax,stack
mov ss,ax
mov sp,16

mov ax,4240H   ;计算1000000/10 即F4240H/0AH
mov dx,000FH
mov cx,0AH

call  divdw

mov ax,4c00h
int 21h
divdw:
push ax   ;公式X/N = int(H/N)*65536+[rem(H/N)*65536+L]/N

mov ax,dx
mov dx,0
call func_div;计算H/N

push dx ;暂存rem(H/N)

call func_mul ;获取int(H/N)*65536,结果存放 在dx,ax中
pop bx ;获取 rem(H/N)
pop bp ;获取L

push dx ;暂存int(H/N)*65536结果高位
push ax ;暂存int(H/N)*65536低位

mov ax,bx
call func_mul ;计算rem(H/N)*65536

add ax,bp ;计算rem(H/N)*65536+L
adc dx,0    ;考虑可能存在的进位

call func_div ;计算[rem(H/N)*65536+L]/N

;获得int(H/N)*65536+[rem(H/N)*65536+L]/N的商
pop bp ;获取int(H/N)*65536结果低位

mov cx,dx ;将余数保存在cx中

pop dx ;获取int(H/N)*65536结果高位
add ax,bp
adc dx,0

ret

func_div: ;32位被除数,16位除数存在cx中,结果商存在ax中,余数存在dx中
div cx
ret

func_mul: ;与65536的乘积高位存放在dx,低位存放 在ax中
mov bx,0100H ;256*256=65536
mul bx       ;由于ax中不可能大于或等于FFH,积必小于65536,可判定在这一步乘后高位dx中为0
mul bx
ret

code ends
end start
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: