收藏 分享(赏)

汇编语言第五章.ppt

上传人:hyngb9260 文档编号:10038704 上传时间:2019-09-30 格式:PPT 页数:135 大小:725.50KB
下载 相关 举报
汇编语言第五章.ppt_第1页
第1页 / 共135页
汇编语言第五章.ppt_第2页
第2页 / 共135页
汇编语言第五章.ppt_第3页
第3页 / 共135页
汇编语言第五章.ppt_第4页
第4页 / 共135页
汇编语言第五章.ppt_第5页
第5页 / 共135页
点击查看更多>>
资源描述

1、,第五章 程序设计的其它方法与技术,一、本章的学习内容: 本章学习汇编语言的高级程序设计技术:(1)串操作指令的使用格式及功能;(2)宏指令的定义与调用方式;(3)模块程序设计方法及连接技术。通过本章的学习,能提高编程的效率和质量, 简化程序设计的工作,这是汇编语言中最具特色 的部分。,第五章 程序设计的其它方法与技术,二、本章的学习重点:(1)串操作指令MOVS、CMPS、SCAS的使用格式及功能;(2)简单宏指令的定义与调用方式;(3)模块程序设计的方法。,第五章 程序设计的其它方法与技术,三、本章学习的难点:(1)MOVS与MOV、CMPS与CMP功能上的差别及串操作指令的正确使用方法;

2、(2)宏指令的定义与调用方式;(3)模块之间的组合、定位及通信方式;(4)模块化程序设计技术。,第五章 程序设计的其它方法与技术,5.1 字符串操作指令5.2 宏功能程序设计,5.1 字符串操作指令,(1) 串传送指令 MOVS(2)串比较指令 CMPS(3)串搜索指令 SCAS(4)取字节/字/双字串指令 LODS(5)存储字节/字/双字指令 STOS( 6 ) 总结,(1) 串传送指令 MOVS,格式:MOVS OPD,OPS 或功能:(1) (DS:SI/ESI) ES:DI/EDI(2) 修改串指针,使之指向下一元素。修改方式为:.当DF0时,(SI)/(ESI)增量1(字节操作)或2

3、(字操作) 或4(双字操作).当DF1时,(SI)/(ESI)减量1(字节操作)或2(字操作)或4(双字操作)说明:(1) 该指令可带的重复前缀为:REP 即当(CX/ECX)0时连续传送,直至(CX/ECX)=0。(2) 源串应在当前数据段,指针为SI/ESI;目的串应在当前附加数据段指针为DI/EDI。,MOVSD 双字串传送,MOVSB 字节串传送,MOVSW 字串传送,(1) 串传送指令 MOVS,例1:将以STR1为首址的字节存储区中存放的字符串传送到以 STR2为首址的字节存储区中。.386DATA SEGMENT USE16STR1 DB ABCDEFGHIJKLM ;输出缓冲区

4、BUF1COUNT EQU $-BUF1 ;BUF1中的字符个数STR2 DB COUNT DUP(O) ;输入缓冲区BUF2DATA ENDSSTACK SEGMENT USE16 STACKDB 200 DUP(0)STACK ENDSCODE SEGMENT USE16ASSSUME DS:DATA,ES:DATA,CS:CODE,SS:SATCK,START:MOV AX,DATAMOV DS,AX ;当前数据段和当前附加数据段重合 MOV ES,AXLEA SI,STR1 ;源串首址送SILEA DI, STR2 ;目的串首址送DIMOV CX,COUNT ;串长度送CXCLD ;将

5、DF清0 REP MOVSB ;重复传送直至CX=0MOV AH,4CH INT 21HCODE ENDSEND START,(1) 串传送指令 MOVS,16,CX,数据段,BUF1,BUF2,A,B,C,D,E,F,G,H,I,J,K,L,M,A,B,C,D,E,F,G,H,I,J,K,L,M,“ REP MOVSB”语句代替了以下程 序段: P: MOV AL, SI MOV DI, AL INC SI INC DI LOOP P 由于每个汇编源程序的开始时, DF=0 为默认状态,一次不用专门使用CLD指 令。,反向操作的源程序:STDLEA SI,BUF1+COUNT-1LEA DI

