《汇编语言第三版》王爽学习历程——实验10(2)

本文介绍了如何使用汇编语言编写子程序divdw,解决16位和32位除法可能产生的溢出问题。子程序接受32位被除数和16位除数,返回32位商和16位余数。通过分析高位和低位除法,确保不产生溢出。文中还提供了测试案例及其调试结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

新人自己分析的,希望大神给予意见~!

问题阐述:
前面讲过,div指令可以做除法。当进行8位除法的时候,用al存储结果的商,ah存储结果的余数;进行16位除法的时候,用ax存储结果的商,dx存储结果的余数。可是,现在有一个问题,如果结果大于al或ax所能存储的最大值,该怎么办?
当CPU执行div等除法指令的时候,如果发生这样的情况,将引发CPU的一个内部错误,这个错误被称为:除法溢出。
需要编写一个子程序divdw解决上述问题。

子程序的描述
名称:divdw
功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
参数:(ax)=dword型数据的低16位,(dx)=dword型数据的高16位,(cx)=除数
返回:(dx)=结果的高16位, (ax)=结果的低16位,(cx)=余数
应用举例:计算1000000/10(F4240H/0AH)

mov ax, 4240h
mov dx, 000fh
mov cx, 0ah
call divdw

结果:(dx)=0001H,(ax)=86A0H,(cx)=0

分析
根据本书提供的公式,以10进制数来作简要分析:
以42÷2为例,42有两部分,一部分为高位4,另一部分为低位2
其中4=(42/10)取整,2=(42/10)取余
分别用4÷2,2÷2得到2和1,分别保存在存储商的高位的寄存器A和存储商的低位的寄存器B(假设A,B两个寄存器只能存一位数字),结果就由(A)×10+(B) = 2×10+1=21

42这个数是一个好处理情况,因为不涉及到高位除以2后会产生余数。
若是52÷2,由于高位5÷2除不尽,除了商以外还有余数1,若直接和上面一样用2÷2,那么结果就会变成21,和42÷2一样,如果这个回答出现在考卷上,那么一定会被扣分的。说明这个余数是不能被舍弃的,根据公式,可以知道商的低位是由
(余数×10+被除数低位)÷除数得到,这里就是(1×10+2)÷2=6,那最后的商为26,这也很符合我们除法的规则,可以用除式试验看看。

16进制也是如此,如FFFF FFFF这个被除数来说,这个数是有FFFF0000+FFFF得到
即FFFF*10000H(十进制65536)+FFFF得到,相应的商的高位就是(高位FFFF÷n)取整,商的低位就是[(高位FFFF÷n)取余+低位FFFF]÷n得到,那么结果最后需要组合一下即高位×10000H+低位得到也就是公式所说的:
X/n=int(H/n)×65536+[rem(H/n)*65536+L]/n

当然附页5还从数学角度利用了等量代换和不等式的性质证明了高位、低位分别除n,一定不会产生溢出,这个比较简单,也和写这个程序没太大关系就不多说了。

寄存器分析:
可以知道,这个程序是有两个参数的,分别用三个寄存器来传递的,在子程序中,需要用到另一个寄存器来保存中间结果,所以需要在调用后保存该寄存器数据。

汇编代码:

assume cs:codesg

stacksg segment
    dw 8 dup(0)
stacksg ends

codesg segment
 start:
    mov ax, stacksg
    mov ss, ax
    mov sp, 10h     ;栈的初始化

    mov ax, 4240h
    mov dx, 000fh
    mov cx, 0ah     ;参数的初始化
    call divdw

    mov ax, 4c00h
    int 21h

 divdw:
    push bx         ;之后需要用到,先保存
    push ax         ;首先计算高位,低位入栈        

    mov ax, dx
    mov dx, 0
    div cx          ;此时,ax保存高位运算后产生的商,dx保存高位运算后产生的余数

    mov bx, ax      ;高位运算后产生的商临时在bx中保存
    pop ax          ;此时,dx和ax保存了余*10000H+L
    div cx

    mov cx, dx      ;cx中保存最终结果的余数
    mov dx, bx      ;dx中保存高位运算后产生的商

    pop bx
    ret

codesg ends

end start

测试1:
计算:1000000/10(F4240H/0AH) 商:100000(186A0H) 余数:0
调试结果:
这里写图片描述

测试2:
计算:1000020/11(F4254H/0BH) 商:90910(1631EH) 余数:10(0AH)
调试结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值