第5章基本程序设计.ppt

上传人:本田雅阁 文档编号:3502922 上传时间:2019-09-04 格式:PPT 页数:184 大小:1.50MB
返回 下载 相关 举报
第5章基本程序设计.ppt_第1页
第1页 / 共184页
第5章基本程序设计.ppt_第2页
第2页 / 共184页
第5章基本程序设计.ppt_第3页
第3页 / 共184页
第5章基本程序设计.ppt_第4页
第4页 / 共184页
第5章基本程序设计.ppt_第5页
第5页 / 共184页
点击查看更多>>
资源描述

《第5章基本程序设计.ppt》由会员分享,可在线阅读,更多相关《第5章基本程序设计.ppt(184页珍藏版)》请在三一文库上搜索。

1、第5章 基本程序设计,5.1 顺序程序设计 5.2 分支程序设计 5.3 循环程序设计 5.4 子程序设计 5.5 具有模块结构的程序设计,5.1 顺序程序设计,8086的汇编语言程序设计比较复杂, 掌握它有一定的困难, 故必须先掌握8086 的指令系统及汇编语言的基本约定。 从本章起, 我们可以集中力量来解决程序设计的方法问题, 并将编写的源程序进行汇编和连接, 生成对应的可执行的程序文件, 在MSDOS 环境下运行这些程序, 这将大大加快学习汇编语言的进程, 深入掌握汇编语言程序设计的方法。,任何一种程序设计语言编写的程序, 其结构都是由顺序程序、 分支程序和循环程序这三种基本结构组成的。

2、 程序结构设计方法简介。 程序结构设计是把算法转化为程序的准备阶段。 对于算法比较复杂的问题, 应绘制程序结构图或程序流程图。 结构图可描述各模块间的参数传送及相互调用的关系, 程序流程图则能较好地描述程序执行的过程。,1. 结构图(structurechart) 结构图是描述程序结构和程序模块间的关系的一种设计方法,它的基本部分是长方形框, 每个框表示1个模块, 如图5.1所示。 方框内用字符串表示(标记)模块的名字, 方框之间的带方向的箭头连线表示模块间的调用关系。调用模块或外层模块通常画在上面, 箭头指向的框表示被调用的模块或内层模块, 图5.1(a)中, A框为调模块, B框为被调用模

3、块。,若可以选择性地调用, 主模块以射线的形式表示, 如图5.1(b)中, 调用模块A可有选择地调用B, C及D模块。 图5.1(c)则描述了在一个循环层中调用B, C, D模块的方式。 图5.1(d), 描述当两个模块间有信息交换时的情况, 此时可用带标注的箭头来表示信息内容.,图 5.1 结构图法示例,2. 流程图法(flowchart) 流程图是最早被使用的一种方法, 也是最直观的方法。 流程图由逻辑框和流程线组成。 逻辑框是指示程序的操作功能的符号, 流程线是指示操作顺序的符号。 流程图常用符号如图5.2所示。,图 5.2 流程图中的符号,(1) 端点框 端点框表示程序的两端起点和终点

4、。 框内可以写上合适的文字,例如“开始(start)”, “结束(end)”或者程序名, 起始地址等。 (2) 过程框或处理框 用于表示一种处理功能或过程的程序段, 框内可用文字标注扼要的功能或过程说明。 该框可以简单到只包含一条指令, 复杂到描述一个程序模块(或子程序即过程)。,(3) 判断框 用于表示1个程序中判定点, 程序将从这一点开始分支, 框内用文字符号注明检测条件, 而检测的结果分别注明于各分支流程线上。 (4) 连接框 它表示1段程序在此处被人为中止, 框内标有符号, 以便与带有同样符号的另一个框相联系。 对于一个大的流程图或由于篇幅不够、 或由于避免出现交叉而不得不被打断的情况

