考虑这样个问题,计算ffff:0-ffff: b单元中的数据的和,结果存储在dx中 我们还是先分析一下
(1)运算后的结果是否会超出dx所能存储的范围?
ffff:0-ffff:b内存单元中的数据是字节型数据,范围在0255之间,12个这样的数据相加,结果不会大于65535,可以在dx中存放下。
(2)我们能否将ffff0-ffff:b中的数据直接累加到dx中?
当然不行,因为ffff:0-ffff: b中的数据是8位的,不能直接加到16位寄存器dx中。
(3)我们能否将ffff:0-ffff: b中的数据累加到dl中,并设置(dh)=0,从而实现累加到dx中?
这也不行,因为dl是8位寄存器,能容纳的数据的范围在0255之间,ffff:0-0ffff:b中的数据也都是8位,如果仅向dl中累加12个8位数据,很有可能造成进位丢失。
(4)我们到底怎样将ffff:0-ffff: b中的8位数据,累加到16位寄存器dx中?
从上面的分析中,可以看到,这里面有两个问题:类型的匹配和结果的不超界。具体的说,就是在做加法的时候,我们有两种方法:
①(dx)=(dx)+内存中的8位数据;
②(dl)=(dl)+内存中的8位数据。
第一种方法中的问题是两个运算对象的类型不匹配,第二种方法中的问题是结果有可能超界。
怎样解决这两个看似矛盾的问题?目前的方法(在后面的课程中我们还有别的方法)就是得用一个16位寄存器来做中介。将内存单元中的8位数据赋值到一个16位寄存器ax中,再将ax中的数据加到dx上,从而使两个运算对象的类型匹配并且结果不会超界。
想清楚以上的问题之后,编写程序如下。
无循环
assume cs:code code segment mov ax,0ffffh mov ds,ax ;设置(ds)=ffffh mov dx,0 ;初始化累加寄存器,(dx)=0 mov al,ds:[0] mov ah,0 ;(ax)=((ds)*16+0)=(ffff0h) add dx,ax ;向dx中加卜ffff:0单元的数值 mov al,ds:[1] mov ah,0 ;(ax)=((ds}*16+1)=(fffflh) add dx,ax ;向dx中加ffff:l单元的数值 mov al,ds:[2] mov ah,0 ;(ax)=((ds)*16+2)=(ffff2h) add dx,ax ;向dx中加卜ffff:2单元的数值 mov al,ds:[3] mov ah,0 ;(ax)=((ds)*16+3)=(ffff3h) add dx,ax ;向dx中加卜ffff:3单元的数值 mov al,ds:[4] mov ah,0 ;(ax)=((ds)*16+4)=(ffff4h) add dx,ax ;向dx中加卜ffff:4单元的数值 mov al,ds:[5] mov ah,0 ;(ax)=((ds)*16+5)=(ffff5h) add dx,ax ;向dx中加卜ffff:5单元的数值 mov al,ds:[6] mov ah,0 ;(ax)=((ds)*16+6)=(ffff6h) add dx,ax ;向dx中加卜ffff:6单元的数值 mov al,ds:[7] mov ah,0 ;(ax)=((ds)*16+7)=(ffff7h) add dx,ax ;向dx中加卜ffff:7单元的数值 mov al,ds:[8] mov ah,0 ;(ax)=((ds)*16+8)=(ffff8h) add dx,ax ;向dx中加卜ffff:8单元的数值 mov al,ds:[9] mov ah,0 ;(ax)=((ds)*16+9)=(ffff9h) add dx,ax ;向dx中加卜ffff:9单元的数值 mov al,ds:[0ah] mov ah,0 ;(ax)=((ds)*16+0ah)=(ffffah) add dx,ax ;向dx中加卜ffff:a单元的数值 mov al,ds:[0bh] mov ah,0 ;(ax)=((ds)*16+0bh)=(ffffbh) add dx,ax ;向dx中加卜ffff:b单元的数值 mov ax,4c00h ;程序返回 int 21h code ends end
上面的程序很简单,不用解释,你一看就懂。不过,在看懂了之后,你是否觉得这个程序编得有些问题?它似乎没有必要写这么长。这是累加fff#0-ffff:b中的12个数据,如果要累加0000:0-0000:7fff中的32KB个数据,按照这个程序的思路,将要写将近10万行程序(写一个简单的操作系统也就这个长度了)。
采用LOOP循环
;loop和bx的联合应用 assume cs:code code segment mov ax,0ffffh mov ds,ax ;数据段 mov bx,0h ;偏移地址从0开始初始化ds:bx指向ffff:0 mov dx,0 ;累加器清零初始化累加寄存器dx, (dx)=0 mov cx,12 ;初始化循环计数寄存器cx,(cx)=12 s: mov al,[bx] mov ah,0h add dx,ax ;间接向dx中加卜((ds)*16+(bx))单兀的数值 inc bx ;ds:bx指向下一个单元 loop s mov ax,4c00h int 21h code ends end
在实际编程中,经常会遇到,用同一种方法处理地址连续的内存单元中的数据的问题。我们需要用循环来解决这类问题,同时我们必须能够在每次循环的时候按照同一种方法来改变要访问的内存单元的地址。这时,就不能用常量来给出内存单元的地址(比如,[0], [1], [2]中,0. 1. 2是常量),而应用变量。"mov al,[bx]”中的bx就可以看作一个代表内存单元地址的变量,我们可以不写新的指令,仅通过改变bx中的数值,改变指令访问的内存单元。