6、,BUF2+COUNT-1MOV CX,COUNTREP MOVSB “REP MOVE“语句代替了以下程序段P: MOV AL, SI MOV DI,AL DEC SIDEC DI LOOP P 由于DF=0为默认状态,故须使用STD 指令设置DF=1,才能反向操作.,(2)串比较指令 CMPS,格式:CMPS OPD,OPS 或功能: (DS:SI/ESI)(ES:DI/EDI),即将SI/ESI所指的源串中的 一个字节(或字、双字)中的数与DI、EDI所指的目的串中的一个字节(或字、双字)中的据相减,并根据相减的结果设置标志位,结果并不保存。 修改串指针,使之指向串中的下一个元素。修改方

7、式为: i. 当DF0时,(SI)/(ESI)和(DI)/(EDI)增量1(字节操作)或2(字操作)或4(双字操作)。 ii. 当DF1时,(SI)/(ESI)和(DI)/(EDI) 减量1(字节操作)或2(字操作) 或4(双字操作)。,CMPSB,字节串比较,CMPSW 字串比较,CMPSD 双字串比较,。,(2)串比较指令 CMPS,说明: 源串放在当前数据段中,指针为SI/ESI;目的串放在 当前附加数据段中,指针为DI/EDI; 该指令可带的重复前缀为:a.REPE/REPZ 当(CX/ECX)0时,如两串对应字符相等继续比较,不相等跳出循环;b.REPNE/REPNZ 当(CX/EC

8、X)0时,如两串对应字符相等继续比较,不相等跳出循环;,例2,(2)串比较指令 CMPS,例2 从键盘输入一字符串至STR1为首址的字节缓冲区中,试比较该串与字节字符串STR2是否相等,相等则0BX;不等-1BX。.386 DATA SEGMENT USE16 STR1 DB 80 DB 0 DB 80 DUP(0) STR2 DB WAN1ASM COUNT EQU -STR2 DATA ENDS STACK SEGMENT USE16 STACK DB 200 DUP(0) STACK ENDS CODE SEGMENT USE16 ASSUME DS:DATA,ES:DATA,SS:ST

9、ACK,CS:CODE,输入缓冲区,;待比较字符串,;待比较字符串长度,(2)串比较指令 CMPS,START: MOV AX,DATA MOV DS,AX MOV ES,AX LEA DX,STR1 MOV AH,10 输入一串字符至STR1缓冲区 INT 21H MOV AL,STR11 CMP AL,COUNT 比较两串长度是否相等,不等转EXITJNE EXIT LEA SI,STR12 LEA DI,STR2 MOV CX,COUNT REPZ CMPSB ;逐一比较两串的对应字符是否相等 JNE EXIT ;不等,转EXIT MOV BX,0 ;相等,0BX JMP RETU EX

10、IT: MOV BX,-1 RETU: MOV AH,4CH INT 21H CODE ENDS END START,当前数据段和当前附加数据段重合,(3)串搜索指令 SCAS,格式: SCAS OPD 或 功能: 字节操作:(AL)-(ES:DI/EDI) 字操作: (AX)- (ES:DI/EDI)双字操作:(EAX)-(ES:DI/EDI) 修改串指针使之指向下一元素.修改方式为:i.当DF0时,(DI)/(EDI)增量1(字节操作)或2(字操作)或4(双字操作)。ii.当DF1时,(DI)/(EDI)减量1(字节操作)或2(字操作)或4(双字操作)。 修改循环变量(CX)/(ECX)

11、-1 CX)/ECX,SCASB 字节串搜索,SCASW 字串搜索,SCASD 双字串搜索,(3)串搜索指令 SCAS,说明: 待搜索串一定要是目的串,放在当前附加数据段中,指针为DI/EDI; 该指令可带的重复指令为:i. REPZ/REPE 若(CX/ECX)0且相等时接着搜索.ii.REPNZ/REPNE 若(CX/ECX)0且不相等时接着搜索.,例3,(3)串搜索指令 SCAS,例3 从键盘输入一串字符至ASS区,试用串搜索指令在该串中搜索子串AM出现的次数BX.386DATA SEGMENT USE16 ASS DB 80 DB 0DB 79 DUP(0) DATA ENDS STA