5、下, 用连接框表示程序流程图从何处被中止, 又从何处重新开始。,(5) 流程线 带有箭头的流程线用于指出程序执行的流向。 一个程序按其功能可分为若干部分, 每部分可用一个逻辑框来表示,各个逻辑框通过流程线有机地联系起来, 构成了总的程序流程图。 流程图可以清楚地反映设计思想和程序结构是否合理。 流程图是程序设计中使用得最早, 最易为人们接受和应用的一种有效的工具。,3. NS图(NASSISHCINDERMAN) NS图又称为方块图, 是结构化程序设计中的算法描述工具。 用NS图得到的程序一定是结构化程序。 非结构化的程序, 用NS图是无法表示的。 它有三种基本逻辑,五种类型, 如图5.3所示

6、。 三种基本逻辑即顺序逻辑、 选择逻辑和循环逻辑。 选择逻辑可分为单分支和多分支两类。 循环逻辑又分为当型循环(do while)和直到型循环(do until p)两类。,图 5.3 NS图表示法,4. 伪码流程图 伪码流程图是通过形式语言描述程序结构的一种方法。它可以直接把流程图或方块图(NS图)以伪码流程图的形式表示出来, 并能很方便地转化为程序。 例如: 选择结构可以表示如下: IF PT A ELSE B ENDIF,对于多分支的选择结构可用伪码流程图表示如下: DOCASE CASEP1 A CASEP2 B CASEPN S ENDCASE,5.1.1 简单算术运算及逻辑运算顺序

7、程序 1. 单字节压缩BCD数加法运算 例5.1 将存储单元A1和A2中的两个BCD数相加, 结果送至A3单元中。 相加后的进位送至A31单元。 分析: 为了得到十进制的结果, 应在两个字节相加后再用加法十进制调整指令DAA进行调整。 对于A1、 A2、 A3这三个存储器变量的存取方法, 希能通过实例掌握。,源程序如下: NAMEEX051 DATA SEGMENT A1 DB48H A2 DB53H A3 DB2DUP(? ) DATA ENDS CODE SEGMENT ASSUMECS: CODE, DS: DATA,START: MOVAX, DATA MOVDS, AX MOVAL,

8、 A1 ADDAL, A2 DAA MOVA3, AL LAHF ANDAH, 01H MOVA31, AH MOVAH, 4CH INT 21H CODE ENDS END START,2. 二进制字加法及乘法运算 例5.2 首先将FIRST字变量与SECOND字变量相加, 结果存至THIRD存储字中,然后将FIRST与SECOND两个字变量相乘, 结果存至THIRD1开始的两个字中。 分析: 8088的指令既可进行字节运算, 也可进行字运算, 只要变量类型定义正确,本程序即很容易编写。,源程序如下:; NAME EX052 DATA SEGMENT FIRST DW7684 SECOND

9、DW23569 THIRD DW ? THIRD1 DW2DUP(? ) DATA ENDS CODE SEGMENT ASSUMECS: CODE, DS: DATA,START: MOVAX, DATA MOV DS, AX MOV AX, FIRST ADD AX, SECOND MOV THIRD, AX; 保存加法结果 MOV AX, FIRST MUL SECOND MOV THIRD1, AX MOV THIRD12, DX; 保存乘法结果 MOV AH, 4CH INT 21H,CODE ENDS END START 其中MULSECOND实现16位乘法, 即(AX)*存储器字

10、,存储器变量给指令功能的灵活性发挥了很大的作用, 使程序设计变得更加简单省事。,3. 取数的反码和补码 例5.3 将字变量A1转换为反码和补码, 分别存入字变量A2和A3中。 分析: 此处的取反码和取补码, 是指取一个数的相反数的反码和补码。 取反码要求原数按位求反, 可由NOT指令实现, 补码可由反码加1得到。 也可以由NEG 指令获取相反数的补码, 由补码减1得到反码值。 所以可用两种方法来实现。,(1) 先取反, 再取补的程序段: MOV AX, A1 NOT AX ; 取反码 MOV A2, AX INC AX ; 形成补码 MOV A3, AX,(2) 先取补再取反的程序段: MOV

