您的位置:首页 > 运维架构

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

2011-04-20 22:14 453 查看
第五章 [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的使用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