8086汇编-27[BX]和Loop指令05

#pragma once
/*    27-[BX]和Loop指令05

  loop和[bx]的联合应用
    考虑这样一个问题:

        计算ffff:0~ffff:b单元中的数据的和,结果存储在dx中。

    计算ffff:0~ffff:b单元中的数据的和,结果存储在dx中。

    分析:
        (1)运算后的结果是否会超出 dx 所能存储的范围?
             ffff:0~ffff:b内存单元中的数据是字节型数据,范围在0~255之间,12个这样的数据相加,结果不会大于 65535 ,可以在dx中存放下。

    
    计算ffff:0~ffff:b单元中的数据的和,结果存储在dx中。

    分析:
        (2)我们是否将 ffff:0~ffff:b中的数据直接累加到dx中?
             当然不行,因为ffff:0~ffff:b中的数据是8位的,不能直接加到16位寄存器dx中。


    计算ffff:0~ffff:b单元中的数据的和,结果存储在dx中。

    分析:
       (3)我们能否将ffff:0~ffff:b中的数据累加到dl中,并设置(dh=0,从而实现累加到dx中的目标?
         这也不行,因为dl是8位寄存器,能容纳的数据的范围在小 255 之间,ffff : 0~ffff:b中的数据也都是 8 位,如果仅向dl中累加12个 8 位数据,很有可能造成进位丢失。

    计算ffff:0~ffff:b单元中的数据的和,结果存储在dx中。

    分析:
        (4)我们到底怎样将用ffff:0~ffff:b中的8位数据,累加到16位寄存器dx中? 


    从上面的分析中,我们可以看到,这里面有两个问题:类型的匹配和结果的不超界。
    具体的说,就是在做加法的时候,我们有两种方法:
           (dx)=(dx)+内存中的8位数据:
           (dl)=(dl)+内存中的8 位数据;

      第一种方法中的问题是两个运算对象的类型不匹配,第二种方法中的问题是结果有可能超界。 


     计算ffff:0~ffff:b单元中的数据的和,结果存储在dx中。

    分析:
       怎样解决这两个看似矛盾的问题?
       目前的方法(在后面的课程中我们还有别的方法)就是我们得用一个16位寄存器来做中介。

    我们将内存单元中的 8 位数据赋值到一个16位寄存器ax中,再将ax中的数据加到dx上,从而使两个运算对象的类型匹配并且结果不会超界。

        想清楚以上的问题之后,我们编写程序代码。
        mov ax,0ffffH        
        mov ds,ax            设置(ds)=0ffffH
        mov dx,0            初始化累加寄存器,(dx) =0

        mov al,ds:[0]
        mov ah,0            (ax) = ((ds)*16+0) = (0ffff0H)
        add dx,ax            向dx中加上0ffffH:0 单元的的数值

        mov al,ds:[1]
        mov ah,0            (ax) = ((ds)*16+1) = (0ffff1H)
        add dx,ax            向dx中加上0ffffH:1 单元的的数值

        mov al,ds:[2]
        mov ah,0            (ax) = ((ds)*16+2) = (0ffff2H)
        add dx,ax            向dx中加上0ffffH:2 单元的的数值

        mov al,ds:[3]
        mov ah,0            (ax) = ((ds)*16+3) = (0ffff3H)
        add dx,ax            向dx中加上0ffffH:3 单元的的数值

        mov al,ds:[4]
        mov ah,0            (ax) = ((ds)*16+4) = (0ffff4H)
        add dx,ax            向dx中加上0ffffH:4 单元的的数值

        mov al,ds:[5]
        mov ah,0            (ax) = ((ds)*16+5) = (0ffff5H)
        add dx,ax            向dx中加上0ffffH:5 单元的的数值

        ........

    问题
       应用loop 指令,改进上面程序 ,使它的指令行数让人能够接受。
   
       请先思考后再看分析。

  分析
    我们可以看出,在程序中,有12个相似的程序段,我们将它们一般化地描述为:
            mov al,ds:[x]
           mov ah,0
           add dx,ax

    我们可以看到,12个相似的程序段中,只有mov al,ds:[X]指令中的内存单元的偏移地址是不同的,其他都一样。

    而这些不同的偏移地址是可在0≤X≤0bH的范围内递增变化的。

    我们可以用数学语言来描述这个累加的

    运算:

 

                                           ---- 看不懂没关系哦.

    从程序实现上,我们将循环做:
       (al )=((ds)*16+X)
       (ah)=0  
       (dx)=(dx)+(ax)

   一共循环12次,在循环开始前(dx)=0ffffh,X=0,ds:X指向第一个内存单元。每次循环后,X递增,ds:X指向下一个内存单元。

   完整的算法描述
   初始化:(ds)=0ffffh 
            X=0
           (dx)=0
   循环12次:
           (al) =((ds)*16+X) 
           (ah) = 0 
           (dx)=(dx)+(ax)
           X=X+1            这里是书本中的,写的不太严禁,我认为应该写成 inc X
    
   可见,表示内存单元偏移地址的X应该是一个变量 ,因为在循环的过程中,偏移地址必须能够递增。

   这样,在指令中,我们就不能用常量来表示偏移地址。我们可以将偏移地址放到 bx中,用[bx]的方式访问内存单元。

   在循环开始前设(bx)=0,每次循环,将bx中的内容加1即可。

   最后一个问题是,如何实现循环12次?
   我们的loop指令该发挥作用了。
   更详细的算法描述。

   更详细的算法描述初始化
         (ds)=0ffffh
         (bx)=0
         (dx)=0
         (cx)=12
   循环12 次:
         s:(al)=((ds)*16+(bx))
         (ah)=0
         (dx)=(dx)+(ax)
         (bx)=(bx)+1
         loop s    

  我们的最终程序:

assume cs:code

code segment

start:    mov ax,0ffffH
        mov ds,ax
        mov bx,0

        mov dx,0

        mov cx,12

s:        mov al,[bx]
        mov ah,0
        add dx,ax
        inc bx
        loop s

        mov ax,4c00H
        int 21H

code ends

ends start


        

  loop和[bx]的联合应用
    在实际编程中,经常会遇到,用同一种方法处理地址连续的内存单元中的数据的问题。

    我们需要用循环来解决这类问题,同时我们必须能够在每次循环的时候按照同一种方法来改变要访问的内存单元的地址。

    这时,我们就不能用常量来给出内存单元的地址(比如[0]、[1]、[2]中,0、1、2是常量),而应用变量。

    “mov al,[bx]”中的 bx就可以看作一个代表内存单元地址的变量,我们可以不写新的指令,仅通过改变bx中的数值,改变指令访问的内存单元。

  段前缀
    
    指令“mov ax,[bx]”中,内存单元的偏移地址由bx给出,而段地址默认在ds中。

    我们可以在访问内存单元的指令中显式地给出内存单元的段地址所在的段寄存器。

    这些出现在访问内存单元的指令中,用于显式地指明内存单元的段地址的“ds:”、“cs:”、“ss:”或“es:”,在汇编语言中称为段前缀
        例如 mov ax,ds:[0] 这种 ds:[0] 的ds: 就是段前缀

*/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值