王爽《汇编语言》(第二版) 学习笔记 (第五章 [BX]和loop指令 )

 

第五章 [BX]和loop指令
本章概述:
1.         这里将使用一个描述性的符号“()”来表示一个寄存器或一个内存单元中的内容。“()”中的元素可以有3种类型:寄存器名、段寄存器名、内存单元的物理地址(一个20位数据)。如:(ax)、(ds)、(al)、(cx)、(20000H)、((ds)*16 + (bx))都是正确的,(2000:0),((ds):1000H)是错误的
2.         mov ax,[0] 即(ax)=((ds)*16+0)                mov al,[0] 即(al)=((ds)*16+0)
3.         要完整地描述一个内存单元,需要两种信息:
1)        内存单元的地址
2)        内存单元的长度(类型)。
4.         用[0]表示一个内存单元时,0表示单元的偏移地址,段地址默认在ds中,单元的长度(类型)可以由具体指令中的其他操作对象(比如说寄存器)指出。
5.         [bx]同样也表示一个内存单元,它的偏移地址在bx中,如:
1)        mov ax,[bx] 即(ax)=((ds)*16+(bx))
2)        mov al,[bx] 即(al)=((ds)*16+(bx))
6.         “(X)”所表示的数据有两种类型:字节或字。是哪种类型由寄存器名或具体的运算决定。例如:
1)        (al)、(bl)、(cl)等得到的数据为字节型;(ds)、(ax)、(bx)等得到的数据为字型。
2)        (al)=(20000H),则(20000H)得到的数据为字节型;(ax)=(20000H),则(20000H)得到的数据为字型。
7.         约定符号idata表示常量。如:
1)        mov ax ,[idata]就代表mov ax,[1] 、mov ax,[2]、 mov ax,[3]
2)        mov bx ,idata就代表 mov bx,1  、 mov bx,2 、mov bx,3
 
一、     [BX]
1.         mov ax,[bx] 即(ax)=((ds)*16+(bx))             mov [bx],ax 即((ds)*16+(bx))=(ax)
2.         inc bx     在bx中的内容加1
二、     loop 指令
1.         loop指令的格式是:loop 标号,CPU执行loop指令的时候,要进行两步操作,先(cx)=(cx)-1,然后判断cx中的值,不为0则转至标号处执行程序,如果为0则向下执行。在汇编语言中,标号代表一个地址。
2.         cx中的值影响着loop指令的执行结果。通常我们用loop指令来实现循环功能,cx中存放循环次数。
3.         使用cx和loop指令的要点:
1)        在cx中存放循环次数 
2)        loop指令中的标号所标识地址要放在前面    
3)        要循环执行的程序段,要写在标号和loop指令的中间。
4.         注意一般应该减少循环的次数以提升程序效率
三、     在Debug中跟踪用loop指令实现的循环程序
1.         当需要把一个8位的数放到16位的寄存器的低8位中,且在以后的运算中,数据可能超过8位时,可以在先把8位数放到XX的XL中,然后置XH=0,之后的操作对象在XX上进行就没有问题。
2.         大于9FFFH的十六进制数据A000H、A0001H…..FFFFH等,在书写的时候都是以字母开头的,而在汇编源程序中,数据不能以字母开头,所以要在前面加0。
3.         注意“int 21”要用p命令执行。
4.         使用Debug的g命令,“g 0012”,它表示执行程序到当前代码段的0012h处。
5.         在循环中使用p命令来快速调试,Debug就会自动重复执行循环中的指令,直到(cx)=0为止。也可以使用g命令来跳过循环来快速调试。
四、     Debug 和汇编编译器masm对指令的不同处理
1.         Debug和编译器对形如mov ax,[idata]的指令在解释上有很大的不同:Debug将[idata]解释为“[idata]”是一个内存单元,“idata”是内存单元的偏移地址。而编译器却将“[idata]”解释为“idata”一个数。
2.         Debug和编译器对形如mov ax,[寄存器]的指令在解释上是相同的。
3.         两种方法解决:
1)        将偏移地址以直接数的形式送进bx,然后mov ax,[bx] 这样用bx来间接地给出内存单元的偏移地址。
2)        在“[]”的前面显式地给出段地址所在的段寄存器。
4.         如果“[]”中的内容是常量idata,如果没有加段前缀,则编译器将“[idata]”解释为“idata”,如果“[]”中的内容是寄存器,则段地址默认在ds中,也可以显式地给出段地址所在的段寄存器。
五、     loop 和[bx]的联合应用
1.         计算ffff:0-ffff:b单元中的数据的和,结果存储在dx中。会遇到类型不匹配和结果超界的问题,解决方法是借用一个16位的寄存器来做中介。将数据依次放到al中,而ah置0,然后将ax赋值到dx中进行累加。
2.         “mov al,[bx]”中的bx就可以看做一个代表内存单元地址的变量,我们可以不写新的指令,仅通过改变bx中的数值,改变指令访问的内存单元。
六、             段前缀
形如:
1)        mov ax,ds:[bx] 
2)        mov ax,cs:[bx] 
3)        mov ax,ss:[bx] 
4)        mov ax,es:[bx]  
5)        mov ax,ss:[0]   
6)        mov ax,cs:[0]     
这些访问内存单元的指令中,用于显式地指明内存单元的段地址的“ds:”、“cs:”、“ss:”、“es:”,在汇编语言中称为段前缀。
七、             一段安全的空间
1.         在8086模式中,随意向一段内存空间写入内容是很危险的,因为这段空间中可能存放着重要的系统数据或代码。如果改写了,将引发错误。
2.         在不能确定一段内存空间中是否存放着重要的数据或代码的时候,不能随意向其中写入内容。
3.         我们是在操作系统的环境中工作,操作系统管理所有的资源,也包括内存。如果我们需要向内存空间写入数据的话,要使用操作系统给我们分配的空间,而不应直接用地址任意指定内存单元,向里面写入。
4.         我们在纯DOS方式(实模式)下,可以不理会DOS,直接用汇编语言去操作真实的硬件,因为运行在CPU实模式下的DOS,没有能力对硬件系统进行全面、严格地管理。但在Windows2000、Unix这些运行于CPU保护模式下的操作系统中,不理会操作系统,用汇编语言去操作真实的硬件,是根本不可能的。硬件已被这些操作系统利用CPU保护模式所提供的功能全面而严格地管理了。
5.         在一般的PC机中,DOS方式下,DOS和其他合法的程序一般都不会使用0:200-0:2ff的256字节的空间。所以,使用这段空间是安全的。不过为了谨慎起见,在进入DOS后,我们可以先用Debug查看一下,如果0:200~0:2ff单元的内容都是0的话,则证明DOS和其他合法的程序没有使用这里。
八、             段前缀的使用
1.         将内存ffff:0-ffff:b单元中的数据复制到0:200-0:20b单元中时,使用2个不同的段寄存器作为段前缀以优化程序。
2.         对于同一个地址一般有多种段地址:偏移地址的组合,有时为了优化程序可以改变原来给定的段地址:偏移地址的组合。
3.         使用2个不同段寄存器有时可以优化程序。
九、             实验4  [bx] 和loop 的使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值