11、 AX, A1 NEG AX ; 取补码 MOV A3, AX DEC AX ; 形成反码 MOV A2, AX,5.1.2 字符处理和代码转换程序 1. 屏蔽和组合 例5.4 将字类型变量A的高4位和低4位置0, 其余各位保持不变。 分析: 要让一个数的某几位置0, 则只要与一个数相与。 对应位为0, 则相与结果即为0; 对应位为1, 则相与结果即保持不变。 此处应与数0FF0H相与, 0FF0H 被称为屏蔽字。 对应的程序段如下:,MOV AX, A AND AX, 0FF0H MOV A, AX 也可用1条8086指令实现: ANDA, 0FF0H; 可见8086指令灵活、 功能强大,2

12、. 拆字 例5.5 将存储单元A中2个压缩BCD数拆成2个非压缩的BCD码, 低位BCD数存入C中,高位BCD数存于B中, 并将对应的ASCII码存入C1及B1中。 分析: 将1个字节中的两位BCD码分开, 可采用屏蔽高4位、 保留低4位的方法,得到低位BCD码; 由未组合的BCD码转为ASCII码, 只要高4位加或或30H; 若将高4位BCD码分离,可以采用逻辑右移4位的方法, 左边移入4个0, 即可达到目的。 程序段如下:,程序段如下: NAMEEX055 DATA SEGMENT A DB 37H B DB? C DB? B1 DB? C1 DB? DATA ENDS CODE SEGM

13、ENT,ASSUME CS: CODE, DS: DATA MAIN PROC FAR START: PUSH DS MOV AX, 0 PUSH AX ; 保存返回地址 MOV AX, DATA MOV DS, AX MOV AL, A MOV CL, 4 SHR AL, CL MOV B, AL,OR AL, 30H MOV B1, AL MOV AL, A AND AL, 0FH MOV C, AL OR AL, 30H MOV C1, AL RET ; 返回DOS MAIN ENDP CODE ENDS END START,3. 查表将1个09的BCD数转换成格雷码 格雷码又称循环码,

14、 循环码的特点是任意两个相邻的数之间只有1位状态改变。 即任意一个BCD数与它相邻的数之间只有1位(二进制位)的状态不同。 满足这种要求的编码状态很多,表5.1仅给出一种。,表5.1 格雷码与BCD数之间的对应关系,例5.6 将变量A中的两位BCD码转换为格雷码。 高位格雷码存于C中, 低位的格雷码存于B中。 分析: 查表指令XLAT是实现转换的关键, 该指令要求从(DS): (BX)(AL)中取得结果。 源程序如下: NAMEEX056 DATA SEGMENT GRAY DB 00H, 01H, 03H, 02H, 06H DB 0EH, 0AH, 08H, 0CH, 04H,A DB25

15、H B DB? C DB? DATAENDS CODESEGMENT ASSUMECS: CODE, DS: DATA START: MOV AX, DATA MOV DS, AX MOV AL, A MOV CL, 4 SHR AL, CL,MOV BX, OFFSET GRAY XLAT MOV C, AL MOV AL, A AND AL, 0FH XLAT MOV B, AL MOV AH, 4CH INT 21H CODE ENDS END START,5.2 分支程序设计,5.2.1 简单分支结构程序 单重分支程序的结构可用图5.4表示。 图中的T(true)表示条件为真(成立),

16、 F(false)表示条件为假(不成立)。在8088汇编中, 条件判断和转移操作通常用比较指令和条件转移指令实现。 比较指令根据比较结果置标志位, 转移指令根据标志位决定分支的走向。,图 5.4 单重分支结构程序,例5.7 变量X的符号函数可用下式表示:,Y的取值是由X的符号决定的。 为了判别X的符号, 可以让X直接与0比较,也可以用一条能影响标志位的指令来进行。 例如用与或或操作, 就把X的符号和是否为0反映到SF与ZF标志上。 流程图如图5.5所示。,图 5.5 符号函数的程序流程图,源程序如下: NAMEEX057 CODE SEGMENT ASSUME CS: CODE, DS: CO

