鱼C论坛

 找回密码
 立即注册
查看: 1767|回复: 0

[汇编作业] 汇编语言实验10第二个程序解题思路,欢迎交流

[复制链接]
发表于 2015-7-2 22:37:25 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
test10-2.bmp
如题。这个程序让我有种久违的数学课的感觉,泪流满面啊:cry
不废话,直接开始,题目中给出了公式:X/N = int(H/N) * 65536 + [rem(H/N) * 65536 + L]/N, 公式里的数字是十进制的,转换成十六进制是: X/N = int(H/N) * 10000h + [rem(H/N) * 10000h + L]/N。先来看下这个公式,公式按+号分为两部分,最终结果 = 第一部分乘以10000H + 第二部分,意思就是int(H/N)的值左移4位,作为最终结果的高位;第二部分作为最终结果的低位,然后把第二部分的余数作为整体计算结果的余数,保存在cx中。具体解题思路如下:
  • [b]分析这两部分,都用到了H/N的结果,而且只要H/N的结果计算出来了,那么第一部分的结果就也出来了,因此我们先计算H/N,然后计算第二部分,再计算第一部分,最后再把两部分结果合起来[/b]
  • 计算H/N的结果,H: (dx) =000FH,8位;N:(cx)=0AH,8位,计算步骤:(ax)=(dx), div cl。计算结果是(al),余数是(ah)。因为后边还要用到H/N的结果,我们可以在这一步把计算结果保存起来,后续再用到的时候可以直接取值。我看bx还没有用到,就保存到bx里吧。这一步的最终结果是:(bx) = (H/N)。
  • [b][rem(H/N) * 10000h + L]/N[/b]    取H/N的余数,左移4位,加上L之后,除以N,是不是感觉很熟悉?对了,这是个典型的16位除法运算:被除数的高位是rem(H/N),低位是L,除数是N,这就好办了。H/N的结果在bx中,取余数bh放到dx中: (dl) = (bh), (dh) = 0;L原本就在ax中,除数在cx中,所以可以直接除了: div cx。 计算结果商在ax中,余数在dx中。因为这个时候,还有公式第一部分没有计算,但是已经可以确定第一部分的计算用不到cx,因此我们可以按要求,直接把余数放到cx中,这一步的最终结果是:(ax) = [rem(H/N) * 1000h + L]/N 的商,(cx) = [rem(H/N) * 1000h + L]/N的余数,也是最终结果的余数。
  • int(H/N) * 1000H。  取H/N的商,左移4位。整个计算的最终结果要求(dx)=结果的高16位,(ax)=结果的低16位,因此,在这里,我们把H/N的商直接保存在dx中就可以了: (dl) = (bl), (dh) = 0。这一步的最终结果是:(dx) = int(H/N)。
  • 这时候我们再来回顾整个结果:(dx) = int(H/N) , (ax) = [rem(H/N) * 1000h + L]/N的商, (cx) = [rem(H/N) * 1000h + L]/N的余数,也就是整个结果的余数===>X/N = (dx) = int(H/N)  + [rem(H/N) * 1000h + L]/N =  (dx) * 10000H + (ax), 余数(cx)


好了,思路已经够详细了,怕麻烦的同学直接看代码(PS: 原题中被除数是0F4240H,除数是0AH,转换成十进制也就是100 0000/10,这样的话,余数是0,不好看,所以我在代码中给改成了100 0001/10,也就是0F4241H/0AH):
assume cs:code
code segment
        main:         mov ax, 4241h
                          mov dx, 0fh
                          mov cx, 0ah

                          call divdw

                          mov ax, 4c00h
                          int 21h

       divdw:         call calch
                          call calcl
                          call sum
                          ret

        calch:         push ax                ; calculate H/N,  result --> bx
                          push cx
                          mov ax, dx
                          div cl
                          mov bx, ax           
                          pop cx
                          pop ax
                          ret

         calcl:         push dx                 ; [rem(H/N)*10000h + L]/N, quotient-->ax, remainder-->cx
                          mov dl, bh
                          mov dh, 0
                          div cx
                          mov cx, dx
                          pop dx
                          ret

         sum:         mov dl, bl               ; int(H/N) , result --> dx
                          mov dh, 0
                          ret
code ends
end main
结果如下:初始状态(ax)=4240H, (dx)=000FH, (cx)=0AH;计算结果:(ax)=86a0H, (dx)=0001H, (cx)=0001H;手动验证一下对不对:
100 0001/10=10 0000  余 1,转化成十六进制:186A0H 余 1,低16位86A0H,高16位0001H,余数0001H, 完全正确:victory::victory::victory:
test10-2.jpg

如果大家有更好的思路,或者更高效的代码,欢迎交流,大家共同学习进步:lol::lol::lol:


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-27 13:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表