20192431张潇文汇编程序设计前四章学习笔记
第一章
1.1节—概述
计算机程序语言可以分为:机器语言、高级语言和汇编语言三类。
1. 机器语言:就是把控制计算机的命令和各种数据直接用二进制数码表示的一种程序设计语言。
2. 高级语言:屏蔽了许多操作细节,但是效率比机器语言低
3. 汇编语言:便于记忆和阅读,使用字母和符号来表示。汇编语言程序与机器语言程序的关系是一条汇编语言的语句与一条机器语言指令对应,汇编语言程序与机器语言程序效率相同。汇编语言和硬件密切联系。
1.2进制以及数的表示部分:
进位计数制及其相互转换:
- 位权:各个位置上所表示的基本数值称为位权,简称权。
- 基数:每个数位上能使用不同数码的个数称为基数。每个数位能取的最大数码值=基数-1.二进制在机器语言当中用的比较多。
- 二进制与八进制十六进制:3位二进制数与一位八进制数一样,4位二进制数与一位十六位进制数类似。
常用的字母表达:
各种数制间的相互转换:主要讨论二进制与十进制之间的转换。
1.3十进制整数转换为二进制数:
1. 减权定位法:从二进制数高位起,依次用带转换的十进制数与各位权值进行比较,如果够减,该位为1,不够减该位为0。如图:
2. 除基取余法。如图:
但是要注意是从下往上读。这种转换方法同样适合于其它进制数之间的转换。
- 十进制小数转换为二进制数:
1. 减权定位法:
1. 乘基取整法:
1.4、二进制整数转换为十进制数:
1. 按权相加法
2. 逐次乘积相加法:
1.5二进制小数转换为十进制数:
(1)按权相加法
(2)逐次除基相加法:
1.6带符号数的表示:
-
用“+”或“-”表示正负的数叫真值
-
用“0”或“1”表示正负的数叫机器数
-
原码表示
-
二进制数的最高位表示符号,0表示正,1表示负,数值部分用二进制数绝对值表示
注:8位二进制数原码的最大数为01111111(+127),最小数为11111111(-127)0的原码有两种表示形式:00000000和10000000(+0和-0)
补码表示
补码的定义:带符号数X的补码表示[X]补定义为[X]补=M+X(Mod
M),其中模数M根据机器数的位数而定,如位数为8则M=2^8
用补码表示的机器数,符号位仍然表示数的符号:0为正,1为符。对于正数,补码与原码相同,对于负数需要进行变换。
-
负数的真值变换为补码的方法:将各位变反(0变1,1变0)然后在最低位加1
-
负数的原码变换为补码:保持符号位不变,其余各位变反,最低位加1.
当位数为8时,最大补码为01111111=[+127]补,最小补码为10000000=[-128]补(这考虑进位),0的补码只有一个,[0]补=00000000,[-128]补=10000000,[-1]补=11111111.
补码的加减运算:
规则:[X+Y]补=[X]补+[Y]补
[X-Y]补=[X]补-[Y]补=[X]补+[-Y]补
注:其中[-Y]补是对[Y]补执行一次求补运算(求补运算是将原数连同符号位一起(不管是正还是负)按位求反,再在最低位加1)。
1.7字符的表示:
在计算机内部,各种字符都是按一定的方式编写成二进制信息,不同的计算机以及不同的场合所采用的编码形式可能不同,目前最广泛采用的是ASCII码。标准ASCII码为一字节,其中用低七位表示字符编码,用最高位表示奇偶数校验位。一共128个
非打印和打印ASCII码,非打印的有33个。
基本逻辑运算:
常见的基本逻辑运算就是与或非和异或。
具体见下表即可理清楚:
第二章 IBM微机基本结构
2.1节:微机基本结构:
一般计算机应包括五大部件:运算器、控制器、存储器,输入设备和输出设备。由于微机的主要特点是其体积很小,因此在系统上就有一些特殊考虑。将运算器和控制器两大部件集成在一个集成电路芯片上,称为中央处理器,简称CPU,也叫微处理器。
系统采用总线结构,总线结构分为三种,是计算机内部不同部件之间的传输通道。这个示意图显示出了五大部件之间的连接关系,三大总线可以相互连接,控制和传输的作用。
中央处理器CPU,它包括运算器和控制器。分析从主存储器取来的各条指令的功能,控制计算机各部件完成指定功能的各项操作。
存储单元的多少标识了其大小,对每个存储单元是按照地址来进行访问的。
在大多数计算机中,存储器的组织都是以字节为基本单位,每一个基本单位称为一个存储单元。10位就是1K个单元。
主机:习惯上将CPU于主存储器合称为主机,在计算中,一般还配置有辅助存储器,称为辅存,也可叫做外村。
输入输出设备及接口:磁盘、磁带,触摸显示屏二者功能兼有。
由于I/O设备不同的设备查边很大,因此需要有I/O接口才能与系统总线连接。
三大总线传输的内容是不同的。
汇编语言由一系列的指令构成,是最基本的单位。在执行指令的过程中有两个步骤,取指令和执行指令。这两个步骤执行又分为串行和指令流水线方式。
串行方式:以CPU为例,取指,执行,存数。
特点是:当CPU在指令执行阶段,不需要占用系统总线,但此时总线也不工作,因此系统总线的空闲时间比较多。
在存储器取指令、取数据或存数据时,总线处于忙状态,其所占用的时间也比较长。而CPU却只需要花很短的时间去处理,因此大部分时间处于闲置状态。
8086CPU结构分为两部分(执行单元EU和总线接口单元BIU)。
EU当中主要进行计算控制,通用寄存器,ALU等等。
BIU中通过三种类型的总线去进行功能。
EU和BIU是相互独立合作的。
2.2节:CPU寄存器结构及其用途
一共有14个寄存器,8个16位通用寄存器。AX,BX,CX,DX(8个通用寄存器)。H表示高位,L表示低位。AX是累加器,BX是基址寄存器,CX是计数寄存器,DX是数据寄存器。具体可看下图:
一、通用寄存器:
AX数据寄存器既可以用来存放参加运算的操作数,也可以存放运算的结果。在多数情况下,使用这些寄存器时必须在指令中明确指示。
如 MOV AX BX;将BX的内容送到AX中去。
很显然后面的是源地址,前面的是目的地址。
在有些指令中,不需要明确指出使用的寄存器名,即隐含使用了某寄存器。比如在循环指令LOOP中,CX被隐含指定做循环次数计数用。
特定使用:移位指令 SHL AX,CL。CL被固定用作移位次数。
指针寄存器有堆栈指针SP和基址指针BP,它们一般用来存放16位地址,在形成20位的物理地址时,常被作为偏移量来使用。SP隐含使用时,用来指向堆栈顶部单元。BP一般指向堆栈段内某一存储单元。当然也可存放结果操作数之类的。
SI(源变址寄存器),DI(目的变址寄存器)。也可以作为通用寄存器
段寄存器(有四个):每个段用来存放不同的内容,如程序代码、数据等等。每个存储段的起始位置叫做段基址。由低到高。
CPU在访问存储器时必须指明两个内容:存储单元属于哪个段,存储单元与段基址的偏移量。
在程序设计中,一个程序将存储器划分成多少个存储段式任意的,但在程序运行的时候最多只有四个段,分别由CS、DS、ES、SS指定。
指令指针IP:IP作为偏移量,段寄存器CS作为代码段的基址指针,共同形成一条指令的存放地址。
当CPU从内存中取出一条指令后,IP自动修改为下一条指令的地址。
IP的内容不能被直接访问,可以通过某些指令的执行而自动修改IP内容,转移指令和子程序调用指令CALL可以自动改变IP寄存器的内容。
子程序调用指令CALL,将IP原有内容自动压入堆栈,而将子程序的入口地址偏移量自动送入IP,而返回指令RET,又自动从堆栈中弹回原有IP的内容。
标志寄存器:用来反映CPU在运行时的某些状态,8086/8088中是16位,但只定义了其中9位,如图:
标志位分为状态标志和控制标志
状态标志:CF,PF,AF,ZF,SF,OF
控制标志:TF,DF,IF
CF用在借位或者进位,当然在移位类指令中,CF也用来存放从最高位(左移)或最低位(右移)移出的数值
PF:低八位中含有1的个数为偶数时,被置1。
AF:置反映运算结果低八位,与操作数长度无关。
OF:超过补码所能表示数的范围时置1,否则置0.
溢出和进位是不同的
2.3存储器组织结构
存储器由若干个存储单元构成。每个存储单元存放相同长度的二进制数,8位一个字节。每个存储单元有唯一的地址编号——地址。
8086/8080CPU有20根地址总线。
为了方便书写,在源程序中常用5位16进制数或一个符号来表示一个存储单元的地址。
任何两个相邻字节单元就构成一个字单元。即16位二进制数位一个字。
放数据的时候就是低对低,高对高。
在定义一个地址时必须指出是字节或字类型属性。
存储器的段结构具有以下几个特点:
每个段的最大长度为64K。在这些段里用户可以任意设定长度和用途以及段的个数。
2.每个段的基址必须是一个小节的首址。
小节:每16个字节单元称为一个小节。
3.逻辑段在物理存储器中可以是邻接的、间隔的、部分重叠的和完全重叠的灯四种情况。内存中的一个物理存储单元可以映象到一个或多个逻辑段中。
4.在任一时刻,一个程序只能访问4个当前段中的内容。4个段分别是代码段、数据段、堆栈段和附加段。
三、逻辑地址与物理地址及对应关系。
1.物理地址:00000H~FFFFFH
逻辑地址:包含段基值和偏移量。
段基值:存放在那4个段寄存器中的值。
偏移量:表示某个存储单元与它所在段的段基址之间的字节距离。
逻辑地址的表示方法:段基值:偏移量
逻辑地安置转为物理地址:将逻辑地址的段基址左移4位,形成20位的段基址(低位为0)然后与16位的偏移量相加,结果即为20位的物理地址。
同一个物理地址可以被多个逻辑地址映射。
逻辑地址的来源:在程序的执行过程中,CPU根据不同操作类型访问存储器,其逻辑地址中段基值和偏移量的来源是不一样的。
2.4堆栈及其操作方法:
堆栈是一个特定的存储区,访问该存储区一般需要按照专门的规则进行操作。主要用于暂存数据以及在过程调用或处理中断时保存断点信息。
堆栈的构造:专用堆栈存储器和软件堆栈。
专用:专门设计的存储器
软件:在内存中划分出一块区域。
堆栈的一端是固定的,称为栈底,栈底是堆栈存储区的最大地址单元。另一端是浮动的称为栈顶,栈顶是最后存入信息的存储单元。栈顶是随着堆栈中存放信息的多少而改变。
堆栈指针SP,指示堆栈的顶部。
堆栈存取数据的规则是FILO。
堆栈寄存器SS指示了一段空间,SS是堆栈的起始位置。
数据满的时候指向栈顶。没有数据的时候指向栈顶+2,其值就是堆栈的长度。如果指向栈底,说明还是有数据的。如果堆栈的数据超过了64K的话,那么我们只要多设置几个栈就好。
堆栈的操作:
1.设置堆栈,对堆栈段寄存器SS和堆栈指针SP赋值。
PARA STACK就是用来说明本段为堆栈段。SP会被设置为初值100。
2.进栈PUSH,由指令PUSH或者由机器自动实现,可以将通用寄存器、段寄存器或字存储单元的内容压入堆栈顶部。
进栈的过程:首先将堆栈指针SP-2,将数据放入SP指向的单元里。
3.出栈POP,把堆栈顶部弹出一个字(两个字节)传送到存储单元中。
将SP指向的字单元(即栈顶字单元)内容送往指定的寄存器或存储器,堆栈指针SP内容加2。数据少了就应该变长。
进栈操作先操作指针,出栈的操作先进行内容,再处理指针。
第三章 寻址方式与指令系统
3.1节寻址方式:
寻址方式:一条指令通常由操作码和操作数两大部分构成。操作码:行为,操作数:对象。寻址就是找操作数的方法。
操作数的方法有以下四种:立即数操作数,在指令代码中提供。
寄存器操作数
存储器操作数
I/O端口操作数。
1.立即数寻址:立即数可以是8位或者16位。
MOV AX 20A0H:表示将16位立即数20A0H送入AX中。
立即数寻址速度非常快,直接从BIU的指令队列中取出,它不需要另外占用总线周期,因此这种寻址方式执行速度快。立即数只能作为源操作数,而不能作为目的操作数。
2.寄存器寻址:操作数在寄存器里可以是通用寄存器也可以是段寄存器。MOV
AX,BX。这种寻址方式在CPU内部进行,不需要总线周期,所以执行速度也很快。
后面的寻址方式就将在存储器中。
一个存储单元逻辑地址表示为:段基值:偏移量。
有效地址也叫做偏移量EA。
存储器寻址方式:
1.直接寻址:操作数的有效地址EA只有位移量地址分量。在汇编语言程序中,直接寻址方式用符号或常数来表示。再用常数表示的时候要用方括号括起来。
2.寄存器间接寻址:EA直接从基址寄存器BX或BP或变址寄存器(SI或DI中获得)。如果在程序运行期间,只要对寄存器内容进行修改,就可以实现用同一条指令实现对不同存储单元进行修改。指示存储器所在段的段寄存器可以省略,当指令中使用的BP寄存器,则隐含表示使用SS段寄存器,其余情况则隐含使用DS段寄存器。
3.基址寻址/变址寻址:EA由两个分量构成。段寄存器的隐含使用规则与寄存器间接寻址方式相同。
基址和变址称为寄存器相对寻址,只需改变寄存器的内容就可以用一条指令访问不同的存储单元。
4.基址变址寻址:EA=基址+变址+位移量
5.串操作寻址方式,使用SI和DI专门指示,在寻找源操作数时,隐含使用SI作为地址指针,在寻找目的串时,隐含使用DI作为地址指针,在串操作完成之后,自动对SI和DI进行修改,使它们指向下一个操作数
6.I/O端口寻址:在计算机系统,对I/O端口的寻址方式:存储器编址方法(需要占用存储地址空间)
I/O端口编址方法:与存储器地址分开,并使用专门的输入指令和输出指令。
直接端口寻址:端口地址一般采用两位16进制数,也可以用符号表示。直接端口寻址可访问的端口数为0~255个。
寄存器间接端口寻址:把I/O端口的地址先送到DX中,用DX作间接寻址寄存器。如果访问的端口地址大于255,则必须用I/O端口间接寻址。
3.2指令系统:
指令的划分:
无操作数指令:不需要操作数的指令,如HLT
在指令格式中,没有显式地指明操作数,但是它隐含指明了操作数的存放地方,如PUSHF
一、传送类指令:MOV DEST,SRC
MOV指令对标志寄存器的各位无影响。立即数只能作源操作数,且它不能传送给段寄存器。寄存器之间的传送中要注意,段寄存器CS只能作源操作数,不能作目的操作数。段寄存器之间不能直接传送,存储单元之间不能直接传送数据,寄存器与存储单元之间传送。
二、交换指令
指令格式:XCHG DEST,SRC
数据交换可以在寄存器之间或寄存器与存储器单元之间进行,但是不能再存储单元之间直接进行数据交换,寄存器只能使用通用寄存器。
三、标志传送指令:对标志寄存器进行存取的指令有4条,它们都是无操作数指令,即指令隐含指定标志寄存区,AH寄存器或堆栈为操作数。
(1)取标志寄存器指令:指令格式:LAHF,将标志寄存器的低8位送入AH寄存器,即将标志SF/ZF/AF/PF/CF送入AH的第7,6,4,2,0位,而AH的5,3,1位不确定。
(2)存储标志寄存器指令:指令格式:SAHF,将寄存器AH中的送入标志寄存器中
(3)标志进栈指令:指令格式:PUSHF,将堆栈指针SP-2,然后将16位标志寄存器内容送入SP指向的字单元。
(4)标志出栈指令:指令格式:POPF
四、地址传送指令:将存储单元的地址送寄存器
(1)装入有效地址:格式:LEA
DEST,SRC,源操作数必须是一个地址,目的是一个16位通用寄存器。作用是将SRC存储单元地址中的偏移量,即有效地址EA传送到一个16位通用寄存器中。指令执行对标志寄存器各位无影响。
(2)装入地址指针指令:格式:LDS DEST,SRC/LES DEST,SRC
五、算术运算类指令
加减乘除指令,这些指令可以对字节数据或字数据进行运算,参加运算的可以是无符号数,也可以是带符号数,带符号数用补码表示
(1)加法指令:指令格式:ADD
DEST,SRC。DEST只能是通用寄存器或存储器操作数,不能是立即数。
DEST和SRC不能都为存储器操作数。可以是字节操作数相加,也可以是字操作数相加。
(2)带进位加法指令:指令格式:ADC DEST,SRC
与ADD不同的是结果要加上进位标志CF的值。注意CF是本条指令执行之前的值。
(3)加1指令:指令格式:INC
DEST,目的操作数可以是任意的8位16位通用寄存器或存储器操作数,它不影响CF,INC指令主要用于某些计数器的计数和修改地址指针。
(4)减法指令:指令格式:SUB
DEST,SRC,,目的-源,再放入目的地址。不能同时为存储器操作数减法指令对借位标志的影响,若采用变减为加的运算方法,则产生的进位与CF标志结果相反。
(5)带借位减法:指令格式:SBB DEST,SRC,其实就是多减了一个CF和带进位加法类似。
(6)减1指令:指令格式:DEC DEST
(7)求负数指令:指令格式:NEG
DEST,也叫做取补指令。对进位CF的影响:只有当操作数为0的时候,CF才被置0。当字节操作数为-128,或字操作数为-32768时,执行NEG指令的结果操作数将无变化,但OF被置1.
六、位操作类指令:
(1)逻辑运算指令,逻辑运算指令共有4条,它们的指令格式分别是逻辑“与”指令:AND
DEST,SRC
逻辑“或”指令:OR DEST,SRC
逻辑“异或”指令:XOR DEST,SRC
逻辑“非”指令:NOT DEST
这四条指令都是执行按位逻辑运算。
逻辑指令对标志位的影响:NOT对标志无影响,而其余三条指令将根据结果影响SF、ZF和PF,而CF和OF总是置0,AF为不确定。可以对一些数分离其高位或低位,或者把最低位置1,最高位置0,取反等等。
(2)测试指令:TEST
DEST,SRC。与AND类似,但是运算的结果不送入目的操作数。主要用于测试某一操作数的一位或几位的状态。
(3)移位/循环移位指令:
1.算术移位:算术左移和算术右移
左移:SAL DEST,COUNT
右移:SAR DEST,COUNT(符号位不动)
2.逻辑移位:逻辑左移和逻辑右移
左移:SHL DEST,COUNT(和算术左移一样)
右移:最高位补0
3.循环移位:小循环:循环右移:ROR,循环左移;ROL
循环左移:不移CF,最高位到最低位,同时最高位还要到CF里面。
循环右移:最低位到最高位,最低位还要移到CF里。
大循环:带进位的循环左移和循环右移,也就是要把CF纳入到循环当中,最高位到CF,CF到最低位。
以上移位的八条指令的共通点:DEST为操作对象,COUNT决定移位的次数,移位的次数>1必须使用寄存器CL,移位次数是1时可以使用常数。在执行移位时,根据指令不同,每移位一次,最高位(左移)或最低位(右移)都要送到进位标志CF。
算术移位和逻辑移位,对标志位CF,PF,ZF,SF和OF,而AF不确定。后四条移位仅修改CF和OF。
对OF的影响:移位次数为1时,移位前后操作数的符号位发生变化,则OF->1,否则置0.移位次数大于1时,OF不确定。
算术左移相当于×2^n,移位后的结果不能发生溢出。
对于多字节或多字数据的移位,需要使用带进位循环移位指令。
七、处理器控制类指令:
(1)标志位操作指令,能直接操作的标志位有CF,IF和DF。
1.清除进位标志:CLC:置CF为0.
2.置1进位标志:STC:置CF为1
3.进位标志取反:CMC:CF的值取反
4.清除方向标志:CLD:置DF为0
5.置1方向标志:STD:置DF为1
6.清除中断标志:CLI:置IF为0
7.置1中断标志:CTI
(2)与外部事件同步的指令:ESC,HLT,WAIT,LOCK
(2)空操作指令:NOP,相当于延时,三个CPU的时钟周期。
3.3节——指令编码
四种编码格式:
(1)双操作数指令编码格式:
两种情形(一个操作数在寄存器中,另一个在寄存器或存储器中)(目的操作数在寄存器或存储器中,源操作数时立即数)
操作特征:1字节,又分为OPCODE,6bit,标明了该指令所执行的功能和两个操作数的来源,如果源操作数是立即数,则需要使用第二字节中REG字段作辅助操作码。有一个方向字段d,与寻址特征一起决定源操作数和目的操作数的来源。当SRC为IMM时,d字段无效。字节字段W,W=1为字,=0是字节
寻址特征:1字节:与操作特征部分的d结合,知道两个操作数的寻址方式和哪个寄存器。MOD,REG和R/M三个字段。REG字段确定一个操作数,另外两个一起确定一个操作数。d=1时,目的操由REG字段确定,源由另外两个确定。d=0反过来即可。REG字段确定一个操作数是某一通用寄存器的内容,使用的是寄存器寻址方式。
位移量:2字节。根据寻址特征中MOD和R/M字段确定的有效地址计算方法,位移量可以是以下三种情况之一:没有位移量
,1字节位移量disp8,2字节位移量disp16
立即数:两字节
(2)单操作数指令编码格式:这种编码适用于只有一个操作数的指令,如INC,DEC,移位循环之类的。
操作特征部分:OPCODE、V和W三个字段。V字段只有移位/循环指令中才有该字段。其它指令中没有该字段。V=0时,指令中常使用常数1作为移位或循环次数,V=1时,CL。
(3)与AX或AL有关的指令编码格式:这种编码格式用于隐含指定AX/AL作为一个操作数的双操作数指令。
(4)其它指令编码格式:如标志位操作指令、堆栈操作指令等。一般只有一个字节。有些单字节指令的编码中,将该字节划出部分位作为REG字段,例如PUSH指令。
第四章——汇编语言程序格式
4.1节:汇编语言种类及其格式
常用的汇编程序有:ASM,MASM,TASM,OPTASM。
汇编语言语句种类及其格式:语句可以分为指令语句和伪指令语句。
指令语句:可执行语句,一般格式为
标号:指令助记符,操作数;注释(多个操作数用逗号隔开)
标号字段:可选字段,后面必须有:。标号是一条指令的符号地址,代表了该指令的第一个字节存放的地址。一般放在一个程序段或子程序的入口处,控制程序的执行转到该程序位置,在转移指令中可直接引用这个标号
指令助记符(必须有的),表示这条语句要求CPU完成什么具体操作,可以在前面加上前缀,比如重复操作REP。
操作数字段:操作数数量不定。
注释字段:可有可无。不会影响到程序的。
伪指令语句:又叫做命令语句,本身并不产生对应的机器目标代码,只是告诉汇编程序对其后面的指令语句和伪指令语句的操作数应该如何处理。
格式:符号名 伪指令符,操作数;注释
符号名:可选的,可以是常量名,过程名,结构名,和记录名等。可以作为其他指令语句或伪指令语句的操作数,实际上是一个地址。
伪指令符:介绍功能,必须要有的。
操作数:和指令语句的操作数类似。
三、标识符:标号和符号名统称为标识符。标识符是由若干个字符构成的,具体什么规则可查。
4.2汇编语言数据:
操作数的基本组成部分,由数值和属性两部分构成,在说明数据时不仅需要指定其数值,还需要说明它的属性,比如是字节还是字。常数变量和标号是三类数据格式。
1.常数:不会改变,二进制数,八进制数,十进制数,十六进制数,注意十六进制数的常数的第一个数字是字母的话,为了与标识符加以区分,必须在前面加上0。实数。
在汇编程序里,可把实数转换为4字节八字节的二进制数。字符串常数,用单引号或双引号括起来的字符。ASCII码存储。
常数的使用方法,作指令语句的源操作数,在直接寻址方式,变址(基址)寻址方式或基址变址寻址方式中作位移量。在数据定义伪指令中使用。
2.变量:表示用来存放数据的存储单元。可以被改变。要给变量赋予一个符号名,即变量名。还要为这些存储单元置初值。
变量定义的一般格式:变量名 表达式1,表达式2……
DB:字节变量,DW:字,DD:4,DQ,DT依次增2.
变量的三个属性:段属性,偏移量属性,类型属性。
给变量赋初值的表达式有四种形式:数值表达式,?表达式,不带引号的问号“?”表示可以预置任意内容。字符串表达式。两个字符的存放顺序是前一个字符放在高地址,后一字符放低地址单元。注意,DW和DD指令不能用两个以上字符构成的字符串赋初值,否则将出错。
DUP表达式:多个多次。
变量可能在寻址中作为偏移量,在伪指令中表示取变量地址的偏移量。
3.标号:指令地址的别名。NEAR和FAR。(距离属性)
隐含方式,默认为NEAR属性也就是说只能被本段的转移指令和调用指令。
用LABEL伪指令给标号指定距离属性。还可以用来定义变量的属性,即改变一个变量的属性,如把自变量的高低字节作为字节变量来处理。
4.3符号定义语句。
两种符号定义语句:等值语句:符号名 EQU 表达式
等号语句:符号名=表达式,等号语句可以对一个符号进行多次定义。等号语句不能为助记符定义别名。等值语句与等号语句都不会为符号分配存储单元,因此所定义的符号没有段、偏移量和类型等属性。
4.4表达式与运算符。
大多与别的编程语言类似,SHR为右移,左边移出来的空位用0表示,SHL左移。注意移位运算符是对一个数,注意和移位指令进行区别。数字表达式一般由数字常量、数字变量、数字运算符和括号构成。与数字表达式相关的运算符如下:
①“+”、“—”、“×”、“/”及“mod”算术运算符
以上的算术运算符分别代表加、减、乘、除和取余数运算。例如,以x和y表示两个数字表达式,则:
x+y 表示x与y的和。 x—y 表示x与y的差。 x×y 表示x与y的乘积。 x/y 表示x除以y的商。
x:mod:y 表示x除以y的余数。 ②“rol”、“ror”、“shl”及“shr”移位运算符
以x和y表示两个数字表达式,以上的移位运算符代表的运算如下。 x:rol:y
表示将x循环左移y位。 x:ror:y 表示将x循环右移y位。 x:shl:y 表示将x左移y位。
x:shr:y 表示将x右移y位。
③“and”、“or”、“not”及“xor”按位逻辑运算符
以x和y表示两个数字表达式,以上的按位逻辑运算符代表的运算如下。 x:and:y
表示将x和y按位做逻辑与的操作。 x:or:y 表示将x和y按位做逻辑或的操作。 :not:y
表示将y按位做逻辑非的操作。 x:xor:y 表示将x和y按位做逻辑异或的操作。
4.关系运算符:EQ、NE、LT、LE、GT、GE。用来比较两个表达式的大小,两个表达式要不都是常数,或同一逻辑段中的变量。如果是常量的比较,则按无符号数进行比较,如果是变量的比较则比较它们的偏移量的大小。关系运算的结果只能是全1或全0。
一个重要的例子:
5.数值返回运算符:将变量或标号的某些特征值或存储单元地址的一部分提取出来。
SEG运算符:取变量或标号所在段的段基址。
OFFSET运算符:取变量或标号在段内的偏移量
TYPE运算符:取变量或标号的类型属性,并用数字形式表示,对变量来说就是取它的字节长度。
LENGTH运算符:取变量的长度,如果变量是用重复数据操作符DUP说明的,则LENGTH运算取外层DUP给定的值,如果没有用DUP说明,则LENGTH运算返回值总是1.
SIZE运算符:等于LENGTH*TYPE(只能用于变量)
6.属性修改运算符:对变量、标号或存储器操作数的类型属性进行修改或指定。
PTR运算符:类型 PTR
地址表达式(将地址表达式所指定的标号、变量或用其它形式表示的存储器地址的类型属性修改为“类型”所指的值)。修改是临时的。
HIGH/LOW运算符:将表达式的值分为高字节和低字节。如果表达式是一个常量,则将其分离成高8位和低8位,若果表达式是一个地址,则分离出它的高字节和低字节。
THIS运算符:一般与等值运算符EQU连用,用来定义一个变量或标号的类型属性。所定义的变量或标号的段基值和偏移量与紧跟其后的变量或标号相同。
4.5程序的段结构:
四个段寄存器CS,DS,ES,SS。使用伪指令来使用和定义这些段。
(1)段定义伪指令:SEGMENT和ENDS定义一个逻辑段,必须配对,表示定义的开始和结束。段名是由用户自己任意选定的。一个段的开始与结尾必须是一致的。
(2)定位类型:决定段的起始边界,第一个可存放数据的位置。不是段基址,可以有四种。PAGE(表示该段从一个页面的边界开始)。PARA类型表示该段从一个小节的边界开始,一般缺省值都是PARA。WORD,偶数字节地址开始。BYTE表示可以是任一地址值。
(3)组合类型:段与段之间的连接关系和定位。六种形式查就可以了。
(4)类别名。必须用单引号引起来,所用字符串可以任意选定,它不能使用程序中的标号、变量名或其他定义的符号。
二、段寻址伪指令:
ASSUME的作用是告诉汇编程序在处理源程序时,定义的段与哪个寄存器关联。ASSUME并不设置各个段寄存器的具体内容,段寄存器的值是在程序运行时实现的。
在一个代码段中可以有几条ASSUME伪指令,对于前面的设置,可以用ASSUME改变原来的设置。可以使用关键字NOTHING将前面的设置删除。
三、段寄存器的装入:
段基值装入到段寄存器里去。
(1)DS和ES的装入:在程序中使用数据传送模式传输
(2)SS的装入:两种方法,使用STACK参数,并在寻址伪指令语句中把该段与SS段寄存器关联。或使用类似于DS和ES的装入方法。
(3)CS的装入:必须在程序执行前装入CS和IP的值,因此,CS和IP的初始值就不能用可执行语句来装入。
4.6过程定义伪指令
(PROC/ENDP)过程其实就是一个程序。被用作CALL的目的操作数,它类同一个标号的作用。
过程名 PROC[NEAR/FAR]
……
RET
……
过程名 ENDP
4.7当前位置计数器$与定位伪指令ORG
将表达式的值赋给当前位置计数器,ORG语句后面的指令或数据以表达式给定的值作起始偏移量。
4.8标题伪指令TITLE
TITLE 标题名
功能:给程序指定一个标题,以便在列表文件中每一页的第1行都显示这个标题。字符串个数不能超过60。
4.9从程序返回操作系统的方法
一般有两种方法:
- 使用程序前缀PSP(100H字节),将代码段(CS)指向EXE程序的代码段,SS指向堆栈段,DS和ES并不指向用户程序的数据段和附加段,而是指向PSP。
在PSP首地址(第一、二字节)有一条软中断指令“INT
20H”(有关中断部分我会在以后说到),而这条指令的功能就是结束用户程序返回操作系统,因此可以用程序段前缀实现返回DOS,其步骤如下:
a、将程序编织成一个过程,并且将过程的类型属性设置为FAR
b、将PSP的起始逻辑地址压入堆栈,即将“INT
20H”指令的地址压入堆栈。由于EXE文件装入内存时DS和ES都是指向PSP的,因此用指令“PUSH
DS”就可以实现将PSP的起始逻辑地址压入堆栈的操作。
c、在程序编制而成的过程结束时使用返回指令RET,这样执行该指令时系统便会将保存在堆栈中的PSP起始逻辑地址弹出到CS和IP中,进而转去执行PSP首地址处的指令INT
20H, 从而实现返回DOS的目的。 - 用4CH系统功能调用实现返回
4CH系统调用功能是结束程序执行返回DOS,因此可以利用它来完成程序返回操作系统,其具体方法是在程序
结束时使用下列命令:
MOV AH, 4CH
INT 21H
但并不是任何程序都可以用这种方法来实现返回DOS的,只有返回DOS的主程序才能使用这种方式,而对于调用的子程序应该返回给的是调用程序而不是系统,所以不能用4CH实现返回。