17、DE SIGEF: PUSH CS POP DS ; 将CODE值赋给DS MOV AX, X ; 取变量X值 OR AX, AX ; 置标志 JE ZERO ; X为0转ZERO,JNS PLUS ; X不为负, 转PLUS MOV BL, 0FFH ; X为负, 将0FFH(即-1)(BL) JMP CONTI ; ZERO: MOV BL, 0 ; X为0, 将0(BL) JMP CONTI PLUS: MOV BL, 1 ; X为正, 将1(BL) CONTI: MOV RESULT, BL ; 保存结果至RESULT MOV AH, 4CH ; 返回DOS INT 21H,X DW

18、7086H RESULT DB ? CODE ENDS END SIGEF 该程序中, DS与CS都对应同一个逻辑段CODE, 由于CODE由系统自动装入CS中, 故用PUSH CS,先将CS值压入堆栈, 然后再用POP DS指令, 将CODE值装入DS。 在CODE 中除了指令代码外, 还含有X和RESULT这样的数据变量。,例5.8 比较两个带符号数的大小, 若AB, 则显示出AB, 否则显示BA。程序流程图如图5.6所示。,图 5.6 例5.8程序流程图,源程序如下: NAMEEX058 CODE SEGMENT ASSUMECS: CODE, DS: CODE START: PUSH

19、CS POP DS MOV AL, A CMP B, AL JGE BGA ; BA转BGA MOV DL, A ; 准备显示AB,MOV AL, B JMP COM BGA: MOV DL, B ; 准备显示BA MOV AL, A COM: MOV AH, 2 ; 利用系统调用2, 显示1个字符 INT 21H MOV DL, INT 21H MOV DL, AL INT 21H,MOV AH, 4CH ; 返回DOS INT 21H A DB B DB CODE ENDS END START 此处利用系统调用2, 显示比较的结果, 要求将调用号2送入AH, 显示的字符ASCII 码送DL

20、, 用INT21H进行调用。,5.2.2 多分支结构程序 在程序设计中, 有时要求对多个条件同时进行判断, 根据判断的结果, 可能有多个分支要进行处理, 就象伪码流程图法中的DOCASE语句及NS图表示法中的多分支逻辑结构。 然而在汇编语言中, 每一条条件转移指令只有两个出口, 因此, 在遇到多分支结构的程序时, 只能用多条条件转移指令来实现。 例5.9 根据源块地址与目标块地址有无重叠分别用不同的方式进行数据块传送的指令。,例如在A地址有50个单元的数据块, 要求传到B地址处的50个单元的存储区中, A和B两个区域的位置关系, 可有三种情况, 如图5.7所示。 图5.7(a)为两个数据块之间

21、没有重叠的情况, 而图5.7(b)和(c),为两个数据块之间存在部分重叠的情况。 对于图5.7(b), 若由A块传送至B块, 可采用由低地址端先传送,按增址方向实现字符串的自动传送。 但不能采用由高地址端先传送, 按减址方向实现字符串的自动传送。,图5.7 两数据块关系图,对于图5.7(c), 由A块传送至B块, 则应采用从高地址端先传送,按减址方向重复字符串的传送, 而不应由低地址端先传送, 按增址方向重复字符串的传送。 不注意以上的情况, 并采取不同的传送方法, 就可能在传送中破坏重叠区的原来数据。 图5.8, 就是能区别A、 B两块间的位置关系, 正确传送块的流程图。对应的源程序如下:,

22、图5.8 例5.9程序流程图,对应的源程序如下: NAME EX-05-9 DATA SEGMENT BLOCK DB100 DUP(X) DB100 DUP(Y) ; 定义了200个字节的存储区 A EQUBLOCK20 B EQUBLOCK60 ; A, B关系属图5.9的(c) L EQU50,DATA ENDS STACK SEGMENT PARA STACK STACK DB 100DUP(?) STACK ENDS CODE SEGMENT ASSUMECS: CODE, DS: DATA, ES: DATA, SS: STACK START PROC FAR BEGIN: PUS

