glider 发表于 2015-7-2 22:37:25

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


如题。这个程序让我有种久违的数学课的感觉,泪流满面啊:cry
不废话,直接开始,题目中给出了公式:X/N = int(H/N) * 65536 + /N, 公式里的数字是十进制的,转换成十六进制是: X/N = int(H/N) * 10000h + /N。先来看下这个公式,公式按+号分为两部分,最终结果 = 第一部分乘以10000H + 第二部分,意思就是int(H/N)的值左移4位,作为最终结果的高位;第二部分作为最终结果的低位,然后把第二部分的余数作为整体计算结果的余数,保存在cx中。具体解题思路如下:

[*]分析这两部分,都用到了H/N的结果,而且只要H/N的结果计算出来了,那么第一部分的结果就也出来了,因此我们先计算H/N,然后计算第二部分,再计算第一部分,最后再把两部分结果合起来
[*]计算H/N的结果,H: (dx) =000FH,8位;N:(cx)=0AH,8位,计算步骤:(ax)=(dx), div cl。计算结果是(al),余数是(ah)。因为后边还要用到H/N的结果,我们可以在这一步把计算结果保存起来,后续再用到的时候可以直接取值。我看bx还没有用到,就保存到bx里吧。这一步的最终结果是:(bx) = (H/N)。
[*]/N。    取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) = /N 的商,(cx) = /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) = /N的商, (cx) = /N的余数,也就是整个结果的余数===>X/N = (dx) = int(H/N)+ /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               ; /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:


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


页: [1]
查看完整版本: 汇编语言实验10第二个程序解题思路,欢迎交流