1、第五章第五章 汇编语言程序设计汇编语言程序设计第五章第五章 汇编语言程序设计汇编语言程序设计5.1 5.1 源程序的基本结构源程序的基本结构 汇编语言源程序的组成部分有:模块、段、子程序和宏等。一个模块对应一个目标文件,当开发较大型的应用程序时,该程序可能由若干个目标文件或库结合而成的。有关子程序的知识和宏将在后续章节介绍,本章将介绍程序段及程序结构。1 1 段的定义段的定义v微机系统的内存是分段管理的,为了与之相对应,汇编语言源程序也分若干个段来构成。8086CPU有四个段寄存器,在该系统环境下运行的程序在某个时刻最多可访问四个段,而80386及其以后的CPU都含有六个段寄存器,于是,在这些
2、系统环境下开发的运行程序在某个时刻最多可访问六个段。5.1 5.1 源程序的基本结构源程序的基本结构 1 1 段的定义段的定义v不论程序在某个时刻最多能访问多少个段,在编程序时,程序员都可以定义比该段数更多的段。在通常情况下,一个段的长度不能超过64K,在80386及其以后系统的保护方式下,段基地址是32位,段的最大长度可达4G。v段的长度是指该段所占的字节数:v如果段是数据段,则其长度是其所有变量所占字节数的总和;v如果段是代码段,则其长度是其所有指令所占字节数的总和。v在定义段时,每个段都有一个段名。在取段名时,要取一个具有一定含义的段名。5.1 5.1 源程序的基本结构源程序的基本结构
3、1 1 段的定义段的定义段定义的一般格式如下:段名SEGMENT对齐类型组合类型类别;段内的具体内容段名ENDS5.1 5.1 源程序的基本结构源程序的基本结构 2 段寄存器的说明语句段寄存器的说明语句v在汇编语言源程序中可以定义多个段,每个段都要与一个段寄存器建立一种对应关系。建立这种对应关系的说明语句格式如下:vASSUME 段寄存器名:段名,段寄存器名:段名,v其中:段寄存器是CS、DS、ES、SS、FS和GS,段名是在段定义语句说明时的段名。v在一条ASSUME语句中可建立多组段寄存器与段之间的关系,每种对应关系要用逗号分隔。例如,ASSUME CS:CODE1,DS:DATA15.1
4、 5.1 源程序的基本结构源程序的基本结构 2 段寄存器的说明语句段寄存器的说明语句v上面的语句说明了:CS对应于代码段CODE1,DS对应于数据段DATA1。v在ASSUME语句中,还可以用关键字NOTHING来说明某个段寄存器不与任何段相对应。下面语句说明了段寄存器ES不与某段相对应。vASSUME ES:NOTHINGv在通常情况下,代码段的第一条语句就是用ASSUME语句来说明段寄存器与段之间的对应关系。在代码段的其它位置,还可以用另一个ASSUME语句来改变前面ASSUME语句所说明的对应关系,这样,代码段中的指令就用最近的ASSUME语句所建立的对应关系来确定指令中的有关信息。5.
5、1 5.1 源程序的基本结构源程序的基本结构 3 堆栈段的说明堆栈段的说明v堆栈段是一个特殊的段,在程序中可以定义它,也可以不定义。除了要生成COM型执行文件的源程序外,一个完整的源程序一般最好定义堆栈段。如果在程序中不定义堆栈段,那么,操作系统在装入该执行程序时将自动为其指定一个64K字节的堆栈段。5.1 5.1 源程序的基本结构源程序的基本结构3 堆栈段的说明堆栈段的说明v在源程序中,可用以下方法来定义堆栈段。方法方法1 1:STACK1 SEGMENTDB 256 DUP(?);256是堆栈的长度,可根据需要进行改变TOP LABEL WORDSTACK1 ENDSv在源程序的代码段中,
6、还要添加如下程序段,才能把段STACK1当作堆栈段来使用。ASSUMESS:STACK1 ;可在代码段的段指定语句中一起说明CLI ;禁止响应可屏蔽中断MOV AX,STACK1MOV SS,AXMOV SP,OFFSET TOP;给堆栈段的栈顶寄存器SP赋初值STI;恢复响应可屏蔽中断5.1 5.1 源程序的基本结构源程序的基本结构 3 堆栈段的说明堆栈段的说明方法方法2 2:STACK1SEGMENTSTACK;定义一个堆栈段,其段名为STACK1DB256 DUP(?)STACK1ENDSv上述段定义说明了该段是堆栈段,系统会自动把段寄存器SS和栈顶寄存器SP与该堆栈段之间建立相应的关系
7、,并设置其初值,而不用在代码段对它们进行赋值。5.1 5.1 源程序的基本结构源程序的基本结构 4.段的基本属性段的基本属性v在第一小节中,我们已经介绍了段定义的格式,现在对段定义中另外的一些属性“对齐类型”、“组合类型”和“类别”作以说明,这些可选项可根据需要选择书写。如果源程序中不指定某个属性,那么,汇编程序将使用该属性的缺省值。v(1)(1)对齐类型对齐类型(ALIGN)(ALIGN)v对齐类型表示当前段对起始地址的要求,连接程序(LINK.EXE)按表6.1的地址格式来定位段的起始地址。在进行段定位时,会根据其定位类型进行定位的,所以,各段之间就有可能出现一些空闲字节,即可能浪费几个字
8、节单元。段对齐类型与段起始地址之间的对应关系段对齐类型与段起始地址之间的对应关系对齐类型起始地址(二进制)功能说明最多的空闲字节数BYTExxxx xxxx xxxx xxxx xxxx下一个字节地址0WORDxxxx xxxx xxxx xxxx xxx0下一个字地址1DWORDxxxx xxxx xxxx xxxx xx00下一个双字地址3PARAxxxx xxxx xxxx xxxx 0000下一个节地址15PAGExxxx xxxx xxxx 0000 0000下一个页地址1275.1 5.1 源程序的基本结构源程序的基本结构 4.段的基本属性段的基本属性(2)(2)组合类型组合类型(
9、COMBINE)(COMBINE)组合类型是告诉连接程序如何把不同模块中段名相同的段合并在一起。具体的组合类型如下:NONE表示当前段在逻辑上独立于其它模块,并有其自己的基地址。NONE是缺省的组合类型。PUBLIC表示当前段与其它模块中同段名的PUBLIC类型段组合成一个段。组合的先后次序取决于LINK程序中目标模块排列的次序。在组合时,后续段的起始地址要按其对齐类型进行定位,所以,同名段之间可能有间隔。COMMON表示当前段与其它模块中同名段重叠,也就是说,它们的起始地址相同。最终段的长度是同名段的最大长度。由于段覆盖,所以,前一同名段中的初始化数据被后续段的初始数据覆盖掉。STACK组合
10、类型STACK表示当前段是堆栈栈,其组合情况与PUBLIC相同。AT 数值表达式该数值表达式是当前段所指定的绝对起始地址的段地址。5.1 5.1 源程序的基本结构源程序的基本结构 4.段的基本属性段的基本属性(3)(3)类别类别(CLASS)(CLASS)v类别是一个由程序员指定的用单引号括起来的字符串。如果一个段没有给出类别,那么,这个段的类别就为空。类别是用于段的分类,连接程序利用该类别来调整同名、同类别的段,并使它们相邻。典型的类别是Data和Code。如果指定某段的类别是Code,那么,该段最好是代码段,这样,有的调试程序(如:CodeView)就可以顺序工作。例如:DATA1SEGM
11、ENT WORD PUBLIC DataDATA1ENDS上述段定义说明了该段的起始地址是下一个字地址、组合类型为PUBLIC、段类别是Data。5.1 5.1 源程序的基本结构源程序的基本结构 4.段的基本属性段的基本属性(4)(4)段组段组(GROUP)(GROUP)段组伪指令GROUP是用于把源程序模块中若干个段结合成一个组,并对该段组定义一个段组名。段组伪指令的格式如下:段组名 GROUP 段名,段名,其中:段名之间要用逗号间隔,段名也可以用表达式“SEG 变量”或“SEG 标号”。第五章第五章 汇编语言程序设计汇编语言程序设计5.2 5.2 汇编语言程序设计的基本方法和步骤汇编语言程
12、序设计的基本方法和步骤1 1 汇编语言程序设计基本步骤汇编语言程序设计基本步骤 一般来说,编制一个汇编语言程序的步骤如下:分析题意,确定算法或算法思想。分析题意,确定算法或算法思想。根据算法画出流程图,简单的情况也可不画。根据算法画出流程图,简单的情况也可不画。分配存储空间和工作单元,合理地使用寄存器。分配存储空间和工作单元,合理地使用寄存器。根据流程图编写程序。根据流程图编写程序。上机调试运行程序。上机调试运行程序。编写说明文件编写说明文件第五章第五章 汇编语言程序设计汇编语言程序设计5.2 5.2 汇编语言程序设计的基本方法和步骤汇编语言程序设计的基本方法和步骤2 2 结构化程序的概念结构
13、化程序的概念v结构化程序设计由迪克斯特拉(E.W.dijkstra)在1969年提出,是以模块化设计为中心,将待开发的软件系统划分为若干个相互独立的模块,这样使完成每一个模块的工作变单纯而明确,为设计一些较大的软件打下了良好的基础。v由于模块相互独立,因此在设计其中一个模块时,不会受到其它模块的牵连,因而可将原来较为复杂的问题化简为一系列简单模块的设计。模块的独立性还为扩充已有的系统、建立新系统带来了不少的方便,因为我们可以充分利用现有的模块作积木式的扩展。第五章第五章 汇编语言程序设计汇编语言程序设计5.2 5.2 汇编语言程序设计的基本方法和步骤汇编语言程序设计的基本方法和步骤2 2 结构
14、化程序的概念结构化程序的概念v按照结构化程序设计的观点,任何算法功能都可以通过由程序模块组成的三种基本程序结构的组合:顺序结构、选择结构和循环结构来实现。v结构化程序设计的基本思想是采用自顶向下,逐步求精的程序设计方法和单入口单出口的控制结构。自顶向下、逐步求精的程序设计方法从问题本身开始,经过逐步细化,将解决问题的步骤分解为由基本程序结构模块组成的结构化程序框图;单入口单出口的思想认为一个复杂的程序,如果它仅是由顺序、选择和循环三种基本程序结构通过组合、嵌套构成,那么这个新构造的程序一定是一个单入口单出口的程序。据此就很容易编写出结构良好、易于调试的程序来。第五章第五章 汇编语言程序设计汇编
15、语言程序设计3 流程图画法规定流程图画法规定v程序流程图是程序分析中最基本、最重要的分析技术,它是进行流程程序分析过程中最基本的工具。是由特定的几何图形、指向线、文字说明来表示数据处理的步骤,形象描述逻辑控制结构以及数据流程的示意图。(1)符号用法符号用法第五章第五章 汇编语言程序设计汇编语言程序设计3 流程图画法规定流程图画法规定 (2)使用约定使用约定v图的布局 流程图中所用的符号应该均心地分布,连线保持合理的长度,并尽量少使用长线。v符号的形状 流程图中多数符号内的空白供标注说明性文字。使用各种符号应注意符号的外形和各符号大小的统一,避免使符号变形或各符号大小比例不一。v符号内的说明文字
16、 应使符号内的说明文字尽可能简明。通常按从左向右和从上向下方式书写,并与流向无关。如果说明文字较多,符号内写不完,可使用注解符。若注解符干扰或影响到图形的流程,应将正文写在另外一页上,并注明引用符号。第五章第五章 汇编语言程序设计汇编语言程序设计3 流程图画法规定流程图画法规定v符号标识符 为符号规定标识符是为了便于其它文件引用该符号。便如,程序清单中引用到流程图中的特定符号。符号标识符一般写在符号的左上角.v符号描述符 为便于进一步理解符号的功能,可标注符号描述符。通常描述符写在符号的右上角.v详细表示 在处理符号或数据符号中画一横线,表明该符号在同一文件集中的其它地言有更为详细的表示。横线
17、在符号内靠近项端,详细表示的标识符写在符号内横线之上。端点符用作详细表示的开始符号和结束符号,在此符号中应给出加横线符号中的标识符。第五章第五章 汇编语言程序设计汇编语言程序设计5.2 5.2 汇编语言程序设计的基本方法和步骤汇编语言程序设计的基本方法和步骤v流线标准流向与箭头的使用流线的交叉流线的汇集符号流线进出连接符v多出口判断的两种表示方法直接从判断符号引出多条流线从判断符号引出一条流线,再从它引出多条流线第五章第五章 汇编语言程序设计汇编语言程序设计5.3 5.3 顺序程序设计顺序程序设计v顺序程序设计是完全按照指令的书写顺序而执行每一条指令,它没有分支、循环和转移。是指令中最简单,最
18、常见的程序结构,它的特点是结构简单,易于理解,但只适合于处理简单问题的场合。实际应用中,完全采用顺序结构的程序并不多。顺序结构程序流程图如下:S1S2S3第五章第五章 汇编语言程序设计汇编语言程序设计5.3 5.3 顺序程序设计顺序程序设计1.1.顺序程序设计举例顺序程序设计举例【例1】试编写一程序计算以下表达式的值。=(v-(*+-540)/x式中x、v均为有符号字数据。【例2】已知某班学生的英语成绩按学号(从1开始)从小到大的顺序排列在TAB表中,假定要查询的学生的学号放在变量NO中,请将查得的结果放在变量ENGLISH中。试编写程序。【例3】假设有二个字变量word1和word2,编写程
19、序段实现交换其值的功能。【例4】试编写一个程序,把压缩存放的BCD码,转换为其对应十进制数字的ASCII码。第五章第五章 汇编语言程序设计汇编语言程序设计5.3 5.3 顺序程序设计顺序程序设计2.用用简单查表法简单查表法实现实现代码转换代码转换v在汇编语言程序设计中,代码转换是经常的事。上面的把BCD码转换成ASCII码就是一例。对于各种不同代码之间的转换,往往要采用各种不同的方法,以便获得最佳效率。查表是实现代码转换的方法之一,下面介绍的简单查表法是一种计算查表方法,适用于代码集合较小且转换关系复杂的场合。第五章第五章 汇编语言程序设计汇编语言程序设计5.3 5.3 顺序程序设计顺序程序设
20、计2.2.用用简单查表法简单查表法实现实现代码转换代码转换【例】编写一个把16进制数字码转换为对应七段代码的程序。七段显示数码管示意图如下:0123456第五章第五章 汇编语言程序设计汇编语言程序设计5.3 5.3 顺序程序设计顺序程序设计2.2.用用简单查表法简单查表法实现实现代码转换代码转换v利用上图所示的七段显示数码管,能较好地显示16进制数字(0,1,。9,A,B,C,D,E,F)。七段数码管的每一段对应一个二进制位,如果我们设0表示对应段亮,1表示对应段暗,那么数字码0对应以二进制形式表示的代码1000000,数字码1对应以二进制形式表示的代码1111001,如此,数字码F对应以二进
21、制形式表示的代码0001110。这种用于表示七段数码管亮暗的代码称为七段代码。v显然,16进制数字码与七段代码间的关系难以表示成一个简单的算术表达式,所以,利用表的方法实现代码转换较合适。第五章第五章 汇编语言程序设计汇编语言程序设计5.3 5.3 顺序程序设计顺序程序设计3.3.查表法求函数值查表法求函数值v有许多数学函数的求值计算用汇编语言实现较为困难,除非利用数学协处理器。然而,上述这种表的组织形式和查表的方法,能够适用于直接获得某些数学函数的值。v【例】设X是一个1-10之间的整数,写一个求函数Y=LOG(X)值的程序。v把1-10这10个数的对数值组织成一张表,那么程序运行时的计算工
22、作就大大减缓了,甚至可以说没有具体的计算。由于1-10的以10为底的对数在0-1的范围之间,为了表示的方便和考虑一定的精度,所以把这些对数值放大10000倍,这样每个对数值就用一个字表示。第五章第五章 汇编语言程序设计汇编语言程序设计5.3 5.3 顺序程序设计顺序程序设计3.3.查表法求函数值查表法求函数值v使用查表法求函数值有两个优点:(1)程序比较容易;(2)能够得到十进制或十六进制(或任何其它)格式的高精度函数值。v其缺点也许不那么明显:(1)函数值必须事先安排好,因而有许多限制;(2)函数值的精度和准确性由程序员控制,而不是由数学函数决定,当数据表的项较多时,难免有误差。第五章第五章
23、 汇编语言程序设计汇编语言程序设计5.4 5.4 分支程序设计分支程序设计v分支程序结构可以有两种形式,它们分别相当于高级语言中IF-THEN-ELSE语句和CASE语句,适用于要求根据不同条件作不同处理的情况。IF-THEN-ELSE语句可以引出两个分支。CASE语句则可以引出多个分支。不论哪一种形式,它们的共同特点就是:运行方向是向前的,在某一种特定条件下,只能执行多个分支中的一个分支。第五章第五章 汇编语言程序设计汇编语言程序设计5.4 5.4 分支程序设计分支程序设计IF-THEN-ELSE语句结构条件判断程序段1程序段2第五章第五章 汇编语言程序设计汇编语言程序设计5.4 5.4 分
24、支程序设计分支程序设计CASE语句结构程序段1程序段2程序段N条件判断第五章第五章 汇编语言程序设计汇编语言程序设计5.4 5.4 分支程序设计分支程序设计1.1.分支程序举例分支程序举例【例1】设有三个单字节无符号数存放在BUFFER开始的缓冲区中,写一个能将它们按大到小重新排列的程序。【例2】已知字节变量CHAR1,编写一程序段,把它由小写字母变成大写字母。【例3】编写一程序段,计算下列函数值。其中:变量X和Y是有符号字变量。第五章第五章 汇编语言程序设计汇编语言程序设计5.4 5.4 分支程序设计分支程序设计2.2.利用地址表实现多向分支利用地址表实现多向分支v当要根据某个变量的值,进行
25、多种不同处理时,就产生了多向分支。多向分支的结构图5.17所示。在高级语言中,常用SWITCH语句等实现多向分支。在汇编语言中,如何实现多向分支呢?第五章第五章 汇编语言程序设计汇编语言程序设计5.4 5.4 分支程序设计分支程序设计2.2.利用地址表实现多向分支利用地址表实现多向分支【例】任何复杂的多向分支总可分解成多个简单分支。下图给出了根据X的值是否为1-4,而进行5中不同处理的流程图片段。N条件1满足?Y处理语句1N条件2满足?Y处理语句2N条件3满足?Y处理语句3N条件4满足?Y处理语句4处理语句5第五章第五章 汇编语言程序设计汇编语言程序设计5.5 5.5 循环程序设计v在程序设计
26、中我们有时会需要能按一定规律,多次重复执行的一串语句,这类程序叫循环程序,在本章节中,我们将对循环程序设计作以介绍。循环程序一般由四个部分组成:1 置循环初值部分:这是为了保证循环程序能正常进行循环操作而必须做的准备工作。循环初值分两类:一类是循环工作部分的初值,另一类是控制循环结束条件的初值。2 工作部分:即需要重复执行的程序段。这是循环的中心,称之为循环体。3 修改部分:按一定规律修改操作数地址及控制变量,以便每次执行循环体时得到新的数据。4 控制部分:用来保证循环程序按规定的次数或特定条件正常循环。第五章第五章 汇编语言程序设计汇编语言程序设计5.5 5.5 循环程序设计v在程序设计中,
27、常见的循环结构有两种:一种是先执行循环体,然后判断循环是否继续进行;另一种是先判断是否符合循环条件,符合则执行循环体,否则退出循环。两种循环结构如下图所示。初始化部分初始化部分工作部分工作部分修改部分修改部分结束处理部分结束处理部分循环结束?循环结束?“先执行后判断”结构,适用于已知循环次数的情况。“先判断后执行”结构,适用于未知循环次数的情况。第五章第五章 汇编语言程序设计汇编语言程序设计5.5 5.5 循环程序设计1.1.单重循环程序设计单重循环程序设计举例举例【例1】计算假设这10个已知数为字类型,已连续存放在内存中以AA为首址的存储区域中,其相加的和仍为字数据存放在BB字单元。【例2】
28、已知有两个5个字节的数分别存放在DA1、DA2为首地址的内存区中,试求其和并把结果存放在DA3为首地址的内存中。【例3】在以BUF为首地址的内存区中存放着一批带符号的8位二进制数,这批数据以0作为结束符号。试编写一程序统计该批数据中有多少个正数(不包含数据0),并把统计结果存放在RESULT单元第五章第五章 汇编语言程序设计汇编语言程序设计5.5 5.5 循环程序设计2.2.多重循环程序设计多重循环程序设计v在程序设计中,有一些比较复杂的过程,仅采用单重循环是不能解决问题的,这就出现了多重循环程序结构。所谓多重循环就是在循环程序的循环体内又包含着循环结构,称为循环嵌套。v多重循环结构中最常用的是二重循环,二重循环是指在一个循环中还包含有另一个完整的循环结构,外面一层循环称为外层循环,里面一层循环称为内层循环。v多重循环程序的设计方法和单重循环程序的设计方法是一致的,应分别考虑各重循环的控制条件及其程序实现,相互之间不能混淆。要注意的是:内循环必须完整地被包含在外循环中,循环可以嵌套、并列,但不可以交叉。另外,还应分清循环层次,避免出现死循环。第五章第五章 汇编语言程序设计汇编语言程序设计5.5 5.5 循环程序设计2.2.多重循环程序设计多重循环程序设计举例举例v【例1】设有一个首地址为ARRAY的n字数组,试编制程序使该数组中的数按从大到小的次序排列。