23、H DS,MOV AX, 0 PUSH AX MOV AX, DATA MOV DS, AX MOV ES, AX MOV SI, OFFSETA MOV DI, OFFSETB CMP SI, DI JA DOA ; A为大地址, 转DOA,ADD SI, L1 ; 取A尾址 CMP SI, DI ; A尾址B首址(无重叠? ) JB DOA ; A尾址小, 无重叠 STD ; 重叠, 减量数据串传送 ADD DI, L1 ; 指向B串尾址 JMP BMV DOA: CLD BMV: REP MOVSB RET START ENDS END BEGIN,5.3 循环程序设计,5.3.1 循环

24、程序的两种基本结构 循环程序一般由以下三个部分组成: (1) 循环体 就是要求重复执行的程序段部分,又可以再细分为循环工作部分和循环控制部分。 循环工作部分为要求被重复执行的程序段, 它完成有关处理操作。 循环控制部分在每次循环时都要检查一次循环的结束条件。当满足条件时就结束循环, 继续往下执行其它程序段。,(2) 循环结束部分 完成循环结束后的处理, 如数据的分析、 结果的存放等。 (3) 循环初始部分 完成进行循环所作的准备工作,例如设置循环程序工作部分的有关地址指针、 寄存器的初值、控制循环的条件或循环计数器的初始值设置以及有关标志值等。,图5.9与图5.10分别为两种循环程序的基本结构

25、。 前者是先处理后判断的循环程序结构, 其特点是循环体至少被执行一次; 后者是先判断后处理的循环结构, 其特点是循环工作部分可能一次也不执行。,图 5.9 先处理后判断,图 5.10 先判断后处理,5.3.2 用计数器控制的循环 计数控制的循环是最常用的也是最普通的控制循环的方法。下面通过若干个例子进行介绍。 例5.10 在一串给定个数的存储区中寻找最大值, 并放至指定的存储单元, 每个数用16位表示。 现假设串中数据的个数存于COUNT单元, 数据从BUFF单元开始存放, 最大值求出后保存在MAX单元中。 源程序如下: NAME EX-05-10 DATA SEGMENT,BUFF DWX1

26、, X2, XN COUNT DW$-BUFF MAX DW ? DATA ENDS STACK SEGMENTPARASTACKSTACK STACK1 DB-100DUP(? ) TOP EQU$-STACK STACK ENDS CODE SEGMENT ASSUMECS: CODE, DS: DATA, SS: STACK,START PROC FAR BEGIN: PUSH DS MOV AX, 0 PUSH AX MOV AX, DATA MOV DS, AX MOV AX, STACK MOV SS, AX ; 设置堆栈段基址 MOV AX, TOP MOV SP, AX ; 设

27、置堆栈SP初值,MOV CX, COUNT LEA BX, BUFF MOV AX, BX INC BX INC BX DEC CXAGAIN: CMP AX, BX JGE NEXT MOV AX, BX,NEXT: INC BX INC BX LOOP AGAIN RET START ENDP CODE ENDS END BEGIN 程序中的$表示当前单元计数器的值, $-BUFF表示BUFF 定义的存储区中字的个数减去起始地址, 这个值刚好就是数据字的个数N。,$-STACK, 现在是字节单元个数100, 将它赋给TOP, 实际上它就是堆栈栈顶元素的段内偏移量, MOV AX, TOP和

28、MOV SP, AX, 将TOP赋给了SP, 完成堆栈的设置。 例5.11 统计正数、 负数和零的个数。 要求对BUFF开始的存储区中存放的一组带符号数, 统计其正数的个数、 负数的个数和零的个数并存于PLUS、 MINUS及ZERO单元。,图 5.11 例5.11程序流程图,源程序如下: NAME EX-05-11 DATA SEGMENT BUFF DB 2, -3, 18, -24, N EQU$-BUFF PLUS DB? MINUS DB? ZERO DB? DATA ENDS CODE SEGMENT ASSUME CS: CODE, DS: DATA,START: MOV AX,

