解决除法溢出问题

王爽汇编语言第二版实验10.2

 

 


一、实验要求

      当用div指令进行8位除法运算时结果大于8位,或进行16位除法运算结果大于16位时,会出现除法溢出的错误。要求编写一个子程序,实现支持结果不会出现溢出的除法运算

 

 


二、算法概述

      通过一个公式将可能产生溢出的运算X/N,转变为多个不会产生溢出的除法运算。公式中,等号右边的所有除法运算都可以用div指令来实现,并且不会产生除法溢出

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

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

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

H:X的高16位

L:X的低16位

int():描述性运算符,取商

ram():描述性运算符,取余数

 

 


三、程序接口

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

 

 


四、实现代码

divdw:  ;子程序定义开始

       push bx

      

       push ax

       mov ax,dx

       mov dx,0

       div cx

       mov bx,ax

       pop ax

       div cx

       mov cx,dx

       mov dx,bx

 

       pop bx

       ret

 

 

 


 

五、测试代码

assume cs:codesg,ss:stacksg


stacksg segment


dw 8 dup (0)


stacksg ends


codesg segment
start:


 mov ax,stacksg
 mov ss,ax
 mov sp,16
 
 mov ax,4240h
 mov dx,000fh
 mov cx,0ah
 call divdw
 
 mov ax,4c00h
 int 21h

 

codesg ends

end start

 

 


六、测试结果

在执行后,测试除法命令的商为dx*16+ax,余数cx

 

### 8086 CPU 的 DIV 指令溢出错误及其解决方法 #### DIV 指令的工作原理 DIV 是 Intel 8086 处理器中的指令之一,用于执行无符号整数除法操作。该指令可以处理字节或字级别的数据。当使用字节级别数据时,它会将 AX 寄存器的内容视为被数,并将其以 AL 或 AH 中的一个值;对于字级运算,则 DX:AX 组合寄存器作为双精度被数,而单精度寄存器 CX 则存储数。 如果商的结果超出了目标寄存器能够表示的最大范围(即对于字节操作超出 255 或者对于字操作超出 65535),那么就会触发溢出中断[^4]。 #### 发生溢出的原因分析 在执行 `DIV` 指令期间可能会遇到两种类型的溢出情况: 1. **结果过大**:这是最常见的原因,指的是计算得到的商无法放入指定的目标寄存器中。例如,在字节模式下,如果尝试用一个小于等于 255 的数值去大于这个界限的大数,就可能造成这种情况。 2. **余数异常**:虽然理论上讲这不算是严格意义上的“溢出”,但如果剩余部分超过了允许的最大值也会引发类似的错误信号。不过通常来说,只要初始输入有效就不会轻易碰到这种情形。 #### 解决方案探讨 针对上述提到的各种潜在问题点,我们可以采取以下几种策略来规避或者妥善处理这些状况: - **预检查逻辑**: 在实际调用之前做一次简单的验证测试,确保即将参与运算的数据不会违反任何约束条件。比如可以通过比较大小关系提前判断是否存在风险并及时调整算法流程避免真正进入危险区域再继续下去。 - **扩展精度支持**: 如果应用程序确实需要频繁涉及较大规模数值之间的复杂算术活动的话,考虑引入更高层次的语言特性或者是专门设计好的库函数来进行替代实现可能是更好的办法。这样不仅可以简化底层硬件层面的操作难度同时也提高了整体系统的稳定性和可靠性水平。 - **捕获异常事件**: 对某些特定场合而言即使做了充分预防措施仍然难以完全杜绝意外的发生概率因此还需要具备一定的应急响应机制以便快速恢复正常的业务运转状态而不至于因为某个局部的小故障而导致全局瘫痪的局面出现。具体做法上可以在程序启动之初设置好相应的陷阱向量地址使得一旦检测到非法访问请求就能立刻跳转过去执行预定义好的一系列动作序列直至恢复正常为止[^5]. ```assembly mov ax, dividend_high_part ; Load high part of dividend into AX. xor dx, dx ; Clear DX register for division operation. cmp divisor, 0 ; Check whether the divisor is zero or not. je divide_by_zero_handler; Jump to handler if it's zero. idiv divisor ; Perform signed integer division now safely without fear! jmp continue_processing ; Continue with rest of code after successful divison. divide_by_zero_handler: call error_routine ; Call custom routine when encountering errors like dividing by zeros etc.. continue_processing: ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值