12、CK SEGMENT USE16 STACK DB 200 DUP(0) STACK ENDS CODE SEGMENT USE16 ASSUME DS:DATA,ES:DATA,SS:STACK, CS:CODE START: MOV AX,DATA MOV DS,AX MOV ES,AX,当前数据段和当前附加数据段重合,(3)串搜索指令 SCAS,LEA DX,ASS MOV AH,10INT 21HLEA DI,ASS+2MOV CL,ASS+1MOVZX CX,CL MOV AL,AMOV BX,0 P: REPNE SCASB JE A JMP OUT1 A: CMP CX,0JE

13、OUT1CMP BYTE PTR DI, MJNE BINC BX B: JMP P OUT1:MOV AH,4CH INT 21H CODE ENDS END START,;输入串首址DI,;输入串长度CX,;计数器清零,;查找字符”A”,;查到字符”A”转A处执行,;全部查完转结束,;所有判断完否,;全部查完转结束,;判断”A”后的字符为”M”否,;不是转B处执行,;是”AM”计数器加1,;未完转P继续判断,;返回操作系统,(4)取字节/字/双字串指令 LODS,格式: LODS OPS 或 功能: 字节操作:(DS:SI/ESI)AL 字操作: (DS:SI/ESI) AX 双字操作:

14、DS:SI/ESI) EAX 将SI/ESI所指的源串中的一个字节(或字、双字)存储单元中的数 据取出送入AL(或AX、EAX)中。 修改SI/ESI,使之指向下一元素:i.当DF0时,(SI)/(ESI)增量1(字节操作)或2(字操作) 或 4(双字操作)。ii.当DF1时,(SI)/(ESI)减量1(字节操作)或2(字操作) 或 4(双字操作)。 修改循环变量(CX)/(ECX) -1 CX)/ECX,LODSB 从字节串中取数,LODSW 从字串中取数,LODSD 从双字串中取数,(4)取字节/字/双字串指令 LODS,说明:由于该指令的目的地址为一固定的寄存器,如果带上重复前缀,源串的

15、内容将连续地送入AL(或AX、EAX)中,操作结束后,AL(或AX、EAX)中只保存了串中最后一个元素的值,这是没有多大意义的,因此,该指令一般不带重复前缀。,例4,(4)取字节/字/双字串指令 LODS,例4: 下面阅读一个使用了LODSD的程序段:.386DATA SEGMENT USE16BUF DB ABCDEFGHIJKLCOUNT EQU $-COUNTSTART: MOV AX,DATAMOV DS,AXMOV ES,AXLEA SI,BUFMOV CX,COUNT/4LODSD ;该语句执行后,(EAX)44434241H,(5)存储字节/字/双字指令 STOS,格式: STO

16、S OPD 或 功能: 字节操作:(AL) ES:DI/EDI 字操作: (AX) ES:DI/EDI 双字操作:(EAX)ES:DI/EDI 即将AL(或AX、EAX)中的数据送入DI/EDI所指的目的串中的字节(或 字、双字)存储单元中。修改指针DI/EDI,使之指向串中的下一个元素。 修改串指针,使之指向下一元素,修改方式为:i.当DF0时,(SI)/(ESI)增量1(字节操作)或2(字操作) 或 4(双字操作)。ii.当DF1时,(SI)/(ESI)减量1(字节操作)或2(字操作) 或 4(双字操作)。说明:该指令执行后,并不影响标志位,因而它一般只带REP重复前缀,用来将一片连续的存

17、储字节(或字)单元置相同的值。,STOSB 往字节串中存数,STOSW 往字串中存数,STOSD 往双字串中存数,串操作指令总结, 源串指针: DS: SI/ESI 即源串在当前数据段 目标串的指针: ES: DI/EDI 即目的串在当前附加数据段 重复计数器: CX/ECX 中间寄存器: AX/EL/EAX 传送/比较方向: DF=0, SI/ESI, DI/EDI自动增量(加1/加 2/加4).DF=0, SI/ESI, DI/EDI自动减量(减1/减 2/减4). 指令格式: 带操作数: S不带操作数: SD (双字操作) SW (字操作)SB (字节操作),串操作指令总结, 重复前缀:

