[047][汇编语言]实验10 2、解决除法溢出的除法

2、解决除法溢出的除法

题目描述

[047][汇编语言]实验10 2、解决除法溢出的除法_第1张图片
实验10 2、解决溢出的除法.png

算法依据:第二次除法不会产生溢出

  • 参考《汇编语言(第三版)》附注5


    [047][汇编语言]实验10 2、解决除法溢出的除法_第2张图片
    第二次除法不会产生溢出.png

实际输出

[047][汇编语言]实验10 2、解决除法溢出的除法_第3张图片
解决除法溢出的除法.png

完整源码

assume cs:code,ss:stack 
    stack segment
        dw 1 dup (0)
    stack ends  
    
    code segment
    start:  mov ax,4240H
            mov dx,000FH
            mov cx,0AH
            call divdw
            
            mov ax,4c00H
            int 21H
            
    divdw:  push ax 
            
            mov ax,dx
            mov dx,0
            div cx
            
            mov bx,ax
            pop ax
            div cx

            mov cx,dx
            mov dx,bx
            ret
            
        code ends
        end start

代码说明

[047][汇编语言]实验10 2、解决除法溢出的除法_第4张图片
汇编指令 寄存器 栈 内容变化

解题思路

  • 书上提示大家去看附注5,附注5推导了公式,其中对于解题最为有用的是这一句话 H/N产生的余数是绝对不能丢的
  • 如何计算 H/N?更准确地说通过 H/N 我们想得到什么?
我们的 div指令 只能处理
        32位 ÷ 16位
        16位÷ 8位
这两种形式的除法

CX=000AH 是16位
因此 H/N 得用 32位 ÷ 16位 来进行
H 表示的dd数据的高16位,本题中是 000FH
要拓展成一个32位的数据,也是要变成 0000 0000FH
从寄存器的角度上来说,就是要改写DX 以及 AX 寄存器
最终使得 
DX  |  AX
------------
0000 000F
相当于用这个新的 dd型的数据(0000 000FH)来进行除法运算

DX 寄存器 
在除法运算之前表示dd数据的高16位
在进行除法运算之后存着 余数
不同时期,角色不同

AX 寄存器
在除法运算之前表示dd数据的低16位
在进行除法运算之后存着 商
这个也是不同时期,角色不同
 
而对于 H/N
商,我们需要留下的,会出现最终结果里!
余数,我们也要!

除法运算结束之后,我们顺利得到了余数和商
DX  |  AX
------------
0005 0001
余数  商

这个商是最终商的高16位
我们使用BX寄存器保存起来,
这样DX、AX寄存器又可以拿来做除法运算了

  • 最终结果从何而来?
DX  |  AX
------------
0005 0001
余数  商

栈中在一开始保存的AX内容还原一下
并且,换一个角色角度看到DX与AX
这时候它是一个全新的dd型数据
DX  |  AX
------------
0005 4240
高位  低位

使用这个dd型数据,可以直接进行不溢出的除法
再一次得到一个余数(最终余数),以及一个商(最终商的低16位)
DX  |  AX
------------
0000 86A0
余数  商

把各个数据组合成题目需要的形式
用DX存高16位的最终商,从BX寄存器中取回来
用AX存低16位的最终商,不用变动了
用CX存最终余数,从DX寄存器中拿来


DX  |  AX
------------
0001 86A0
商高16位  商低16位

CX
-----
0000
余数
  • H/N 是本题的突破口
H 是32位dd型数据的高16位部分
H/N 的商,记为 a ,可以用 16位表示
H/N 的余数,记为 b,可以用 16位表示

H/N = a...b
a 也是最终的商的高16位
但是 b 不能省略,b结合L,相当于 b x FFFFH + L
FFFFH = 65536D

如附注5所证明的
b/n ≤ FFFFH - 1/n
不会产生进位,也就是不会产生溢出,可以直接用 32位÷16位进行除法

代码参考

  • div除法指令 https://www.jianshu.com/p/211cf4edd4d3

感想

算法中的数学部分,告诉并保证了我们这样做是正确的。然而,编程直到最后解决问题不仅仅是掌握数学就一步登天了,纵然我知道了什么才是对的,我也要知道如果才能做对,这就是做正确的事情(数学)和正确地做事之间的区别。要想知道自己做的事情是正确的,我需要学习数学。更大一部分,要正确地做事,我还需要知道汇编语言除法指令中寄存器的角色安排,我还需要思考解决这个问题本身的指令顺序安排,这大把东西一样既不简单(复杂)也不容易(困难)。海阔凭鱼跃、天高任鸟飞,世界大得很!

你可能感兴趣的:([047][汇编语言]实验10 2、解决除法溢出的除法)