第4章程序设计.docx
- 文档编号:4902099
- 上传时间:2022-12-11
- 格式:DOCX
- 页数:23
- 大小:88.14KB
第4章程序设计.docx
《第4章程序设计.docx》由会员分享,可在线阅读,更多相关《第4章程序设计.docx(23页珍藏版)》请在冰豆网上搜索。
第4章程序设计
第4章汇编语言程序设计
一、内容简介:
1汇编语言语法
2汇编语言程序实现
3汇编语言程序设计方法及应用
顺序结构程序设计;分支程序设计;循环程序设计;子程序设计;宏
系统功能调用
4汇编语言程序设计举例
二、教学目标:
熟练掌握8086/8088微处理器汇编语言程序设计的方法。
三、重点内容:
汇编语言程序设计方法及应用
四、教学时数:
12
4.1汇编语言语法
4.1.1源程序的结构及组成
1.
汇编语言程序结构
1)段式结构
2)语句
指令语句:
产生目标机器代码,供CPU执行并完成特定操作。
[标号:
][前缀]指令助记符[操作数][;注解]
其中用方括号括起来的部分,可以有也可以没有。
每部分之间用空格(至少一个)分开,一行最多可有132个字符。
1.标号
是给指令或某一存储单元地址所起的名字。
可由下列字符组成:
字母:
A~z;数字:
0~9;特殊字符:
?
、·、@、一、$。
数字不能作标识符的第一个字符,而圆点仅能用作第一个字符。
标识符最长为31个字符。
当标识符后跟冒号时,表示是标号。
它代表该行指令的起始地址;当标识符后不带冒号时,表示变量;伪指令前的标识符不加冒号。
2.指令助记符
表示不同操作的指令,可以是8088的指令助记符,也可以是伪指令。
3.操作数
是指令执行的对象。
依指令的要求,可能有一个、两个或者没有,
例如:
RET;无操作数
COUNT:
INCCX;一个操作数
如果是伪指令,则可能有多个操作数,例如:
COSTDB3,4,5,6,7;5个操作数
MOVAX,[BP十4];第二个操作数为表达式
4.注解
该项可有可无,是为源程序所加的注解,用于提高程序的可读性。
伪指令语句:
不产生机器码,告诉汇编程序如何对源程序进行正确的翻译和编排
[标号:
][伪指令助记符][操作数][;注解]
宏指令语句:
若干语句组成的程序段,宏指令语句用于定义宏。
[标号:
]宏指令参数1,…[;注解]
2.汇编语句中的名字
一般规定:
1、程序主体:
一个程序可有多个段,每段可有多个程序;每段由SEGMENT语句开始,ENDS语句结束;程序结束用END。
2、大、小写:
任选
3、标号区:
不能用数字开头,不能用保留字
4、指令区:
操作码助记符区(指令助记符,伪指令助记符)
5、操作数区:
4.1.2汇编语言伪指令
指令——助记符,汇编时生成相应指令代码
伪指令——汇编时解释执行,用于“控制和指挥”汇编操作
共分8种:
·数据定义
·符号定义
·段定义
·过程定义
·宏定义及宏调用
·模块定义与结束
·处理器方式
·条件
·列表
·其他
1.数据定义伪指令
该类伪指令用来定义存储空间及其所存数据的长度。
·DB:
定义字节,即每个数据是1个字节。
·DW:
定义字,即每个数据占1个字(2个字节)。
·DD:
定义双字,即每个数据占2个字。
低字部分在低地址,高字部分在高地址。
·DQ:
定义4字长,即每个数据占4个字。
·DT:
定义10个字节长,用于压缩式十进制数,
例如:
DATA1DB5,6,8,100
DATA2DW7,287
TABLEDB?
;表示在TABLE单元中存放的内容是随机的
当一个定义的存储区内的每个单元要放置同样的数据时,可用DUP操作符。
一般格式:
COUNTDUP(?
),COUNT为重复的次数,“( )”中为要重复的数据。
如:
BUFFERDB100DUP(0);表示以BUFFER为首地址的100个字节中存放00H数据
BUFFER1DB100DUP(3,5,2DUP(10),35),24,‘NUM’)
想一想存储区的情况?
2.符号定义伪指令EQU、=、及PURGE
·EQU伪指令给符号定义一个值。
在程序中,凡是出现该符号的地方,汇编时均用其值代替,
如:
TIMESEQU50
DATADBTIMESDUP(?
)
上述两个语句实际等效于如下一条语句:
DATADB50DUP(?
)
·“=”伪指令可给初始变量赋值。
如:
COUNT=100;COUNT=100
TIME=50;TIME=50
·PURGE伪指令用于释放由EQU伪指令定义的变量,使这些变量可以被重新定义。
PURGETIMES;释放TIMES变量
TIMESEQU2;重新定义
·LABLE伪指令用于定义变量或标号的类型,变量或标号的段属性和偏移属性由该语句所处的位置决定。
如:
AREAWLABELWORD;字类型相同数据区
ARWABDB100DUP(?
);字节类型
3.段定义伪指令SEGMENT和ENDS
一般来说,一个完整的汇编源程序由3个段组成,即堆栈段、数据段和代码段。
段定义伪指令可将源程序划分成若干段,以便生成目的代码和连接时将各同名段进行组合。
段定义伪指令一般格式为:
段名SEGMENT[定位类型][组合类型][类别]
段名ENDS
SEGMENT和END5应成对使用,缺—不可。
其中段名是不可省略的。
其它是可选项,是赋予段名的属性,可以省略。
例如:
DATASEGMENT
DW20DUP(?
)
DATAENDS
4.设定段寄存器伪指令ASSUME
一般格式:
ASSUME段寄存器:
段名[,段寄存器:
段名,……]
功能:
通知汇编程序,哪一个段寄存器是该段的段寄存器,以便对使用变量或标号的指令汇编出正确的目的代码。
在段名中,CODE表示代码段,DATA表示数据段,STACK表示堆栈段。
由于ASSUME伪指令只指明某一个段地址应存于哪一个段寄存器中,并没有包含将段地址送入该寄存器的操作。
因此要将真实段地址装入段寄存器还需用汇编指令来实现。
这一步是不可缺少的。
例如,CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,SS:
STACK
MOVAX,DATA;DATA段值送AX
MOVDS,AX;AX内容送DS,DS才有实际段值
CODEENDS
当程序运行时,由于DOS的装入程序负责把CS初始化成正确的代码段地址,SS初始化为正确的堆栈段地址,因此用户在程序中就不必设置。
但是,在装入程序中DS寄存器由于被用作其它用途,因此,在用户程序中必须用两条指令对DS进行初始化,以装入用户的数据段地址。
当使用附加段时,也要用MOV指令给ES赋段地址。
5.定义过程的伪指令PROC和ENDP
在程序设计中,可将具有一定功能的程序段看成为一个过程(相当于一个子程序),它可以被别的程序调用。
一个过程由伪指令PROC和ENDP来定义,其格式为:
过程名PROC[类型]
过程体
RET
过程名ENDP
其中过程名是为过程所起的名称,不能省略,过程的类型由FAR(远过程,为段间调用)和NEAR(近过程,在本段内调用)来确定,如果缺省类型,则该过程就默认为近过程。
ENDP表示过程结束。
过程体内至少应有一条RET指令,以便返回被调用处。
过程可以嵌套,也可以递归使用。
例如一个延时100ms的子程序,其过程可定义如下,
DELAYPROC
PUSHBX
PUSHCX
MOVBL,10
;延时10ms,改变BL和CX中的值,即可改变延时时间。
AGAIN:
MOVCX,2801;
WAIT;LOOPWAIT
DECBL
JNZAGAIN
POPCX
POPBX
RET
DELAYENDP
CALLDELAY;调用该过程
远过程调用时被调用过程必定不在本段内。
例如,有两个程序段,其结构如下:
CODE1SEGMENT
ASSUMECS:
CODE1
FARPROCPROCFAR
RET
FARPROCENDP
CODE1ENDS
CODE2SEGMENT
ASSUMECS:
CODE2
CALLFARPROC
…..
CODE2ENDS
CODE1段中的FARPROC过程被另一段CODE2调用,故为远过程。
6.宏指令
在汇编语言书写的源程序中,若有的程序段要多次使用,为了简化程序书写,该程序段可以用一条宏指令来代替,而汇编程序汇编到该宏指令时,仍会产生源程序所需的代码。
宏指令的一般格式为:
宏指令名MACRO[形式参量表]
宏体
ENDM
例如:
SHIFTMACRO
MOVCL,4
SALAL,Cl
ENDM
这样定义以后,凡是要使AL中内容左移4位的操作都可用一条宏指令SHIFT来代替。
宏指令与子程序有许多类似之处。
它们都是一段相对独立的、完成某种功能的、可供调用的程序模块,定义后可多次调用。
但在形成目的代码时,子程序只形成一段目的代码,调用时转来执行。
而宏指令是将形成的目的代码插到主程序调用的地方。
因此,前者占内存少,但执行速度稍慢;后者刚好相反。
七、ORG伪指令
ORG伪指令规定了在某一段内,程序或数据代码存放的起始偏移地址。
一般格式:
ORG<表达式>
例如:
DATASEGMENT
BUFF1DB23,56H,‘EOF’
ORG2000H
BUFF2DB‘STRING’
DATAENDS
上述变量定义中,BUFF1从DATA段偏移地址为0的单元开始存放,而BUFF2则从DATA段偏移为2000H的单元开始存放,两者不是连续存放。
八、汇编结束伪指令END
该伪指令表示源程序的结束.令汇编程序停止汇编。
因此,任何一个完整的源程序均应有END指令。
一般格式:
END[表达式]
其中表达式表示该汇编程序的启动地址。
例如:
ENDSTART;表明该程序的启动地址为START。
4.1.3汇编语句
由汇编语言编写的源程序是由许多语句(也可称为汇编指令)组成的。
每个语句由1~4个部分组成,其格式是:
[标号]指令助记符[操作数][;注解]
1.常量
·常数:
二进制、八进制、十六进制、十进制或ASCII码
表示范围-32768~+32767
·标号:
数据变量标号:
段值——所在段的地址
偏移量——数据变量的位置地址与其段地址之差值
类型——数据变量是字节、字或双字
程序位置标号:
NEAR——段内调用或转移
FAR——段间调用或转移
2.变量
可以具有不同值的量。
通过数据定义伪指令定义,与某个存储区关联。
类型有:
字节型BYTE,字型WORDD,双字型DWORD,4字型DQ,5字型DT等
3.汇编语言的运算符
1).算术运算符、逻辑运算符和关系运算符
①算术运算符可以应用于数字操作数,结果也是数字。
而应用于存储器操作数时,只有+、-运算符有意义。
2).分析运算符SEG、OFFSET、TYPE、SIZE和LENGTH
·SEG和OFFSET分别给出一个变量或标号的段地址和偏移量。
例如,定义:
SLOTDW25
则:
MOVAX,SLOT;从SLOT地址中取一个字送入AX
MOVAX,SEGSLOT;将SLOT所在段的段地址送入AX
存储器操作数的类型属性及返回值
字节
1
字
2
双字
4
NEAR
-1
FAR
-2
MOVAX,OFFSETSLOT;将SLOT所在段的段内偏移地址送AX
·TYPE操作符返回一个表示存储器操作数类型的数值。
各种存储器地址操作数类型部分的值如表3-1所示。
·LENGTH和SIZE操作符只应用于数据存储器操作数。
(用DB/DW/DD等定义的操作数)
LENGTH返回一个与存储器地址操作数相联系的单元数,
SIZE操作数返回一个为存储器操作数分配的字节数。
例如:
若MULT-WORDDW50DUP(0)
则LENGTH(MULT-WORD)=50
SIZE(MULT-WORD)=100
注意:
SIZE(X)=(LENGTHX)*(TYPEX)
3).属性运算符
属性运算符用来给指令中的操作数指定一个临时属性,而暂时忽略当前的属性。
常用的有:
(1)合成运算符PTR
它作用于操作数时,则忽略了操作数当前的类型(字节或字)及属性(NEAR或FAR),而给出一个临时的类型或属性,
一般格式:
类型PTR表达式
功能:
建立一个存储器地址操作数,它与其后的存储器地址操作数有相同的段地址偏移量,但有不同的类型。
例如:
SLOTDW25
此时SLOT已定义成字单元。
若我们想取出它的第一个字节内容,则可用PTR对其作用,使它暂时改变为字节单元,即MOVAL,BYTEPTRSLOT
4.表达式
算术表达式:
算术运算符组成的表达式,+、-、×、÷、MOD(取余数)。
是由运算符和操作数组成的序列,在汇编时产生一个确定的值。
这个值可以仅表示一个常量,也可以表示一个存储单元的偏移地址,相应的表达式称为常量表达式和地址表达式。
1).常数
汇编语言语句中出现的常数可以有7种:
①二进制数后跟字母B,如01000001B。
②八进制数后跟字母Q或O,如202Q或202O。
③十进制数后跟D或不跟字母,如85D或85。
④十六进制数后跟H,如56H,0FFH。
注意,当数字的第一个字符是A~F时,在字符前应添加一个数字0,以示和变量的区别。
另有,十进制浮点数、十六进制实数、字符和字符串
2).常量操作数
常量操作数是一个数值操作数,一般是常量或者是表示常量的标识符。
可以为数字常量操作数或字符串常量操作数。
前者可采用二进制、八进制、十进制或十六进制等计数形式;而后者则为相应字符的ASCII码。
3).存储器操作数
存储器操作数是一个地址操作数,代表一个存储单元的地址,通常以标识符的形式出现。
存储器操作数可以分为变量及标号两者类型,如果存储器操作数所代表的是某个数据在数据段、附加段或堆栈段中的地址,那么这个存储器操作数就称为变量;如果存储器操作数所代表的是某条指令代码在码段中的地址,那么这个存储器操作数称为标号。
变量所对应的存储单元内容在程序的运行过程中是可以改变的,标号通常作为转移指令或调用指令的目标操作数,在程序运行过程中不能改变。
存储器操作数有三个方面的属性。
(1)段地址:
即存储器操作数所对应的存储单元所在段的段地址;
(2)偏移地址:
即存储器操作数所对应的存储单元在所在段内的偏移地址;
(3)类型:
变量的类型是相应存储单元所存放的数据项的字节数;而标号的类型则反映了相应存储单元地址在作为转移或调用指令的目标操作数时的寻址方式,可有两种情况,即NEAR和FAR。
具体值可见表3-1
4).常量表达式:
由常量操作数及运算符构成,在汇编时产生一个常量。
如PORT、VAL十1、OFFSETSUM、SEGSUM、TYPECYCLE等。
5).地址表达式:
由存储器操作数与运算符构成,必须有明确的物理意义。
例如SUM+2、CYCLE-5
表达式SUM+2、CYCLE-5的值仍然是一个存储器操作数,该存储器操作数的段地址与类型属性分别与存储器操作数SUM及CYCLE相同,但偏移地址分别比SUM及CYCLE大2或小5。
表达式是在汇编时计算的,而变量单元的内容在程序的运行过程中可以改变。
逻辑表达式:
逻辑运算符组成的表达式,AND、OR、XOR、NOT,逻辑运算按位进行。
关系运算表达式:
关系运算符组成的表达式,EQ(等于)、NE(不等)、LT(小于)、GT(大于)、GE(大于等于);满足条件,表达式的值为1,否则为0。
分析运算表达式:
把存储器操作数分解为几个组成部分。
合成运算表达式:
把这些组成部分综合为存储器操作数。
4.2汇编语言程序实现
4.2.1汇编语言程序实现步骤
图4-1汇编语言程序实现流程
1.编辑源程序
字处理,如:
EDIT,WORD等
2.汇编
用汇编工具将源文件XX.ASM进行汇编,生成目标文件XX.OBJ。
3.连接
用连接工具将目标文件XX.OBJ进行连接,生成可执行文件XX.EXE。
4.程序运行
提示符下键入文件名。
查错→修改源程序→汇编、连接、运行。
5.程序调试及结果查看
动态调试工具DEBUG。
4.2.2COM文件的生成
1.把EXE文件转换成COM文件
2.用DEBUG生成COM文件
4.2.3可执行程序的装入
1.EXE程序
图4-2程序连接与定位过程图
2.COM文件
图4-3COM文件内存映像
3.程序段前缀
图4-4程序段前缀结构
4.2.4汇编语言和操作系统MS-DOS的接口
1.标准方法
1)将应用程序的主程序定义成一个FAR过程,其最后一条指令为RET。
2)在代码段的主程序开始部分用三条指令,把PSP中INT20H指令的段地址(CS=DS=ES)及偏移地址(0)压入堆栈。
PUSHDS
MOVAX,0
PUSHAX
2.用DOS功能调用4CH
在用户程序中不定义过程段,只在代码段结束之前增加2条语句:
MOVAH,4CH
INT21H
内中断21H是操作系统向用户提供服务程序的窗口,4CH号功能服务用于结束用户程序,操作系统收回CPU的控制权。
类似功能有INT20H。
4.3汇编语言程序设计方法及应用
4.3.1概述
1.程序设计步骤
·分析问题,建立数学模型
·确定解决问题的算法
·绘制流程图或结构图
·分配存储空间及工作单元(包括寄存器)
·编写程序
·静态检查
·上机运行调试
2.结构化程序设计
·程序质量标准“清晰第一,效率第二”
·程序设计过程“自顶向下,逐步求精”
·三种基本结构:
顺序、分支、循环
4.3.2顺序结构程序设计
简单程序设计是没有分支,没有循环的直线运行程序,程序执行按照IP内容自动增加的顺序进行。
【例1】利用查表法计算平方值。
已知0~9的平方值连续存在以SQTAB开始的存储区域中,求SUR单元内容X的平方值,并放在DIS单元中。
假定0≤X≤9且为整数。
分析:
建立平方表,通过查表完成。
STACKSEGMENT
DB100DUP(?
)
STACKENDS
DATASEGMENT
SURDB?
DISDB?
SQTABDB0,1,4,9,16,25,36,49,64,81;0~9的平方表
DATAENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,SS:
STACK,ES:
DATA
BEGIN:
PUSHDS
MOVAX,0
PUSHAX;保证返回DOS,
MOVAX,DATA
MOVDS,AX;为DS送初值
LEABX,SQTAB;以下程序部分完成查表求平方值
MOVAH,0;亦可用查表指令完成(如下程序段)
MOVAL,SUR;AL=XLEABX,SQTAB
ADDBX,AX;MOVAL,SUR
MOVAL,[BX];XLAT
MOVDIS,AL;MOVDIS,AL
CODEENDS
ENDBEGIN
【例2】已知Z=(X+Y)-(W+Z),其中X,Y,Z,W均为用压缩BCD码表示的数,写出程序。
分析:
这也是一种典型的直线程序,在这里要注意是BCD数相加,要进行十进制调整。
具体程序如下:
MOVAL,Z
MOVBL,W
ADDAL,BL
DAA
MOVBL,AL;BL=(W+Z)
MOVAL,X
MOVDL,Y
ADDAL,DL;AL=(X+Y)
DAA;十进制调整
SUBAL,BL;AL=(X+Y)-(Z+W)
DAS;十进制调整
MOVZ,AL;结果送Z
4.3.3分支程序设计
分支程序的基本思想是根据逻辑判断的结果来形成程序的分支,如图,若A成立,则执行P1;否则执行P2。
图4-5分支程序结构
1.双分支程序实现
【例3】试编写程序段,实现符号函数。
分析:
变量X的符号函数可表示为:
1X>0
Y=0X=0
-1X<0
程序可通过对符号标志的判别来确定执行哪一分支。
START:
MOVAX,BUFFER;(BUFFER)=X
ORAX,AX
JEZERO;X=0,则转ZERO
JNSPLUS;X为正数,则转PLUS
MOVBX,0FFFFH;X为负数,则-1送BX
JMPCONT1
ZERO:
MOVBX,0
JMPCONT1
PLUS:
MOVBX,1
CONT1:
……
【例4】两数比较大小
图4-6比较大小
2.多分支程序设计
相异性条件:
所有条件中只有一个条件成立。
相容性条件:
所有条件中可能有两个以上甚至所有条件都成立
常用方法:
转移表法、地址表法、逻辑分解法
1)转移表法
【例5】一监控程序,有10个控制命令键。
这些命令的实现由监控程序中10个子程序完成,子程序入口地址为ADR0~ADR9。
据此建立跳转表,表内存放10条跳转指令,JMPADR0~JMPADR9。
设10个命令键编号为0~9。
分析:
表地址=表基地址+偏移量,按键号X为条件,每条跳转指令长度为3个字节,则按键号X对应的命令子程序的跳转指令在跳转表中的偏移量是3X。
JMPNEARBRA1
JMPNEARBRA2
JMPNEARBRA3
……
BRA-TAB
程序:
MOVAH,0
MOVBL,AL
ADDAL,AL;求2X
ADDAL,BL;求3X,即位移量
MOVBX,OFFSETBRA-TAB;设BRA-TAB为表首
ADDBX,AX
JMPBX
2)地址表法
【例6】利用表实现分支
表4-1子程序R1—R8的入口地址表
P1
子程序R1的入口偏移地址
P2
子程序R2的入口偏移地址
P3
子程序R3的入口偏移地址
……
……
…….
……
P7
子程序R7的入口偏移地址
P8
子程序R8的入口偏移地址
根据AL中各位被置位情况,控制转移到8个子程序P1~P8之一中去。
地址表的结构如表4-1所示。
分析:
对于这种程序关键要找出每种情况的转移地址,从图中可见
表地址=表基地址+偏移量,而偏移量可由AL各位所在位置*2求得。
流程图见图4-7。
DATASEGMENT
BASEDWSR0,SR1,SR2,SR3,
SR4,SR5,SR6,SR7
DATAENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,ES:
DATA
BEGIN:
PUSHDS
XORAX,AX
PUSHAX
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 章程 设计