18、REP 重复执行,直到(CS/ECS)=0; (主要是MOVS指令使用)REPE/REPZ ZF=1 时重复执行,直到(CS/ECS)=0; REPNE/REPNZ ZF1时重复执行,直到(CS/ECS)=0;说明:循环次数(CX)是否为0是在操作之前检测的,因此,当(CX)为0时不会引起串操作.操作终止后,SI,DI均指向下一待操作的EA,方向由DF确定.,主要时CMPS,SCAS指令使用,工作流程,串操作指令总结,5.2 宏功能程序设计, 宏定义 宏调用与宏扩展 宏指令中的参数 宏库的使用 宏指令与子程序的比较, 宏定义,宏指令在使用之前要先定义. 定义格式: 宏指令名 MACRO 形式参

19、数 ,形式参数宏体 ENDM 例如: 某一程序中要多次使用DOS9号功能调用: LEA DX,BUF1 MOV AH,9 INT 21H LAE DX,IN_BUF MOV AH,9 INT 21H, 宏定义,他们之间的差别仅在于输出缓冲区的首址不一样.如果讲该首址定义成 形参,就可将其写成宏定义:WRITE MACRO A LEA DX,A MOV AH,9 INT 21H ENDM 说明:(1)宏名字可以与其他变量,标号,保留字同名,汇编程序在处理时宏名字优先级最高.利用这一特点,程序员可以设计新的指令系统., 宏定义,(2) 形参可有可无个数不限,但总字符长度不超过132个,个参数之间用

20、逗号隔开; (3) ENDM和MACRO必须成对出现; (4) 宏指令必须先定义后调用,因为它是在汇编期间处理的., 宏调用与宏扩展,调用格式: 宏指令名 实在参数 ,实在参数 对于例1中所作的宏定义,所应做的宏调用为:WRITE BUF1 ;宏调用 WRITE IN_BUF ;宏调用 汇编程序的处理方式:(1) 第一次扫描时,先扫描宏定义,将宏名字、形参、宏体均填入宏定义表中再遇到宏调用时,则嵌入宏体,用实参按位置顺序替换形参,这一过程称为宏扩展。(2) 第二次扫描时,再将其转换成目标代码., 宏调用与宏扩展,在汇编列表文件(.lst)中,宏拓展后的宏体语句均在前面冠 以”+”以示与其他语言

21、的区别,即拓展后的形式为:+ LEA DX,BUF1 + MOV AH,9 + INT 21H + LEA DX,IN_FUT + MOV AH,9 + INT 21H, 宏调用与宏扩展,说明:(1) 宏指令名要与原宏定义的名字一致;(2) 实参与形参应按位置关系一一对应:i.实参个数多形参,多余实参被忽略;ii.实参个数小于形参,缺少的实参被处理成空白(没有字符). 还可以讲DOS9号和10号调用写成一个宏定义:IO MACRO A, BLEA DX, A ;形参A代表输入/输出缓冲区首址MOV AH, B ;形参B代表DOS调用号INT 21HENDM, 宏指令中的参数,一、带几个符的参数

22、在宏调用中,有时实参是一串带间隔符的字符串,为了不致混 淆,应该尖括号将它们括起来,说明为一个参数.例如,每一个程序都需要定义堆栈段,只是堆栈的大小和初值不 一样 .可以讲定义堆栈的语句写成宏定义:DEF_STACK MACRO A STACK SEGMENT USE16 STACK DB A STACK ENDS ENDM 如果需要建立200个字节、初值均为1的堆栈段,宏调用应为: DEF_STACK ,其中实参为一个重复子句,它中间带有空格,因此要用尖括号括起来, 宏指令中的参数,二、宏体中的变量与标号 例1. 以下程序段的功能为:求从AA开始连续BB个奇数(或偶数)的和送AX.AA =1

23、BB =50MOV BX,AAMOV CX,BBMOV AX,0NEXT:ADD AX,BXADD BX,2LOOP NEXT,其宏定义和宏调用如下: SUM MACRO AA, BBMOV BX, AAMOV CX, BBMOV AX, 0 NEXT: ADD AX, BXADD BX,2LOOP NEXT ENDM SUM 1, 50SUM 10, 20,查看说明,查看宏定义, 宏指令中的参数,+ MOV BX, 1 + MOV CX, 50 + MOV AX, 0 + NEXT:ADD AX, BX ;标号NEXT第一次出现 + ADD BX, 2 + LOOP NEXT + MOV B