29、 DATA MOV DS, AX MOV SI, OFFSET BUFF MOV CX, N MOV DL, 0 ; DL为正数计数器 MOV DH, DL ; DH为负数计数器 MOV BL, DL ; BL为零个数计数器 LOP: CMP BYTE PTR SI, 0 JE CZERO ; 若为0, 零个数计数器加1 JG CPLUS ; 若为正数, 正数计数器加1,INC DH ; 若为负数, 负数计数器加1 JMP NEXT CZERO: INC BL JMP NEXT CPLUS: INC DL NEXT: INC SI LOOP LOP NZERO: MOV PLUS, DL MO

30、V MINUS, DH MOV ZERO, BL,MOV AH, 4CH INT 21H CODS ENDS END START 在统计时, 直接对PLUS、 MINUS和ZERO单独使用INC指令也是可以的, 但这样做,三存储单元的初值应为0。 对BUFF单元, 用DW定义, 就成为统计字类型的带符号数的程序。 在INC SI后, 再插入一条INC SI指令, 以保证每次统计后, 指针要移动两个单元。,例5.12 数据传送程序。 将BUFF1开始的存储区中的20个字节的数据传送到BUFF2开始的存储区中, 且不考虑数据块的重叠问题。 分析: 由于数据块的长度已知, 因此可用计数控制的循环程序

31、来实现。每传送一个字节, 应修改源块和目标块的地址指针, 计数值减1为0时, 循环结束。 源程序如下: NAME EX-05-12 DATA SEGMENT BUFF1 DB0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,DB13, 14, 15, 16, 17, 18, 19 BUFF2 DB20DUP(? ) DATA ENDS CODE SEGMENT ASSUMECS: CODE, DS: DATA START: MOV AX, DATA MOV DS, AX MOV CX, 20 LEA SI, BUFF1 LEA DI, BUFF2,CYCLE:

32、MOV AL, SI MOV DI, AL INC SI INC DI LOOP CYCLE MOV AH, 4CH INT 21H CODE ENDS END START,例5.13 考虑数据块重叠的传送数据块程序。 这里设源块首址低于目标块首址, 但并不知道这两块是否有重叠, 因此需要判别。 若无重叠, 则按地址升序进行传送; 若有重叠, 则应从末地址开始, 减址方向进行传送。 源程序如下: NAME EX-05-13 DATA SEGMENT STRG DB ABCDEFGHIJKLMNOP STRG1 EQU STRG+4 STRG2 EQU STRG+8 STRL NEQU 6,DA

33、TA ENDS CODE SEGMENT ASSUMECS: CODE, DS: DATA START: MOV AX, DATA MOV DS, AX MOV CX, STRLN MOV SI, OFFSETSTRG1 MOV DI, OFFSETSTRG2 PUSH SI ADD SI, STRLN-1 ; SI指向源块末地址,CMP SI, DI POP SI JL MOVINC ; 无重叠, 转MOVINC, 按增址顺序传送 ADD SI, STRLN-1 ; 重叠时, SI, DI指向末地址 ADD DI, STRLN-1 ; 进行减址传送 MOVDEC: MOV AL, SI MO

34、V DI, AL DEC SI DEC DI,LOOP MOVDEC JMP DONE MOVINC: MOV AL, SI MOV DI, AL INC SI INC DI LOOP MOVINC DONE: MOV AH, 4CH INT 21H CODE ENDS END START,5.3.3 条件控制的循环程序 有些循环程序的循环次数是不知道或不确定的, 因此需要根据某些条件来确定是否结束循环。 例如统计一个字符串的长度, 由于事先不知道串的长度,因此这是一个循环次数未知的循环程序。 如果知道这个串以什么字符结束, 例如以$或0DH或其它已知的字符结束时, 我们便以检测是不是这个字符

