[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 bx1   mov bx2  mov bx3

 

一、     [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.         使用cxloop指令的要点:

1)        cx中存放循环次数 

2)        loop指令中的标号所标识地址要放在前面   

3)        要循环执行的程序段,要写在标号和loop指令的中间。

4.         注意一般应该减少循环的次数以提升程序效率

三、     Debug中跟踪用loop指令实现的循环程序

1.         当需要把一个8位的数放到16位的寄存器的低8位中,且在以后的运算中,数据可能超过8位时,可以在先把8位数放到XXXL中,然后置XH=0,之后的操作对象在XX上进行就没有问题。

2.         大于9FFFH的十六进制数据A000HA0001H…..FFFFH等,在书写的时候都是以字母开头的,而在汇编源程序中,数据不能以字母开头,所以要在前面加0

3.         注意“int 21”要用p命令执行。

4.         使用Debugg命令,“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中,而ah0,然后将ax赋值到dx中进行累加。

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

六、             段前缀

形如:

1)        mov axds:[bx] 

2)        mov axcs:[bx] 

3)        mov axss:[bx] 

4)        mov axes:[bx]  

5)        mov axss:[0]   

6)        mov axcs:[0]    

这些访问内存单元的指令中,用于显式地指明内存单元的段地址的“ds:”、“cs:”、“ss:”、“es:”,在汇编语言中称为段前缀。

七、             一段安全的空间

1.         8086模式中,随意向一段内存空间写入内容是很危险的,因为这段空间中可能存放着重要的系统数据或代码。如果改写了,将引发错误。

2.         在不能确定一段内存空间中是否存放着重要的数据或代码的时候,不能随意向其中写入内容。

3.         我们是在操作系统的环境中工作,操作系统管理所有的资源,也包括内存。如果我们需要向内存空间写入数据的话,要使用操作系统给我们分配的空间,而不应直接用地址任意指定内存单元,向里面写入。

4.         我们在纯DOS方式(实模式)下,可以不理会DOS,直接用汇编语言去操作真实的硬件,因为运行在CPU实模式下的DOS,没有能力对硬件系统进行全面、严格地管理。但在Windows2000Unix这些运行于CPU保护模式下的操作系统中,不理会操作系统,用汇编语言去操作真实的硬件,是根本不可能的。硬件已被这些操作系统利用CPU保护模式所提供的功能全面而严格地管理了。

5.         在一般的PC机中,DOS方式下,DOS和其他合法的程序一般都不会使用0:200-0:2ff256字节的空间。所以,使用这段空间是安全的。不过为了谨慎起见,在进入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
发出的红包

打赏作者

Wireless_Link

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值