24、X, 10 + MOV CA, 20 + MOV AX, 0 + NEXT:ADD AX, BX ;标号NEXT第二次出现,重复定义 + ADD BX, 2 + LOOP NEXT, 宏指令中的参数,处理方式: 1. 将标号定义成形参,每次调用均用实参代替.但会造成参数 过多,给编程带来麻烦; 2.使用伪指令LOCAL,让机器自动生成不同标号. 格式: LOCAL 形式参数,形式参数 功能: 宏拓展时,汇编程序自动为其后形参生成特殊顺序号, 范围为?OOOO - ?FFFFH,并用之取代形参,避免重复 定义. 注意:该语句只能做宏体中的第一个语句., 宏指令中的参数,修改后的宏定义为: SUM

25、 MACRO AA, BBLOCAL NEXTMOV BX, AAMOV CX,BBMOV AX, 0 NEXT: ADD AX, BXADD BX, 2LOOP NEXTENDM,相应的宏拓展为: + MOV BX, 1 + MOV CX, 50 + MOV AX, 0 +?0000:ADD AX,BX;标号NEXT转换?0000 + ADD BX, 2 + LOOP?0000 + MOV BX, 10 + MOV CX, 20 + MOV AX, 0 +?0001:ADD AX, BX;标号NEXT转换?0001 + ADD BX, 2 + LOOP?0001, 宏库的使用,对于经常使用的

26、宏定义,用户可将它们集中在一起,建成 宏库供自己或别人随时调用。由于宏库为文本文件,可用一 般编辑程序建立或修改,文件名也可由用户任意指定。 例如:我们利用编辑程序,建立了一个宏库MACROLIB:当程序中需要调用时,应首先将宏库加入自己的源文件 中,然后按宏库中各宏定义的规定调用即可。将宏库加入源文件一起进行汇编可用伪指令INCLUDE实现。 语句格式:INCLUDE 文本文件名 功 能: 将指定的文本文件从本行起加入汇编,直到该文本文件的最后一行汇编完后,再继续汇编INCLUDE后面的语句。,查看宏库,宏库调用, 宏库的使用,宏库内容: READ MACRO ALEA DX, AMOV A

27、H, 10INT 21HENDM WRITE MACRO ALEA DX, AMOV AH, 9INT 21HENDM,OUT1 MACRO AMOV DL, AMOV AH, 2INT 21HENDM CRLF MACROOUT1 0AH OUT1 0DHENDM STACK0 MACRO A STACK SEGMENT USE16 STACKDB A STACK ENDSENDM, 宏库的使用,INCLUDE MACRO.LIB;将指定的宏库加入本程序一起汇编 .386 DATA SEGMENT USE16 BUF DB 80, 0, 80 DUP(0) DATA ENDS STACK0

28、CODE SEGMENT USE16ASSUME DS: DATA, SS:STACK, CS: CODE START: MOV AX, DATAMOV DS, AXREAD BUF ;输入一字符串BUF缓冲区CRLF ;输出回车换行LEA SI, BUF+2MOV CL, BUF+1MOV CH, 0CLD, 宏库的使用,Y1: LODSB ;从输入串取一字符ALCMP AL, aJB Y2CMP AL, zJA Y2 ;该字符不为小写字母,则转Y2SUB AL, 20H ;将小写字母转换为大写字母的ASCII码 Y2: OUT1 ALLOOP Y1CRLF ;输出回车换行MOV AH, 4

29、CHINT 21H CODE ENDSEND START, 宏指令与子程序的比较,不同点: 处理时间不同;处理方式不同;目标程序的长度不同;执行速度不同;参数传递方式不同;,5.3 模块化程序设计,什么是模块? 一个以END语句为结束的源程序称为一个模块。一个模块是一个独立的汇编源文件,一个模块汇编后生成一个目标文件(*.obj),或称目标模块。 模块化程序是由一个以“END 标号”结束的主模块,和几个以“END”结束的子模块组成。,5.3 模块化程序设计,模块化程序的作用: 用于大型程序系统的设计。通过模块的划分,将复杂的问题合理分配到各子模块中去解决,便于多人合作,编程的质量和效率都会提高