35、来决定循环的结束。,例5.14 统计字符串长度。 要求从STRN地址起的一串字符进行统计, 求其串长, 串尾以$结束, 且串长不包含$。 分析: 为了统计字符个数, 需要指定一个累加器, 且事先应清0, 以后每统计一个字符, 累加器便加1, 直至取出的字符为$时为止。 源程序如下: NAME EX-05-14 DATA SEGMENT STRN DB ABCDRA, $,STRLN DB? DATA ENDS CODE SEGMENT ASSUMECS: CODE, DS: DATA START: MOV AX, DATA MOV DS, AX MOV SI, OFFSETSTRN MOV D

36、L, 0 ; DL中为串长 AGAIN: MOV AL, SI CMP AL, $ ; 串尾为$否?,JE DONE INC DL INC SI JMP AGAIN DONE: MOV STRLN, DL ADD DL, 30H ; 设字符个数小于10 MOV AH, 02 INT 21H ; 将字符个数显示出来 MOV AH, 4CH INT 21H CODE ENDS END START,例5.15 要求统计串中的空格个数和逗号的个数。 空格的ASCII码为20H, 逗号的ASCII码为2CH。 设该串仍以$字符结尾, 此时,应设两个计数器, 例如: DH为空格计数器, DL为,的计数器。

37、 源程序如下: NAME EX-05-15 DATA SEGMENT STRN DB Aabcd BE, RES, $ SPCLN DB? DELILN DB? DATA ENDS CODE SEGMENT,ASSUMECS: CODE, DS: DATA START: MOV AX, DATA MOV DS, AX MOV SI, OFFSETSTRN MOV DX, 0 AGAIN: MOV AL, SI CMP AL, $ ; 判断串尾为$ JE DONE CMP AL, 20H ; 判有没有空格 JNE NEXT,INC DH JMP CONTI NEXT: CMP AL, 2CH ;

38、 判有没有逗号 JNE CONTI INC DL CONTI: INC SI JMP AGAIN DONE: MOV SPCLN, DH ; 存空格数,MOV DELILN, DL ; 存逗号数 MOV AH, 4CH INT 21H CODE ENDS END START,5.3.4 用逻辑尺控制的循环 在一个循环内部可能有两个分支, 每一个分支可能是一个不同功能的程序段, 在整个程序执行时, 第一个分支与第二个分支按照一定的次序轮流执行。 因此, 可以把规定执行的次序设置在一个逻辑尺中, 用以控制转入不同的支路执行。 例如该位为0, 转入第一个分支; 该位为1, 转入第二个分支执行。,例5

39、.16 设有两个子程序, 第一个为FUN1, 第二个为FUN2, 可以完成对一个部件的加工操作。 其操作顺序是执行二次FUN2, 接着执行二次FUN1, 再执行三次FUN2。 分析: 若逻辑尺某位为1, 执行FUN2; 为0执行FUN1, 则逻辑尺可设置为1100111B,循环总次数为7。 工作时, 将逻辑尺逐位移入CF位, 然后对CF进行判别。 源程序如下: NAME EX-05-16 CODE SEGMENT ASSUMECS: CODE,C1 EQU 7 C2 EQU 11001110B START: MOV CL, C1 MOV AL, C2 LP: SAL AL, 1 ; 将逻辑尺某

40、位移至标志位 JC R2 CALL FUN1 ; 执行FUN1子程序 CM: DEC CL ; 循环总次数减1 JNZ LP MOV AH, 4CH,INT 21H R2: CALL FUN2 ; 执行FUN2子程序 JMP CM FUN1 PROC RET FUN2 PROC RET CODE ENDS END START,5.4 子程序设计,5.4.1 子程序与主程序 一般把调用子程序的程序称为主程序, 也称为调用程序,而在程序中被多次调用的程序称为子程序。 主程序与子程序是相对而言的, 因为子程序又可以再调用另一个子程序, 这种情况称为子程序的嵌套。 如图5.12所示, 主程序是通过调用

