汇编语言实验十除法溢出

时间:2022-04-13 01:10:28

2.解决除法溢出的问题

前面讲过,div指令可以做除法。当进行8位除法的时候,用al存储结果的商,ah存储结果的余数;进行16位除法的时候,用ax才能出结果的商,dx存储结果的余数,可是,现在有一个问题,如果结果的商大于alax所能存储的最大值,那么将如何?

比如下面的程序段:

Mov bh,1

Mov ax,1000

Div bh

进行的是8位除法,结果的商为1000,而1000al中放不下。

又比如,下面的程序段:

Mov ax,1000h

Mov dx,1

Mov bx,1

Div bx

进行的是16位除法,结果的商为11000h,而11000hal中放不下。

          我们在用div的指令做除法时,很可能会发生上面的情况:结果商过大,超出了寄存器所能存储的范围。当cpu执行div等除法指令的时候,如果发生这样的情况,将引发cpu内部的一个错误,这个错误被称为:除法溢出。我们可以通过特殊的程序来处理这个错误,但在这里我们不讨论这个错误的处理,这是后面的程序所涉及到的内容。下面我们仅仅来看一下除法溢出时发生的一些现象,如图

 

图中展示了在windows 2000中使用Debug执行相关程序段的结果,div指令引发了cpu的除法溢出,系统对其进行了相关的处理。

好了,我们已经清楚了问题的所在:用div指令做除法的时候可能会产生除法溢出。由于有这样的问题,在进行除法运算的时候要注意除数和被除数的值,比如1000000/10就不能用div指令来计算。那么怎么办呢?我们用下面的子程序divdw解决。

子程序描述

名称:divdw

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

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

    dx=dword型数据的高16

cx=除数

返回:(dx=结果的高16位,ax=结果的低16

cx=余数

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

        Movax,4240h

        Movdx,000fh

        Movcx,0ah

        Calldivdw

        结果:dx=0001hax=86a0hcx=0

        提示

给出一个公式:

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

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

H:X16位,范围:[0ffff]

L:X16位,范围:[0ffff]

Int():描述性运算符,取商,比如,int38/10=10

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

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

实验清单:

assume cs:code,ss:stack

stack segment

        dw8 dup (0)

stack ends

code segment

        start:movax,4240h

                   mov dx,000fh

                   mov cx,0ah

                   call divdw

                   mov ax,4c00h

                   int 21h

        divdw:movbx,ax

                   mov ax,dx

                   mov dx,0

                   div cx     ;商将放在ax中,余数将放在dx

                   push ax    ;将商先压入栈

                   mov ax,bx

                   div cx     ;计算低16位的商

                   mov cx,dx

                   pop dx

                   ret

code ends

end start

实验结果:

汇编语言实验十除法溢出