30、。 此外,通过模块的划分,可以针对不同模块的特性,采用不同的语言编程,有利于发挥各计算机语言的特性。,5.3 模块化程序设计,模块化程序设计主要解决的问题: 如何正确地划分模块 如何把模块装配在一起,5.3.1 段的组合方式,段定义语句: 段名 SEGMENT 定位方式 组合方式 类别 段名 ENDS,5.3.1 段的组合方式,1. 定位方式 2. 类别 3. 组合方式,1. 定位方式,定位方式是用来指定各段的起始物理地址的确定方式。有四种不同的选择: PARA:段从能被16整除的地址开始存放。 WORD:段从一个偶数地址开始存放。 BYTE:对段存放的首地址不作要求。 PAGE:段从能被25

31、6整除的地址开始存放。,例1,已知程序中的DATAl段和DATA2段的定义如下,如果这两个段分别为当前数据段和当前附加数据段试分析下述连接程序对它们边界的处理方法。 DATAl SEGMENT A DB 55H DUP(0FFH) DATAl ENDS DATA2 SEGMENT DB 64H DUP(0) DATA2 ENDS,例1,由于这两个段均未明确指定定位方式,说明它们的定位方式均为PARA。经连接程序连接后,DATAl段与DATA2段的定位形式如图所示。,5.3.1 段的组合方式,1. 定位方式 2. 类别 3. 组合方式,2. 类别,类别是用单引号括起来的字符串,该字符串可以是任何

32、合法的名称。连接程序在进行连接处理时,将类别相同的段(它们不一定同名),按出现的先后次序连续存放(但仍是不同名的段),且每段都有自已的首址。,例2,有5个段名不同的段,分属三个不同的类别,连接时。五个段按以下顺序提供给连接程序: A SEGMENT DATA B SEGMENT CODE C SEGMENT TO D SEGMENT DATA E SEGMENT TO,例2,连接后,在生成的.EXE文件中,各段的相对位置成为 A SEGMENT DATA D SEGMENT DATA B SEGMENT CODE C SEGMENT TO E SEGMENT TO,5.3.1 段的组合方式,1

33、. 定位方式 2. 类别 3. 组合方式,3. 组合方式,组合方式向连接程序提供了本段同其它段的组合关系,主要有: (1) NONE(不选择):本段与其它段不发生任何逻辑上的联系,自己有自己的段首址。(隐含的) (2) PUBLIC:表示应将本段与其它模块中的同名、同类别段按各模块连接的顺序相邻地连接在一起,组成一个物理段, 大小不超过64K。 合并的好处:以数据段为例,当组合成一个段后,在子模块中就不用再对DS送首址,方便而又有效。,3. 组合方式,(3) STACK:仅对堆栈段,功能同PUBLIC。 (4) COMMON:表示本段与同名、同类别的其它段应具有相同段首址,即相覆盖。长度取决于

34、最长的COMMON段。 (5) “AT表达式”:表示该段应放在表达式所指定的绝对地址上。 (6) “MEMORY”:表示该段应放所有段之上(最高地址上)。,5.3.2 通讯方式,1. 局部符号: 仅在定义自己的模块中被访问的符号为局部符号。 2. 公共符号: 不仅被定义自己的模块访问,还要供其它模块访问的符号为公共符号。要用PUBLIC伪指令说明。其格式为:PUBLIC 符号,符号, 3. 外部符号: 只在模块内访问而不在该模块内定义的符号为外部符号。要用EXTRN伪指令说明。其格式为: EXTRN 符号:类型,符号:类型,,5.3.3 连接程序(LINK)的功能,1. 将制定的若干个目标模块

35、(.OBJ)和子程序库(.LIB)中的子程序模块连接在一起,生成可执行的文件(.EXE) 2. 产生一个地址分配文件(.MAP),5.3.4 地址分配文件举例,地址分配文件(.MAP)用以描述执行文件中各段的浮动起始地址、结束地址、所占用空间大小、段名及类别,还可列出各模块中所定义的公共符号及其偏移地址,它主要用于程序调试及资料归档。下面列出WANl和WAN2两模块连接后所产生的“.MAP”文件。,例3,NAME WAN1EXTRN WAN2:NEARPUBLIC DIV0,COUNT .386 DATA1 SEGMENT USE16 PARA PUBLIC D1 BEG EQU 1 COUN

36、T DW 50 DIV0 DW 0 DATA1 ENDS STACK SEGMENT USE16 PARA STACK STACKDB 200 DUP(0) STACK ENDS CODE SEGMENT USE16 PARA PUBLIC CODEASSUME DS: DATA1, CS: CODE, SS: STACK START: MOV AX, DATA1,例3,MOV AX,DATA1MOV DS,AXMOV BX, BEGMOV CX,COUNTCALL WAN2MOV AH,4CHINT 21H CODE ENDSEND START,例3,NAME WAN2EXTRN DIV0:

