第4章汇编语言程序设计.docx
- 文档编号:4082008
- 上传时间:2022-11-27
- 格式:DOCX
- 页数:27
- 大小:655.83KB
第4章汇编语言程序设计.docx
《第4章汇编语言程序设计.docx》由会员分享,可在线阅读,更多相关《第4章汇编语言程序设计.docx(27页珍藏版)》请在冰豆网上搜索。
第4章汇编语言程序设计
第四章汇编语言程序设计
内容简介:
本章着重介绍8086/8088汇编语言程序的基本结构、汇编语言的语法规则和程序设计的基本方法。
§4.1程序设计语言概述
§4.1.1计算机语言分类与特点
用于计算机程序设计的语言分为:
机器语言、汇编语言与高级语言三大类。
(1)机器语言
定义:
指令和数据都用二进制代码表示、计算机能够直接识别与执行的计算机语言叫机器语言。
特点:
①机器语言直接面向机器,编写、阅读和交流困难,通用性差;②任何其它语言编写的程序最终都必须翻译成机器语言,计算机才能理解与执行。
(2)汇编语言
定义:
将机器语言的指令代码、地址等用指令助记符、符号地址等来表示所形成的语言叫汇编语言,也叫符号语言。
特点:
①面向机器,通用性差;②汇编语言源程序与编译产生的机器语言程序(目标代码程序)之间存在一一对应关系。
③汇编语言程序能直接利用硬件系统的特性,能直接对位、字节、字、寄存器或存储单元、I/O端口进行操作;④用汇编语言编写的程序占用内存空间少、执行速度快、实时性好。
(3)高级语言
定义:
完全独立于机器的通用计算机语言。
特点:
①编写时不必考虑不同机器的结构特点,高级语言程序的通用性好;②不能在机器上直接执行,须经过编译或翻译才能运行;③很难利用不同CPU的特点与特性;④生成的目标代码长、占用空间多、执行时间长。
§4.1.2汇编语言程序的上机与处理过程
LINK
链接程序
MASM
汇编程序
EDIT
编写程序
机器语言执行程序
XXX.EXE
机器语言目标程序
XXX.OBJ
汇编语言源程序
XXX.ASM
§4.2汇编语言的程序结构与语法规则
§4.2.1汇编语言程序的框架结构
[举例]:
打印输出字符串“THISISASAMPLEPROGRAM.”
的汇编程序。
一源程序的结构特点
1源程序由若干逻辑段组成,每个逻辑段都有一个段名,由段定义语句(SEGMENT/ENDS)来加以定义;
2在代码段的起始处,用ASSUME命令说明各个段寄存器与逻辑段的关系。
并由用户设置各段寄存器(除代码段CS外)的初值,以建立这些逻辑段的可寻址性。
3每个逻辑段由若干行汇编语句组成,每行只有一条语句且不能超过128个字符,但一条语句允许有后续行,最后以回车作为语句的结束。
4整个源程序必须以END语句来结束,它通知汇编程序停止汇编。
END后面的标号START表示该程序执行时的起始地址。
5每一条语句最多由4个字段组成,各字段之间用空格分开。
6每个源程序在代码段中都必须含有返回到DOS操作系统的指令语句,以保证程序执行完毕后能自动返回到DOS状态。
二源程序与PCDOS的接口
为了保证程序执行完毕后能自动返回到DOS状态,可以采用以下两种方法。
方法一:
标准序方法;
方法如下:
(1)将用户程序的主程序定义为FAR过程,主程序的最后一条指令为RET;
(2)在主程序的开始处加入以下三条指令
PUSHDS
MOVAX,0
PUSHAX
方法二:
非标准序方法;
方法如下:
(1)将用户程序的主程序不定义为FAR过程(PROCFAR;ENDP;RET三句都不要);
(2)在代码段结束以前加入以下两条指令
MOVAH,4CH
INT21H
§4.2.2汇编语言的语句
语句的定义:
语句是汇编语言源程序的基本组成单位,它规定了一个基本的操作要求。
而源程序则是完成某个特定操作任务的一个语句序列。
一语句的种类与格式
1语句的种类
有三种基本语句:
指令语句、伪指令语句和宏指令语句。
(1)指令语句
对应于指令系统中的一条指令,是可执行语句。
汇编时可以产生与之一一对应的机器目标代码。
如:
MOVDS,AX;汇编时产生目标代码:
8EH与D8H。
(2)伪指令语句
CPU不执行的语句,只是汇编时给汇编程序提供汇编信息,如定义符号、分配存储单元、将程序分段等。
汇编时不产生目标代码,也叫“指示性语句”。
如:
SEGMENT/ENDS;就是伪指令语句,用来进行段定义。
(3)宏指令语句
是以某个“宏指令名字”定义的一段指令序列。
汇编时,凡有宏指令语句的地方都将用相应的指令系列的目标代码插入。
2语句的格式
(1)指令语句的一般格式
[标号:
][前缀]指令助记符[操作数][;注释]
(2)伪指令语句的格式
[名字]伪指令定义符[操作数][;注释]
(3)关于标号和名字
标号:
是给指令单元起的符号名称,后面必须有冒号(:
)。
标号代表指令所在存储单元的符号地址,可以作为转移、循环等指令的目标地址。
名字:
是给伪指令起的符号名称,后面没有冒号。
一般用于定义常量、变量、过程、逻辑段等。
标号与名字的选择必须符合相关规定,详见教材P144。
(4)关于助记符与定义符
助记符:
是指令语句的操作码部分的符号表示,指出指令语句的操作性质,根据需要可以加前缀。
定义符:
用于规定伪指令语句的操作功能。
助记符与定义符是语句中唯一不可缺省的部分。
(5)关于操作数
指令语句中的操作数是指令的操作对象。
伪指令语句中操作数的格式与含义相对较复杂,无统一规则。
(6)关于注释部分
注释部分用分号(;)开始,用来对语句的功能加以说明,帮助阅读理解程序,没有其他作用。
二语句中的操作数
操作数可以分为4类:
常量操作数、寄存器操作数、存储器操作数与表达式操作数。
1常量操作数
在汇编时已经确定其值、运行期间不变化的量为“常量”,用常量作为操作数就是常量操作数。
包括:
(1)数值常量。
如:
MOVAL,36H指令中的36H
(2)字符串常量
如:
MOVAL,‘A’指令中的字符串A
(3)符号常量
如:
MOVAL,XYZ指令中的符号XYZ
(XYZ需要预先定义)
2寄存器操作数
用寄存器作为操作数就是寄存器操作数。
如:
MOVAL,36H指令中的AL就是寄存器操作数。
3存储器操作数
存储器操作数分为标号与变量两种:
(1)标号--是某条指令所存放单元的符号地址,这个地址一定在代码段内。
如:
在如下程序段中:
LP1:
INCCX
….
JMPLP1
标号LP1是指令INCCX所在存储单元的符号地址,在指令JMPLP1中作为操作数,属于存储器操作数。
(2)变量—变量是指存放在存储单元中的值,这些值是可变的。
但为了便于对变量的访问,变量常常以变量名的形式出现在程序中。
而变量名可以认为是存放变量的存储单元的符号地址,一般出现在数据段、附加段或堆栈段中。
如:
XDB0
这里:
定义了一个字节变量,初值为0,占据内存中的一个字节单元。
变量本身是存储单元的内容,但无法直接表示它,只好用该单元的地址X来表示,这里X是变量名。
所以:
MOVAL,X指令中,X属于存储器操作数。
(3)标号与变量都与存储器地址相关联,都具有以下三种属性:
①段属性(SEGMENT)--段基址,即标号与变量所在段的段地址。
②偏移量属性(OFFSET)--即标号与变量所在的单元的偏移地址
③类型属性(TYPE)--标号的类型属性是指标号与使用它的指令之间的距离远近。
即:
当标号作为转移指令的目标操作数时,若是段内转移,这个标号的类型属性是“近”(NEAR),若是段间转移,这个标号的类型属性是“远”(FAR)。
变量的类型属性是指变量存取单元的字节数大小,类型有字节(BYTE)、字(WORD)、双字(DWORD)等。
4表达式操作数
表达式也可以作为操作数,它由操作数与操作符(或叫运算符)组成。
(1)表达式的分类
①数值表达式—在汇编时产生一个数值,只有大小而无其他属性。
如:
MOVBH,3+5;指令中,3+5是一个表达式操作数,由运算对象(操作数)3、5与操作符+组成。
由于3+5只产生一个数值8(在汇编的时候产生),因此是数值表达式。
②地址表达式—若汇编时,对表达式运算的结果是存储器地址,那么该表达式就是地址表达式。
如:
MOVBX,1000H
MOVAL,[BX+24H]
汇编时,对表达式[BX+24H]的运算结果是[1024H],这是存储器的一个偏移地址。
因此[BX+24H]就是一个地址表达式操作数。
(2)表达式中的运算符(操作符)
详见教材P146的表4—1
主要有:
算术运算符、逻辑运算符、关系运算符、分析运算符与合成运算符等几种。
①算术运算符;有+、-、*、/与MOD(求余)等。
[举例]:
DAEQU300
MOVAX,DA-80;汇编时,等价于220;
MOVBX,DAMOD100;汇编时,等价于0;
MOVCX,DA/100;汇编时,等价于3;
②逻辑运算符;
有AND、OR、XOR与NOT,只适用于数值表达式,运算的对象只能是常数,得到的结果也是常数。
[举例]:
MOVAL,NOT80H
汇编时,等价于MOVAL,7FH
③关系运算符
有EQ(等于)、NE(不等)、LT(小于)、GT(大于)、LE(小于等于)、GE(大于等于)几种。
关系运算符的两个操作数必须同是数值或同是一个段内的两个存储器地址。
比较时,如果关系不成立(假),则结果为0,若关系成立(真),则结果为全1。
[举例]:
MOVAX,10HGT16
汇编时,相当于:
MOVAX,0;因为比较结果为假。
MOVCX,10HEQ16
汇编时,相当于:
MOVAX,0FFFFH;因为比较结果为真。
④分析运算符。
在下一节讲
⑤合成运算符。
在下一节讲
⑥关于各运算符的优先级见教材P147表4—2。
§4.3汇编语言的伪指令语句
80X86/Pentium宏汇编提供符号定义、数据定义、程序分段定义、模块定义、过程与宏定义、条件汇编和列表控制等伪指令语句。
我们只要求掌握:
8086/8088系统基本伪指令语句。
§4.3.1基本伪指令语句
一符号定义伪指令语句
功能:
符号定义伪指令语句主要是给程序中的表达式或数据赋予一个符号名,以方便程序设计与修改。
1.等值语句EQU
格式:
符号名EQU表达式(或数据)
[举例]:
X1EQU312
X2EQUX1+2
COUNTEQUCX
LiEQUMOV
2.等号语句=
格式:
符号名=表达式
[举例]:
XX=60
XY=XX+1
其功能与EQU类似,但EQU语句不能对同一符号名重复定义,而等号语句则可以。
二数据定义伪指令语句
功能:
数据定义语句用于定义变量;指定变量的类型和名称,并为变量分配存储单元。
1格式
[变量名]数据定义符操作数[,操作数]…[,操作数]
其中:
操作数是赋给变量的初值;
变量名是可选项;
数据定义符一般为下列三种伪指令之一:
(1)DB—定义字节变量,每个变量占一个字节的存储单元。
(2)DW—定义字变量,每个变量占二个字节的存储单元。
数据的低位部分在低地址,高位部分在高地址。
(3)DD—定义双字变量,每个变量占四个字节的存储单元。
数据的低位部分在低地址,高位部分在高地址。
▲经过定义的变量名有三个属性,即:
类型属性、段属性(段地址)与偏移量属性(偏移地址),相关概念在上节已讲到。
▲若变量表达的是一个数组,则其类型属性为数组的单个元素的类型属性。
2举例
[举例1]:
最普通的变量定义形式
XDB25H;定义变量X为字节变量,初值为25H。
YDW4142H;定义变量Y为字变量,初值为4142H。
ZDD12345678H;定义变量Z为双字变量,初值为
;123456H。
它们在内存中的存放方式如下:
[举例2]:
定义变量,但不赋予具体的初值
ADB?
BDW?
[举例3]:
数组的定义
XXDB1,2,4,56H,68H;定义一个字节数组XX,共有
;5个元素
存放方式如下:
YYDW1122H,3344H;定义一个字数组YY,共有
;2个元素
存放方式如下:
[举例4]:
重复单元的表达
XYDB0,0,0,0,0,0;可以写成
XYDB6DUP(0)
其中:
DUP为重复数据定义操作符。
下列数据定义:
XY1DB5DUP(12H,34H)
的存放方式见下图:
[举例5]:
字符串的定义
▲一般用DB来定义字符串,实际存放时,每一个字符用其ASCII来表示。
STRING1DB‘ABCD’
存放方式如下:
41H为A的ASCII码;
….
44H为D的ASCII码。
▲但当一个字符串的长度不超过两个字符时,也可用DW来定义。
STRING2DW‘AB’,‘CD’
存放方式如下:
请注意:
上述数据定义
伪指令语句定义了两个
字符串,每个字符串的
长度不超过两个字符。
3分析运算符与合成运算符的使用
(1)分析运算符(数值返回运算符)
分析运算符(操作符)用于存储器操作数,返回它们的属性值。
这些操作符是:
SEG、OFFSET、TYPE、SIZE、LENGTH。
格式:
分析操作符标号或变量
①SEG和OFFSET操作符
▲SEG操作符返回标号或变量的段地址。
▲OFFSET操作符返回标号或变量的偏移地址。
②TYPE、SIZE和LENGTH操作符
▲TYPE操作符返回标号或变量的类型属性,是一个数值;
对变量而言:
字节变量,类型值为1;字变量,类型值为2;双字变量,类型值为4。
(实质也就是每个变量所占用的字节存储单元的个数)。
对标号而言:
返回的是NEAR(-1)或FAR(-2)类型值。
[举例]:
若已定义X1DB25H则指令:
MOVAL,TYPEX1汇编时TYPEX1的返回值为1。
▲LENGTH操作符返回变量用DUP重复定义的数据项总数。
如果存储区不是用DUP来定义,则返回1。
[举例]:
若已定义
Y1DB100DUP(0)
Y2DW100DUP(68H)
Y3DD200DUP(11H)
Y4DB23H,0,45H,66H
则表达式:
LENGTHY1=100
LENGTHY2=100
LENGTHY3=200
LENGTHY4=?
▲SIZE操作符返回TYPE和LENGTH的乘积,其物理意义是为变量所分配的字节存储单元总数。
[举例]:
变量Y1、Y2、Y3、Y4的定义见上例。
则:
SIZEY1=1*100=100
SIZEY2=2*100=200
SIZEY3=4*200=800
(2)合成运算符(修改属性运算符)
合成运算符用于临时修改存储器操作数的某些属性,以满足不同的访问要求。
常用的有:
PTR、LABEL和THIS三个。
①PTR操作符
PTR用来临时修改存储器操作数的类型属性,但保留原来的段属性与偏移地址属性不变。
格式:
临时指定的类型PTR标号或变量
[举例]:
已定义:
Y4DB23H,0,45H,66H
很显然,指令MOVBX,Y4由于类型不对是一条错误指令。
但指令:
MOVBX,WORDPTRY4就是对的。
其实质是:
MOVBX,0023H
注意:
字节变量Y4修改成字变量只在该指令中临时有效,不改变它在其他地方使用的性质。
②LABEL操作符
LABEL操作符为当前存储单元定义一个指定类型的标号或变量,使它们具有多重属性和名字。
格式:
标号或变量名LABEL新类型
[举例]:
Z2LABELWORD
Z1DB12H,33H,25H,89H
上述定义中,数据块12H,33H,25H,89H具有双重属性,一是变量Z1命名的字节属性,二是Z2命名的字属性。
见下图:
所以:
MOVAL,Z1执行的结果是:
AL=12H
MOVAX,Z2执行的结果是:
AX=3312H
而指令MOVAL,Z2或MOVAX,Z1都是错误的。
③THIS操作符
THIS操作符与EQU配合使用,与LABEL操作符具有同样效果。
格式:
标号或变量名EQUTHIS新类型
三程序分段伪指令语句
1段定义伪指令SEGMENT/ENDS
段定义伪指令SEGMENT/ENDS用来将程序分成若干逻辑段。
格式:
段名SEGMENT[定位类型][组合类型][‘类别名’]
(段体)
段名ENDS
功能:
指出段名及段的各种属性,并表示段的开始与结束位置。
▲段名是用户定义段的名称,用来表示段在内存中的起始位置,具有段地址与偏移地址两个属性。
▲定位类型用来告诉LINK(链接)程序,本段首地址的边界定位方式。
默认为PARA(节),即段的起始地址必须为16的倍数。
一般采用默认方式。
▲组合类型用来告诉LINK(链接)程序,多个模块链接时,本段与其它模块的同名段的组合链接关系。
默认为NONE,表明本段与其它同名段无组合关系。
一般情况下:
数据段、附加段及代码段采用NONE组合类型。
堆栈段一般采用STACK组合类型,这样可以使SS与SP在链接时自动赋值。
另外,还有一种组合类型是:
AT表达式:
表示本段装在表达式的值所定位的段地址上。
▲类别名表示该段的类别,链接时,同名同类别的段在内存中依顺序连续存放。
一般情况下:
数据段、附加段及代码段缺省
堆栈段一般采用‘STACK’类别名
2段寄存器说明伪指令ASSUME
格式:
ASSUME段寄存器名:
段名[,段寄存器名:
段名]…
ASSUME伪指令一般出现在代码段SEGMENT伪指令的后面,用来说明各个段寄存器与逻辑段的关系
[举例]:
DATASEGMENT
XDB?
DATAENDS
EXTRASEGMENT
YB?
EXTRAENDS
STACKSEGMENTSTACK‘STACK’
ZDB100DUP(0)
STACKENDS
CODESEGMENT
ASSUMECS:
CODE,ES:
EXTRA,DS:
DATA,SS:
STACK
上述的ASSUME语句就说明了CODE、EXTRA、DATA与STACK各是什么段。
3组定义伪指令GROUP
用于将程序中的几个不同名的段集中成一个组,并赋予一个组名,使它们都装在一个64K的物理段中。
格式:
组名GROUP段名[,段名]…
[举例]:
BIGDSGROUPDATA1,DATA2
DATA1SEGMENT
XXDB12H,23H
DATA1ENDS
DATA2SEGMENT
YYDW0
DATA2ENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
BIGDS
这个伪指令用得比较少。
4指定地址伪指令ORG
ORG伪指令用来强行指定地址计数器的当前值,以改变段内在该伪指令以后的代码或数据存放的偏移地址。
格式1:
ORG表达式
格式2:
ORG$+表达式
格式1直接将表达式的值作为当前地址计数器的值;
格式2将当前地址计数器的值加上表达式后送入地址计数器。
[举例]:
DATASEGMENT
ORG10H
XDB20H,30H;在数据段中,偏移地址为
;10H处开始存放20H,30H
ORG$+5
YDB40H,50H
;在存放了20H与30H后,当前地址计数器变的值为12H,遇到伪指令ORG$+5后,当前地址计数器变为17H,因此,在数据段的偏移地址为17H处开始存放40H、50H。
四模块定义与通信(不作要求)
五过程与宏定义伪指令语句
1过程定义伪指令
定义:
所谓过程是一段可由其他程序用CALL指令调用的程序,执行完后用RET指令从过程返回原调用处。
如果整个源程序由主程序和若干子程序组成,则主程序与每一个子程序都可以作为一个过程,且都应包含在代码段中。
过程定义格式:
过程名PROC[NEAR]/FAR
过程体
RET
过程名ENDP
说明:
▲过程的属性有NEAR与FAR两种。
▲当属性是NEAR(近过程)时,该过程只能被段内的其他程序调用;缺省时,属性是NEAR。
▲当属性是FAR(远过程)时,该过程可以被任何段中的其他程序调用。
▲一个过程可以有多个RET指令,但至少要执行到一个RET指令。
[举例]:
2宏定义伪指令
背景知识:
若源程序中要经常用到某一程序段,一个方法是可以将该程序段定义成一个子程序(过程),要用时可以用CALL指令进行调用。
但缺点是:
过程的进入与返回都要占用一定时间。
另一个方法是将该程序段定义成一条宏指令,源程序中要用到该程序段时,只要插入该宏指令就行了。
(1)宏的定义、调用与扩展
宏定义格式:
宏指令名MACRO[形参,形参…]
宏体
ENDM
宏调用格式:
宏指令名[实参,实参…]
说明:
▲宏指令名必须是唯一的;
▲宏指令一经定义,就像指令系统中增加了一条新指令一样,在程序中可以像使用普通的指令一样使用宏指令;
▲宏指令必须先定义后调用;
▲形参为可选项。
[举例1]:
不带参数的宏指令;
将AL中的内容算术左移4位,就可定义一条宏指令来实现其功能。
当汇编到SHIFT这条宏指令时,就将对应的宏体插入到源程序中宏指令所在的位置,来代替这条宏指令以产生目标代码,这就是宏扩展。
[举例2]:
带参数的宏指令;
上述例题中的宏有两个限制,一是只能对AL的内容实现左移,二是必须移动4位,如果希望每次能用不同的寄存器移动不同的次数,则可以使用带参数的宏指令。
(2)取消宏指令伪指令PURGE
可以用PURGE伪指令来注销已经定义的宏指令。
格式:
PURGE宏定义名
3过程与宏的区别
(1)宏指令语句由宏汇编程序识别,在程序汇编时完成扩展,到目标代码时就没有宏指令的概念了。
而过程的调用是在程序执行时完成的。
(2)宏指令操作可以实现参数的直接传递与接收,而过程调用时无法直接带有参数,只能通过堆栈、寄存器等间接传递。
(3)宏指令的使用只能简化源程序的编写,缩短源程序的长度,并没有缩短目标代码的长度。
而过程可以缩短源程序与目标代码的长度,有效节省内存空间。
(4)引入宏指令并不会增加执行程序时的额外时间开销。
但过程的调用中过程的进入、返回及堆栈保护等会增加额外时间开销。
六列表伪指令语句(不作要求)
七条件汇编伪指令语句(不作要求)
§4.3.280X86/Pentium扩展伪指令语句(不作要求)
§4.4汇编语言程序设计基础
§4.4.1程序设计的基本过程
见教材P165
§4.4.2程序的基本
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第4章 汇编语言程序设计 汇编语言 程序设计