41、指令CALL来调用子程序的。,图 5.12 主程序和子程序的调用关系,5.4.2 子程序的段内调用和返回 对于近类型的子程序, 可直接在代码段定义,此时调用程序与子程序处于同一个段内。 若有多个子程序, 均可在代码段中定义它们。 这时,调用程序可以在子程序的前面, 也可以在子程序的后面, 但是不允许调用程序和子程序交叉存放。,例5.17 编写一个程序, 从键盘键入一个字符, 若为F, 则调用FIRST子程序; 若为S, 则调用SECOND子程序, 否则显示INPUT CHARACTER FORS!返回DOS 。FIRST和SECONT子程序为近过程。 1. 主程序在子程序的前面 NAME EX

42、-05-17 DATA SEGMENT STR0 DB INPUTCHARACTER FORS !, $ STR1 DB INPUTCHARACTER: $,STR2 DB The First Subroutine ! $ STR3 DB The Second Subroutine ! $ DATA ENDS CODE SEGMENT ASSUMECS: CODE, DS: DATA MAIN PROC FAR START: PUSH DS MOV AX, 0 PUSH AX,MOV AX, DATA MOV DS, AX MOV DX, OFFSETSTR1 MOV AH, 09H INT

43、21H ; 提示输入字符 MOV AH, 01H INT 21H CMP AL, F JE SUBF ; 为F调用子程序FIRST CMP AL S JE SUBS ; 为S调用子程序SECOND,CALL ENTER LEA DS, STR0 MOV AH, 09H INT 21H ; 提示输入字符形式 JMP RETN SUBF: CALL FIRST JMP RETN SUBS: CALL SECOND RETN: RET MAIN ENDP,ENTER PROC MOV DL, 0DH MOV AH, 02H INT 21H MOV DL, 0AH MOV AH, 02 INT 21H

44、 ; 完成回车换行 RET ENTER ENDP FIRST PROC CALL ENTER,LEA DS, STR2 MOV AH, 09H INT 21H RET FIRST ENDP SECOND PROC CALL ENTER LEA DS, STR3 MOV AH, 09H INT 21H RET,SECOND ENDP CODE ENDS END START 在以上程序中,其中MAIN为主程序,放在代码段的最前面还定义了四个子程序。 ENTER子程序为公用子程序, 其作用是完成光标的回车换行。 FIRST 子程序、 SECOND子程序及MAIN主程序都调用了ENTER子程序。 只要

45、在END语句中, 指向主程序的START, 那么在程序装入内存执行时, 总是先转入主程序执行。,2. 主程序在子程序的后面 以上程序也可将主程序MAIN安排在三个子程序的后面, 即在ASSUME伪指令后面,分别定义ENTER、 FIRST及SECOND三个子程序, 最后定义MAIN主程序, 只要程序在结尾处, 用END START即可。 此处不再列出程序。,5.4.3 子程序段间调用和返回 子程序如果用于段间调用, 那么在过程定义时就应将它定义为FAR类型。 在调用FAR类型的子程序时, CALL指令所完成的操作与段内调用时不同, CALL 指令在汇编时产生的机器代码也不相同, 以保证段间调用

46、时, 不仅要保存返回地址的段内偏移量, 而且要保存返回地址的段基址。,1. 同一模块内的段间调用 例5.18 编写一个主程序, 从键盘输入二位非压缩的BCD数, 存入AX寄存器中。 为了将其转换为二进制数, 应编写一个远类型的子程序。 若将字符显示出来,可用近类型子程序实现, 也可用远类型子程序实现。 主程序执行时, 数据可循环输入, 遇到00结束。 由于显示子程序既可被调用程序调用, 又可被转换程序调用, 故也定义为远类型。 主程序MAIN通过系统调用1, 从键盘输入两个BCD数的ASCII码, 存于AX中。 若是00, 则返回DOS, 否则调用转换程序进行转换。,转换程序TRAN完成将BCD码转换为二进制数。 显示程序CON, 主要完成将十六进制数转换为对应的ASCII码送入AL中,然后调用显示子程序DISP, 显示该字符。 TRAN子程序流程图如图5.13所示。 一位十六进制数转换为ASCII码流程图如图5.14所示。,图5.13 TRAN子程序流程图,图 5.14,图5.14 一位十六进制数转为ASCII码流程图,整个程序如下: NAME EX-05-18

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1