37、WORD,COUNT:WORDPUBLIC WAN2 .386 DATA2 SEGMENT USE16 PARA PUBLIC D2 SUM DW - DATA2 ENDS STACK SEGMENT USE16 PARA STACK STACKDB 200 DUP(0) STACK ENDS CODE SEGMENT USE16 PARA PUBLIC CODEASSUME ES:DATA2, CS: CODE, SS: STACK WAN2 PROCMOV AX,DATA2MOV ES,AX,例3,MOV AX,0 NEXT: ADD AX,BXADD BX,2LOOP NEXTMOV S

38、UM,AXMOV DX,0DIV DS:COUNTMOV DS:DIV0,AXRET WAN2 ENDP CODE ENDSEND,例3,Start Stop Length Name Class 00000H 00003H 00004H DATA1 D1 00010H 0019FH 00190H STACK1 STACK 001A0H 001DDH 0003EH CODE CODE 001E0H 001E1H 00002H DATA2 D2 Address Publics by Name 0000:0000 COUNT 0000:0002 DIV0 001A:0020 WAN2 Address

39、 Publics by Value 0000:0000 COUNT 0000:0002 DIV0 001A:0020 WAN2 Program entry point at 001A:0000,例3,WAN1和WAN2两模块连接的特点如下。 1. 由于两代码段名字、类别相同且组合方式均为PUBLIC,因此,这两个段按出现的顺序合并为一个段,也正因为如此,子程序WAN2可定义为近过程。合并后的段所占字节总数应为原来各段大小之和。 2. 两数据段不同名,不同类别,各自独立,不发生任何关系,每个段都有自己的起始地址。在主模块中为当前数据段,在子模块中为附加数据段。,例3,3. 两堆栈段由于同名、同类

40、别且组合方式为STACK,因此,这两个堆栈段合并成一个段,合并后的段所占字节总数应为原来各段大小之和。 4. 程序的启动地址为001A:0000,即为WAN1模块中END后面所带的符号地址START,它是CODE段中第一条语句的标号,因此,EA等于0。 5. 符号表中列出了各模块中所定义的公共符号及经修改过的值。 6. 以上所提供的信息。将给我们调试多模块程序带来很大的方便。,5.4 源程序综合举例,5.4.1 模块程序设计中的注意事项 1. 模块的划分的规则 2. 程序文件的命名 3. 标号的定义 4. 变量和缓冲区的定义 5. 模块注释 5.4.2 模块程序设计举例,1. 模块划分的规则,

41、(1) 如果一个程序段被很多模块所公用,则它应是一个独立的模块。 (2) 如果若干个程序段处理的数据是公用的,则这些程序段应放在一个模块中。 (3) 若两个程序段的利用率差别很大,则应分属于两个模块。 (4) 一个模块既不能过大,也不能过小。过大则模块的通用性较差,过小则会造成时间和空间上的浪费。,1. 模块划分的规则,(5) 力求使模块具有通用性,通用性越强的模块利用率越高。 (6) 各模块间应在功能上、逻辑上相互独立,尽量截然分开,特别应避免用转移语句在模块间转来转去。 (7) 各模块间的接口应该简单,要尽量减少公共符号的个数,尽量不共用数据存储单元,在结构或编排上有联系的数据应放在一个模

42、块中,以免互相影响,造成查错困难。 (8) 每个模块的结构应尽量设计成单入口、单出口的形式。这样的程序便于调试、阅读和理解且可靠性高。,5.4 源程序综合举例,5.4.1 模块程序设计中的注意事项 1. 模块划分的规则 2. 程序文件的命名 3. 标号的定义 4. 变量和缓冲区的定义 5. 模块注释 5.4.2 模块程序设计举例,2. 程序文件的命名,(1) 标识出程序设计者。即在文件名中用一符号作程序员代号。这样,当制作的模块很多时,通过文件名就应能分辨出各个模块的设计者;每个程序员又可在其代码之后加一数字,标识本人编写的不同模块。这样,遇有问题就可快速找到出处,进行追踪。 (2) 简单标识

