第五章([BX]和loop指令)
1.mov ax,[bx] 意思就是bx中存放的数据作为偏移地址EA,段地址SA默认在ds中,将SA:EA处的数据送入到ax中,即(ax)=((ds)*16+bx)
inc bx,1 意思就是bx中的内容加1.
2.loop指令
当CPU执行loop指令时,要进行两步操作:先是(cx)=(cx)-1,然后判断cx的值,不为0则转至标号处执行程序,为0则向下执行。
从这,我们可以看出cx的值直接影响着loop指令的执行,所以我们通常用loop指令来执行循环功能,用cx来存放循环次数。
框架入下:mov cx,循环次数
s:循环的内容
loop s
3.在Debug中跟踪loop指令实现的循环程序
看书上的实验步骤。
4.Debug和汇编编译器masm对指令的不同处理
在debug中指令:mov ax,[0] ;表示将ds:0处的数据送入到ax中。
但是在汇编源程序中 则会被当作指令mov ax,0 来使用
但是我们可以通过以下的代码来实现(先将偏移地址送入到bx寄存器中):mov ax,2000h
mov ds,ax
mov bx,0
mov al,[bx]
后两行也可以用mov al,ds:[0]
意思就是在汇编源程序中如果用指令来访问一个内存单元,必循在”[]"前面给出段地址的段寄存器。
5.loop和[bx]的联合应用
用同一种方法处理地址连续的内存单元的数据的问题,通常我们需要使用loop指令,并且我们可以不写新的指令,仅通过改变bx的指令来改变指令访问的内存单元。
6段前缀
出现在访问内存单元的指令中,用于显式地指明内存单元的段地址的,在汇编语言中称为段前缀。
7一段安全的空间
在不能确定一段内存空间中是否存放着重要的数据或代码的时候,不能随意向其中写入内容。
在DOS方式下,一般情况下,0:200~0:2ff空间没有系统或其他数据或代码,可以用来使用。
8段前缀的使用
可以用来将内存ffff:0~ffff:b单元中的数据复制到0:200~0:20b单元中
第六章 (包含多个段的程序)
程序获得所需空间的方法有两种:一是在加载程序的时候为程序分配;再就是程序在执行的过程中向系统申请
1.在代码段中使用数据
由“end start"指明的程序入口,被转化为一个入口地址,存储在可执行文件的描述信息中,这样CPU就从我们希望的地址处开始执行了。
归根到底,只要在源程序中用”end符号“来指明就可以让CPU从这开始执行程序。
2.在代码段中使用栈
可以在程序中通过定义数据来取得一段空间,然后将这段空间当作栈空间来使用。
所以我们在描述dw的作用时,可以说用它定义数据,也可以说用它开辟内存空间。
3.将数据 代码 栈放入不同的段
我们用定义代码段一样的方法来定义多个段,然后在这些段里面定义需要的数据,或通过定义数据来取得栈空间,主要的思想就是将数据 栈和代码放到不同的段中。
CPU处理我们定义在段中的内容,完全是靠程序中具体的汇编指令,和汇编指令对寄存器的设置来决定的。
第七章 (跟灵活的定位内存地址的方法)
1.and和or指令
and指令:逻辑与指令,按位进行与运算
or指令:逻辑或指令,按位进行或运算
2.关于ASCII码
如果我们用ASCII码的规则来解释显存中的61H,其实就是字符”a"的意思
3.以字符形式给出的数据
我们在汇编程序中,用’......'的方式指明数据是以字符的形式给出的,编译器将他们转换为相对应的ASCII码。
例如:db 'unIX' 相当于”db 75H,6EH,49H,58H"
4.大小写转换的问题
分析一下,我们可以知道,要想改变一个字母的大小写,实际上就是要改变他的ASCII码,我们又知道小写字母的ASCII码比大写字母的ASCII码值大20H。
我们用刚学会的or指令来改变他的第五位置(二进制的情况下):为0时,就为大写字母;反之,为1时,就为小写字母。
5. [bx+idata]
在前面,我们用[bx]的方式来指明一个内存单元,现在我们可以用[bx+idata]来表示,他的偏移地址为(bx)+idata(bx中的值加上idata)
对于指令mov ax,[bx+200]的解释 :
将一个内存单元的内容送入到ax中,这个内存单元的长度为2个字节,存放一个字,偏移地址为bx中的数值加上200,段地址存放在ds中。
数学化:(ax)=((ds)*16+(bx)+200)
6.用[bx+idata]的方式进行数组的处理
bx给出了从偏移地址开始的相对位置。
我们可以通过观察书本上的代码比较发现,[bx+idata]的方式为高级语言实现数组提供了便利机制。
7.SI和DI
si 和di 时8086CPU中和bx功能相近的寄存器,不能够分为两个8位寄存器来使用。
8.[bx+si]和[bx+di]
[bx+si]表示一个内存单元,他的偏移地址位(bx)+(si)
例如:指令 mov ax,[bx+si]
就是将一个内存单元的内容送入ax,这个内存单元的长度为两个字节,用来存放一个字,偏移地址为bx的值加上si的值,段地址存放在ds中。
数学化的描述为:(ax)=((ds)*16+(bx)+(si))
9.[bx+si+idata]和[ba+di+idata]
他们都是表示一个内存单元,偏移地址为(bx)+(si)或(di)+idata;
指令:mov ax,[bx+si+idata]
表示为将一个内存单元的内容送入到ax中,这个内存单元的长度为2个字节,存放一个字,偏移地址为bx 的数值加上di的数值再加上idata。
数学化的描述为:(ax)=((ds*16+(bx)+(di)+idata)
10.不同的寻址方式的灵活应用
(1)[idata]用一个常量来表示地址,可用于直接定位一个内存单元;
(2)[bx]用一个变量来表示内存地址,可用与间接定位一个内存单元;
(3)[bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元;
(4)[bx+si]用两个变量来表示地址;
(5)[bx+si+idata]用两个变量和一个常量表示地址。
可以看出,从[idata]到[bx+si+idata],我们可以用更加灵活的方式来吧定位一个内存单元的地址。
第八章 (数据处理的两个基本问题)
分别是:处理的数据在什么地方;以及要处理的数据有多长。(reg和sreg)
1.bx si di和bp
在8086CPU中,只有这四个寄存器可以用在[.....]中来进行内存单元的寻址。(其他的寄存器是不被允许的)
在[....]中,这四种寄存器可以单独出现,或只能以这四种组合出现:bx和si,bx和di,bp和si,bp和di.
只要在[....]中使用寄存器bp,而指令中没有显性的给出段地址,段地址就是默认存放在ss中
2.机器指令处理的数据在什么地方
指令在执行前,所要处理的数据可以在3个地方:CPU内部,内存,端口
3.汇编语言中数据位置的表达
用3个概念来表示数据的位置:立即数,寄存器,段地址(SA)和偏移地址(EA)
立即数:直接包含在机器指令中的数据,在汇编指令中直接给出;
寄存器:指令要处理的数据在寄存器中,在汇编指令中给出相应的寄存器名
段地址(SA)和偏移地址(EA):指令要处理的数据在内存中,在汇编指令中可用[x]的格式来给出EA,SA在某个 段寄存器中
存放段地址的寄存器一般是默认的,有的也是以显性的方式给出来的。
4.寻址方式
定义:数据存放在内存时,我们用多种方式来给定这个内存单元的偏移地址
主要有:直接寻址,寄存器间接寻址,基址变址寻址,相对基址变址寻址
5.指令要处理的数据有多长
对于8086CPU的指令,可以处理两种尺寸的数据:byte和word,所以,要在机器指令中指明进行的是字操作还是字节操作。
可以通过寄存器名指明要处理的数据的尺寸(比如ax和al)
在没有寄存器名存在的情况下,用操作符X ptr指明内存单元的长度,X在汇编指令中可以为word或byte
例如:mov word ptr [bx],2
mov byte ptr [bx],2
对于push指令而言,它就会z只执行字操作。
6.寻址方法的综合应用
一般来说,我们可以用[bx+si+idata]访问结构体中的数据:用bx 定位整个结构体,用idata定位结构体中的某一个数据项,用si定位数组项中的每个元素。
7.div指令
div是除法指令,有以下问题需要注意:
除数:有8位或16位,存放在reg中或内存单元中
被除数:默认放在AX或DX和AX中,如果除数为8位,则被除数为16位,默认存放在AX中;如果除数为16位,被除数为32位,在DX和AX中,DX存放高16位,AX存放低16位
结果:如果除数为8位,则AL存储除法操作的商,AH存储除法操作的余数;如果除数为16位,则AX存储除法的操作的商,DX存储除法操作的余数。
8.伪指令dd
之前我们用db 和dw来定义字节型数据和字性数据,而dd是用来定义双字型数据的
db 1
dw 1
dd 1
分别表示第一个数据为01H,占一个字节
第二个数据为0001H,占一个字
第三个数据为000000011H,占两个字
9.dup
它是一个操作符,用来进行数据的重复
比如 db 3 dup (0)
定义了三个字节,他们的值都为0,相当于db 0,0,0
db 3 dup(0,1,2)
相当于 bd 0,1,2,0,1,2,0,1,2