43、模块功能。在文件名中标识出模块功能可方便调用与连接。 (3) 标识出模块之间的连接关系:即指一个模块在待连接的一串模块中的位置,可在文件名最后以数字表示顺序。,例如:,程序员编号为“C”,本模块的编号为3,功能为“QUEUE”,无须指定连接关系,则其文件名应为: CQUEUE3.ASM,5.4 源程序综合举例,5.4.1 模块程序设计中的注意事项 1. 模块的划分 2. 程序文件的命名 3. 标号的定义 4. 变量和缓冲区的定义 5. 模块注释 5.4.2 模块程序设计举例,3. 标号的定义,标号名不仅要统一,最好包含它的功能和所有必备的信息。标号所代表的信息有: (1) 模块出处:即为程序员

44、的代号和附加编号。 (2) 功能名称:明确的功能定义可以提高模块的再利用价值。功能名称部分长度以三个字母为宜,太长则输入费时。 如:DSP 表示屏幕显示功能 PRN 表示打印功能 KIN 表示键盘输入功能 (3) 分支代号:程序中的分支代号最理想的是由小而大依序安排,为适应编写程序中的变化,可预留空号以便扩充。,5.4 源程序综合举例,5.4.1 模块程序设计中的注意事项 1. 模块的划分 2. 程序文件的命名 3. 标号的定义 4. 变量和缓冲区的定义 5. 模块注释 5.4.2 模块程序设计举例,4. 变量和缓冲区的定义,例如: 第一个字母用“”为缓冲器名开头;用“V”为变量名开头;用“S

45、”为字符串名开头。 第二个字母可代表定义的类型: Q=QWORD 如:BQxxxx 缓冲器为4字类型。 D=DWORD 如:BDxxxx 缓冲器为双字类型。 W=WORD 如:VWxxxx 变量为字类型。 B=BYTE 如:VBxxxx 变量为字节类型。 S=STRING 如:Sxxxxx 为字符串(字节类型)。 F=FLAG 如:VBFxxx 该变量为字节型类,用作标志。,5.4 源程序综合举例,5.4.1 模块程序设计中的注意事项 1. 模块的划分 2. 程序文件的命名 3. 标号的定义 4. 变量和缓冲区的定义 5. 模块注释 5.4.2 模块程序设计举例,5. 模块注释,为方便子模块的

46、调用,在子模块的前面必须有详细的说明。说明的内容包括:子模块功能、调用此子模块的入口参数和出口参数、子模块中所使用的主要变量等。,5.4 源程序综合举例,5.4.1 模块程序设计中的注意事项 1. 模块的划分 2. 程序文件的命名 3. 标号的定义 4. 变量和缓冲区的定义 5. 模块注释 5.4.2 模块程序设计举例,例1,编写一子程序模块DUMP,使之能将32位寄存器和16位寄存器的内容以有符号十进制数的形式显示出来,显示按“PUSHAD”进栈和“POPAD”出栈的顺序,格式为: (EDI)= (DI)= (ESI)= (SI)= (EBP)= (BP)= (ESP)= (SP)= (EB

47、X)= (BX)= (EDX)= (DX)= (ECX)= (CX)= (EAX)= (AX)= 并要求主模块在调用该子模块之前与之后,全部寄存器的内容均不改变。,例1,本例采用的算法是: 为了保证在调用该子模块之前与之后全部寄存器的内容均不改变,必须一进入本子模块就将全部32位寄存器的内容用“PUSHAD”进栈保存,在返回主模块之前再恢复各寄存器的内容。 整个显示过程需要通过8次循环,一次循环在一行中输出一个32位的寄存器和一个16位寄存器的内容。其方法是: 在每次循环中顺序从堆栈中弹出一个32位寄存器的内容EAX,然后根据二进制转换成十进制ASCII码输出的算法将(EAX)分解成十进制ASCII码BUF1输出缓冲区,显示该32位寄存器的内容; 再将(AX)分解成十进制ASCII码BUF1输出缓冲区,显示该16位寄存器的内容;为了保证按所规定的格式输出,可规定每个寄存器所要显示的字符串长度均为18,不足部分补空格,每行两个显示完后则回车换行,开始下一循环,再在下一行接着显示,这样就能达到每行显示2个并自动对齐的要求。 该例的流程图如下所示。,

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

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报