1、第五章第五章 程序设计的其它方法与技术程序设计的其它方法与技术一、本章的学习内容一、本章的学习内容:本章学习汇编语言的高级程序设计技术:本章学习汇编语言的高级程序设计技术: (1 1)串操作指令串操作指令的使用格式及功能的使用格式及功能; (2 2)宏指令的定义宏指令的定义与与调用调用方式方式; (3 3)模块程序设计方法及连接技术。模块程序设计方法及连接技术。 通过本章的学习,能提高编程的效率和质量,通过本章的学习,能提高编程的效率和质量,简化程序设计的工作,这是汇编语言中最具特色简化程序设计的工作,这是汇编语言中最具特色的部分的部分。第五章第五章 程序设计的其它方法与技术程序设计的其它方法
2、与技术二、本章的学习重点二、本章的学习重点: (1 1)串操作指令)串操作指令MOVS、CMPS、SCAS的的 使用格式及功能使用格式及功能; (2 2)简单简单宏指令的定义宏指令的定义与与调用调用方式方式; (3 3)模块程序设计)模块程序设计的的方法。方法。第五章第五章 程序设计的其它方法与技术程序设计的其它方法与技术三、本章学习的难点三、本章学习的难点: (1 1)MOVS与与MOV、CMPS与与CMP功能上功能上 的差别及串操作指令的正确使用方法的差别及串操作指令的正确使用方法; (2 2)宏指令的定义)宏指令的定义与与调用调用方式方式; (3 3)模块)模块之间的组合、定位及通信方式
3、;之间的组合、定位及通信方式; (4 4)模块化程序设计技术。)模块化程序设计技术。第五章第五章 程序设计的其它方法与技术程序设计的其它方法与技术5.1 5.1 字符串操作指令字符串操作指令5.2 5.2 宏功能程序设计宏功能程序设计5. .1 字符串操作指令字符串操作指令(1) 1) 串传送指令串传送指令 MOVS(2 2)串比较指令串比较指令 CMPS(3 3)串搜索指令串搜索指令 SCAS(4 4)取字节取字节/ /字字/ /双字串指令双字串指令 LODS(5 5)存储字节存储字节/ /字字/ /双字双字串串指令指令 STOS ( 6 ) 总结总结(1) 1) 串传送指令串传送指令 MO
4、VS格式格式: :MOVS OPD,OPS 或或功能功能:(:(1) (1) (DS:SI/ESIDS:SI/ESI) ) ES:DI/EDIES:DI/EDI (2)(2) 修改串指针,使之指向下一元素。修改方式为:修改串指针,使之指向下一元素。修改方式为: .当当DFDF0 0时,时,(SI)/(ESI)(SI)/(ESI)增量增量1(1(字节操作字节操作) )或或2(2(字操作字操作) ) 或或4(4(双字操作双字操作) ) .当当DFDF1 1时,时,(SI)/(ESI)(SI)/(ESI)减量减量1(1(字节操作字节操作) )或或2(2(字操作字操作) ) 或或4(4(双字操作双字操
5、作) ) 说明说明:(1) :(1) 该指令可带的重复前缀为:该指令可带的重复前缀为:REP 即当即当(CX/ECX)(CX/ECX)0 0时连续传送,直至时连续传送,直至(CX/ECX)=0(CX/ECX)=0。 (2) (2) 源串应在当前数据段,指针为源串应在当前数据段,指针为SI/ESISI/ESI;目的串应在;目的串应在 当前附加数据段指针为当前附加数据段指针为DI/EDIDI/EDI。MOVSD 双字串传送双字串传送MOVSB 字节串传送字节串传送MOVSW 字串传送字串传送(1) 1) 串传送指令串传送指令 MOVS例例1 1:将以:将以STR1STR1为首址的字节存储区中存放的
6、字符串传送到以为首址的字节存储区中存放的字符串传送到以 STR2STR2为首址的字节存储区中。为首址的字节存储区中。 .386.386 DATA SEGMENT USE16 DATA SEGMENT USE16 STR1 DB ABCDEFGHIJKLM STR1 DB ABCDEFGHIJKLM ;输出缓冲区;输出缓冲区BUF1BUF1 COUNT EQU $-BUF1 COUNT EQU $-BUF1 ;BUF1BUF1中的字符个数中的字符个数 STR2 DB COUNT DUPSTR2 DB COUNT DUP(O O) ;输入缓冲区;输入缓冲区BUF2BUF2 DATA ENDS DA
7、TA ENDS STACK SEGMENT USE16 STACK STACK SEGMENT USE16 STACK DB 200 DUP(0) DB 200 DUP(0) STACK ENDS STACK ENDS CODE SEGMENT USE16 CODE SEGMENT USE16 ASSSUME DS:DATA,ES:DATA,CS:CODE,SS:SATCK ASSSUME DS:DATA,ES:DATA,CS:CODE,SS:SATCK START:MOV AXSTART:MOV AX,DATADATA MOV DS MOV DS,AX AX ;当前数据段和当前附加数据段重合
8、;当前数据段和当前附加数据段重合 MOV ESMOV ES,AXAX LEA SILEA SI,STR1STR1 ;源串首址送;源串首址送SISI LEA DI, STR2LEA DI, STR2 ;目的串首址送;目的串首址送DIDI MOV CXMOV CX,COUNTCOUNT ;串长度送;串长度送CXCX CLD CLD ;将;将DFDF清清0 0 REP MOVSB ;重复传送直至;重复传送直至CX=0CX=0 MOV AH MOV AH,4CH 4CH INT 21H INT 21H CODE ENDSCODE ENDS END START END START(1) 1) 串传送指令
9、串传送指令 MOVS16CX数据段数据段BUF1BUF2 A B C D E F GH I J K L MA B C D E F GH I J K L M“ “ REP MOVSB”REP MOVSB”语句代替了以下程语句代替了以下程序段序段: :P: MOV AL, SI P: MOV AL, SI MOV DI, AL MOV DI, AL INC SI INC SI INC DI INC DI LOOP P LOOP P 由于每个汇编源程序的开始时由于每个汇编源程序的开始时, DF=0, DF=0为默认状态为默认状态, ,一次不用专门使用一次不用专门使用CLDCLD指指令。令。 反向操作
10、的源程序反向操作的源程序: :STDSTD LEA SI,BUF1+COUNT-1 LEA SI,BUF1+COUNT-1LEA DI,BUF2+COUNT-1LEA DI,BUF2+COUNT-1MOV CX,COUNTMOV CX,COUNT REP MOVSB REP MOVSB 语句代替了以下程序段语句代替了以下程序段P: MOV AL, SI P: MOV AL, SI MOV DI,AL MOV DI,AL DEC SI DEC SI DEC DI DEC DI LOOP P LOOP P 由于由于DF=0DF=0为默认状态为默认状态, ,故须使用故须使用STDSTD指令设置指令设
11、置DF=1,DF=1,才能反向操作才能反向操作. . (2 2)串比较指令)串比较指令 CMPSCMPS格式格式: :CMPS OPDCMPS OPD,OPSOPS 或功能:功能: ( (DSDS:SI/ESI)SI/ESI)( (ESES:DI/EDI)DI/EDI),即将,即将SI/ESISI/ESI所指的源串中的所指的源串中的 一个字节一个字节( (或字、双字或字、双字) )中的数与中的数与DIDI、EDIEDI所指的目的串中的一个字节所指的目的串中的一个字节 ( (或字、双字或字、双字) )中的据相减,并根据相减的结果设置标志位,结果并不中的据相减,并根据相减的结果设置标志位,结果并不
12、 保存。保存。 修改串指针,使之指向串中的下一个元素。修改方式为修改串指针,使之指向串中的下一个元素。修改方式为: : i. i. 当当DFDF0 0时,时,(SI)/(ESI)(SI)/(ESI)和和(DI)/(EDI)(DI)/(EDI)增量增量1(1(字节操作字节操作) )或或2(2(字操字操 作作) )或或4(4(双字操作双字操作) )。 ii. ii. 当当DFDF1 1时,时,(SI)/(ESI)(SI)/(ESI)和和(DI)/(EDI) (DI)/(EDI) 减量减量1(1(字节操作字节操作) )或或2(2(字操字操 作作) ) 或或4(4(双字操作双字操作) )。 CMPSB
13、CMPSB 字节串比较字节串比较 CMPSWCMPSW 字串比较字串比较CMPSDCMPSD 双字串比较双字串比较。(2 2)串比较指令)串比较指令 CMPSCMPS说明说明: : 源串放在当前数据段中源串放在当前数据段中, ,指针为指针为SI/ESI;SI/ESI;目的串放在目的串放在 当前附加数据段中当前附加数据段中, ,指针为指针为DI/EDI;DI/EDI; 该指令可带的重复前缀为该指令可带的重复前缀为: : a. a.REPEREPE/REPZ /REPZ 当当(CX/ECX)0(CX/ECX)0时时, ,如两串对应字符如两串对应字符 相等继续比较相等继续比较, ,不相等跳出循环不相
14、等跳出循环; ; b. b.REPNEREPNE/REPNZ/REPNZ 当当(CX/ECX)0(CX/ECX)0时时, ,如两串对应字符如两串对应字符 不相等继续比较不相等继续比较, ,相等跳出循环相等跳出循环; ;例例2(2 2)串比较指令)串比较指令 CMPS例例2 2 从键盘输入一字符串至从键盘输入一字符串至STR1STR1为首址的字节缓冲区中,试为首址的字节缓冲区中,试 比较该串与字节字符串比较该串与字节字符串STR2STR2是否相等,相等则是否相等,相等则0BX;0BX;不不 等等-1BX-1BX。.386 DATA SEGMENT USE16 STR1 DB 80 DB 0 DB
15、 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:STACK,CS:CODE 输入缓冲区输入缓冲区; ;待比较字符串待比较字符串; ;待比较字符串长度待比较字符串长度(2 2)串比较指令)串比较指令 CMPSSTART: MOV AX,DATA MOV DS,AX MOV ES,AX LEA DX,STR1 MOV AH,10 输入一串字符至输入一串
16、字符至STR1缓冲区缓冲区 INT 21H MOV AL,STR11 CMP AL,COUNT 比较两串长度是否相等,不等转比较两串长度是否相等,不等转EXIT JNE EXIT LEA SI,STR12 LEA DI,STR2 MOV CX,COUNT REPZ CMPSB ;逐一比较两串的对应字符是否相等;逐一比较两串的对应字符是否相等 JNE EXIT ;不等,转;不等,转EXIT MOV BX,0 ;相等,;相等,0BX JMP RETU EXIT: MOV BX,-1 RETU: MOV AH,4CH INT 21H CODE ENDS END START 当前数据段和当前附加数据段
17、重合当前数据段和当前附加数据段重合(3 3)串搜索指令)串搜索指令 SCAS格式格式: SCAS OPD 或或 功能功能: 字节操作:字节操作:(AL)-(AL)-(ESES:DI/EDIDI/EDI) 字操作:字操作: (AX)- (ES(AX)- (ES:DI/EDI)DI/EDI) 双字操作:双字操作:(EAX)-(ES(EAX)-(ES:DI/EDI)DI/EDI) 修改串指针使之指向下一元素修改串指针使之指向下一元素. .修改方式为修改方式为: : i. i.当当DFDF0 0时,时,(DI)/(EDI)(DI)/(EDI)增量增量1(1(字节操作字节操作) )或或 2(2(字操作字
18、操作) )或或4(4(双字操作双字操作) )。 ii.ii.当当DFDF1 1时,时,(DI)/(EDI)(DI)/(EDI)减量减量1(1(字节操作字节操作) )或或 2(2(字操作字操作) )或或4(4(双字操作双字操作) )。 修改循环变量修改循环变量(CX)/(ECX) -1 CX)/ECX(CX)/(ECX) -1 CX)/ECXSCASBSCASB 字节串搜索字节串搜索 SCASWSCASW 字串搜索字串搜索 SCASDSCASD 双字串搜索双字串搜索 (3 3)串搜索指令)串搜索指令 SCAS说明说明: : 待搜索串一定要是目的串待搜索串一定要是目的串, ,放在当前附加数据段中放
19、在当前附加数据段中, , 指针为指针为DI/EDI;DI/EDI; 该指令可带的重复指令为该指令可带的重复指令为: :i. i. REPZ/REPE REPZ/REPE 若若(CX/ECX)0(CX/ECX)0且相等时接着搜索且相等时接着搜索. .ii.ii.REPNZREPNZ/REPNE/REPNE 若若(CX/ECX)0(CX/ECX)0且不相等时接着搜索且不相等时接着搜索. .例例3(3 3)串搜索指令)串搜索指令 SCAS例例3 3 从键盘输入一串字符至从键盘输入一串字符至ASSASS区区, ,试用串搜索指令在该串中试用串搜索指令在该串中 搜索子串搜索子串AM出现的次数出现的次数BX
20、. . .386.386DATA SEGMENT USE16 ASS DB 80 DB 0 DB 79 DUP(0) DATA ENDS STACK 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 3)串搜索指令)串搜索指令 SCASLEA DXLEA DX,ASS ASS MOV AHMOV
21、 AH,1010INT 21HINT 21HLEA DI,ASS+2LEA DI,ASS+2MOV CL,ASS+1MOV CL,ASS+1MOVZX CX,CL MOVZX CX,CL MOV ALMOV AL,AAMOV BXMOV BX,0 0 (CLDCLD) P P: REPNE SCASBREPNE SCASB JE A JE A JMP OUT1 JMP OUT1 A A: CMP CX,0CMP CX,0 JE OUT1 JE OUT1CMP BYTE PTR DI, MCMP BYTE PTR DI, MJNE BJNE B INC BX INC BX B B: JMP P
22、JMP P OUT1OUT1:MOV AHMOV AH,4CH 4CH INT 21H INT 21H CODE ENDS CODE ENDS END START END START ; ;输入串首址输入串首址DIDI; ;输入串长度输入串长度CXCX; ;计数器清零计数器清零; ;查找字符查找字符”A”A”; ;查到字符查到字符”A”A”转转A A处执行处执行; ;全部查完转结束全部查完转结束; ;所有判断完否所有判断完否; ;全部查完转结束全部查完转结束; ;判断判断”A”A”后的字符为后的字符为”M”M”否否; ;不是转不是转B B处执行处执行; ;是是”AM”AM”计数器加计数器加1
23、1; ;未完转未完转P P继续判断继续判断; ;返回操作系统返回操作系统(4 4)取字节)取字节/ /字字/ /双字串指令双字串指令 LODS格式格式: LODS OPS LODS OPS 或或 功能功能: 字节操作:字节操作:(DS(DS:SI/ESISI/ESI)ALAL 字操作:字操作: (DS(DS:SI/ESI) AXSI/ESI) AX 双字操作:双字操作: DSDS:SI/ESI) EAXSI/ESI) EAX 将将SI/ESISI/ESI所指的源串中的一个字节所指的源串中的一个字节( (或字、双字或字、双字) )存储单元中的数存储单元中的数据取出送入据取出送入AL(AL(或或A
24、XAX、EAX)EAX)中。中。 修改修改SI/ESI,SI/ESI,使之指向下一元素使之指向下一元素: : i. i.当当DFDF0 0时,时,(SI)/(ESI)(SI)/(ESI)增量增量1(1(字节操作字节操作) )或或2(2(字操作字操作) ) 或或 4(4(双字操作双字操作) )。 ii.ii.当当DFDF1 1时,时,(SI)/(ESI)(SI)/(ESI)减量减量1(1(字节操作字节操作) )或或2(2(字操作字操作) ) 或或 4(4(双字操作双字操作) )。 * 修改循环变量修改循环变量(CX)/(ECX) -1 CX)/ECX(CX)/(ECX) -1 CX)/ECX L
25、ODSBLODSB 从字节串中取数从字节串中取数 LODSWLODSW 从字串中取数从字串中取数 LODSDLODSD 从双字串中取数从双字串中取数 (4 4)取字节)取字节/ /字字/ /双字串指令双字串指令 LODS说明说明: :由于该指令的目的地址为一固定的寄存器,如果带上由于该指令的目的地址为一固定的寄存器,如果带上重复前缀,源串的内容将连续地送入重复前缀,源串的内容将连续地送入AL(AL(或或AXAX、EAX)EAX)中,操中,操作结束后,作结束后,AL(AL(或或AXAX、EAX)EAX)中只保存了串中最后一个元素的中只保存了串中最后一个元素的值,这是没有多大意义的,因此,该指令一
26、般不带重复前值,这是没有多大意义的,因此,该指令一般不带重复前缀缀。 例例4(4 4)取字节)取字节/ /字字/ /双字串指令双字串指令 LODS例例4: 4: 下面阅读一个使用了下面阅读一个使用了LODSDLODSD的程序段的程序段: : .386.386 DATA SEGMENT USE16 DATA SEGMENT USE16BUF DB ABCDEFGHIJKLBUF DB ABCDEFGHIJKLCOUNT EQU $-BUFCOUNT EQU $-BUFSTART: MOV AX,DATASTART: MOV AX,DATAMOV DS,AXMOV DS,AXMOV ES,AXMO
27、V ES,AXLEA SI,BUFLEA SI,BUFMOV CX,COUNT/4MOV CX,COUNT/4LODSD LODSD ;该语句执行后,(;该语句执行后,(EAXEAX)44434241H44434241H (5 5)存储字节)存储字节/ /字字/ /双字指令双字指令 STOS格式格式: STOS OPDSTOS OPD 或或 功能功能: 字节操作:字节操作:(AL) (AL) ESES:DI/EDIDI/EDI 字操作:字操作: (AX) (AX) ESES:DI/EDIDI/EDI 双字操作:双字操作:(EAX)(EAX)ESES:DI/EDIDI/EDI 即将即将AL(AL
28、(或或AXAX、EAX)EAX)中的数据送入中的数据送入DI/EDIDI/EDI所指的目的串中的字节所指的目的串中的字节( (或或字、双字字、双字) )存储单元中。修改指针存储单元中。修改指针DI/EDIDI/EDI,使之指向串中的下一个元素。,使之指向串中的下一个元素。 修改串指针修改串指针, ,使之指向下一元素使之指向下一元素, ,修改方式为修改方式为: : i. i.当当DFDF0 0时,时,(DI)/(EDI)(DI)/(EDI)增量增量1(1(字节操作字节操作) )或或2(2(字操作字操作) ) 或或 4(4(双字操作双字操作) )。 ii.ii.当当DFDF1 1时,时,(DI)/
29、(EDI)(DI)/(EDI)减量减量1(1(字节操作字节操作) )或或2(2(字操作字操作) ) 或或 4(4(双字操作双字操作) )。 说明说明: :该指令执行后,并不影响标志位,因而它一般只带该指令执行后,并不影响标志位,因而它一般只带REPREP重复前缀,重复前缀,用来将一片连续的存储字节用来将一片连续的存储字节( (或字或字) )单元置相同的值。单元置相同的值。 STOSBSTOSB 往字节串中存数往字节串中存数 STOSW STOSW 往字串中存数往字串中存数 STOSD STOSD 往往双字串中存数双字串中存数串操作指令总结 源串指针源串指针: :DS: SI/ESI DS: S
30、I/ESI 即源串在当前数据段即源串在当前数据段 目标串的指针目标串的指针: :ES: DI/EDI ES: DI/EDI 即目的串在当前附加数据段即目的串在当前附加数据段 重复计数器重复计数器: :CX/ECXCX/ECX 中间寄存器中间寄存器: :AX/EL/EAXAX/EL/EAX 传送传送/ /比较方向比较方向: : DF=0, SI/ESI, DI/EDIDF=0, SI/ESI, DI/EDI自动增量自动增量( (加加1/1/加加2/2/加加4).4).DF=1, SI/ESI, DI/EDIDF=1, SI/ESI, DI/EDI自动减量自动减量( (减减1/1/减减2/2/减减
31、4).4). 指令格式指令格式: : 带操作数带操作数: : S S 不带操作数不带操作数: : SD (SD (双字操作双字操作) ) SW (SW (字操作字操作) ) SB (SB (字节操作字节操作) )串操作指令总结 重复前缀重复前缀: :REPREP重复执行重复执行, ,直到直到(CS/ECS)=0; (CS/ECS)=0; (主要是主要是MOVSMOVS指令使用指令使用) )REPE/REPZREPE/REPZZF=1 ZF=1 时重复执行时重复执行, ,直到直到(CS/ECS)=0; (CS/ECS)=0; REPNE/REPNZ ZF1REPNE/REPNZ ZF1时重复执行
32、时重复执行, ,直到直到(CS/ECS)=0;(CS/ECS)=0; 说明说明: :循环次数循环次数(CX)(CX)是否为是否为0 0是在操作之前检测的是在操作之前检测的, ,因此因此, ,当当(CX)(CX)为为0 0时不时不会引起串操作会引起串操作. .操作终止后操作终止后,SI,DI,SI,DI均指向下一待操作的均指向下一待操作的EA,EA,方向由方向由DFDF确确定定. .主要时主要时CMPS,SCASCMPS,SCAS指令使用指令使用工作流程工作流程串操作指令总结5.2 5.2 宏功能程序设计宏功能程序设计 宏定义宏定义 宏调用与宏扩展宏调用与宏扩展 宏指令中的参数宏指令中的参数 宏
33、库的使用宏库的使用 宏指令与子程序的比较宏指令与子程序的比较 宏定义宏定义宏指令在使用之前要先定义宏指令在使用之前要先定义. .定义格式定义格式: : 宏指令名宏指令名 MACRO MACRO 形式参数形式参数 ,形式参数,形式参数 宏体宏体 ENDMENDM 例如例如: : 某一程序中要多次使用某一程序中要多次使用DOS9DOS9号功能调用号功能调用: : LEA DXLEA DX,BUF1 BUF1 MOV AHMOV AH,9 9 INT 21H INT 21H LAE DXLAE DX,IN_BUF IN_BUF MOV AHMOV AH,9 9 INT 21HINT 21H 宏定义宏
34、定义他们之间的差别仅在于输出缓冲区的首址不一样他们之间的差别仅在于输出缓冲区的首址不一样. .如果讲该首址定义成如果讲该首址定义成形参形参, ,就可将其写成宏定义就可将其写成宏定义: :WRITEWRITE MACROMACRO A A LEA DX LEA DX,A A MOV AH MOV AH,9 9 INT 21H INT 21H ENDM ENDM 说明说明: :(1)(1)宏名字可以与其他变量宏名字可以与其他变量, ,标号标号, ,保留字同名保留字同名, ,汇编程汇编程序在处理时宏名字优先级最高序在处理时宏名字优先级最高. .利用这一特点利用这一特点, ,程序员可以程序员可以设计新
35、的指令系统设计新的指令系统. . 宏定义宏定义(2) (2) 形参可有可无个数不限形参可有可无个数不限, ,但总字符长度不超过但总字符长度不超过132132个个, ,个参个参数之间用逗号隔开数之间用逗号隔开; ;(3) (3) ENDMENDM和和MACROMACRO必须成对出现必须成对出现; ;(4) (4) 宏指令必须先定义后调用宏指令必须先定义后调用, ,因为它是在汇编期间处理的因为它是在汇编期间处理的. . 宏调用与宏扩展宏调用与宏扩展调用格式调用格式: 宏指令名宏指令名 实在参数实在参数 ,实在参数,实在参数 对于例对于例1 1中所作的宏定义中所作的宏定义, ,所应做的宏调用为所应做
36、的宏调用为: :WRITEWRITE BUF1 ; BUF1 ;宏调用宏调用 WRITEWRITE IN_BUF IN_BUF ; ;宏调用宏调用汇编程序的处理方式汇编程序的处理方式: :(1) (1) 第一次扫描时第一次扫描时, ,先扫描宏定义先扫描宏定义, ,将宏名字、形参、宏体均填入宏定将宏名字、形参、宏体均填入宏定义表中,义表中,再遇到宏调用时则嵌入宏体,用实参按位置顺序替换形参,再遇到宏调用时则嵌入宏体,用实参按位置顺序替换形参,这一过程称为宏扩展。这一过程称为宏扩展。 (2) (2) 第二次扫描时第二次扫描时, ,再将其转换成目标代码再将其转换成目标代码. . 宏调用与宏扩展宏调用
37、与宏扩展在汇编列表文件在汇编列表文件(.lst(.lst) )中中, ,宏拓展后的宏体语句均在前面冠宏拓展后的宏体语句均在前面冠以以”+”+”以示与其他语言的区别以示与其他语言的区别, ,即拓展后的形式为即拓展后的形式为: :+ LEA DX+ LEA DX,BUF1 BUF1 + MOV AH+ MOV AH,9 9 + INT 21H + INT 21H + LEA DX+ LEA DX,IN_FUTIN_FUT + MOV AH+ MOV AH,9 9 + INT 21H+ INT 21H 宏调用与宏扩展宏调用与宏扩展说明说明: : (1) (1) 宏指令名要与原宏定义的名字一致宏指令名
38、要与原宏定义的名字一致; ; (2) (2) 实参与形参应按位置关系一一对应实参与形参应按位置关系一一对应: :i.i.实参个数多形参实参个数多形参, ,多余实参被忽略多余实参被忽略; ; ii. ii.实参个数小于形参实参个数小于形参, ,缺少的实参被处理成空白缺少的实参被处理成空白( (没有字符没有字符).). DOS9 DOS9号和号和1010号调用写成一个宏定义号调用写成一个宏定义: :IOIOMACROMACRO A, BA, BLEA DX, LEA DX, A A ; ;形参形参A A代表输入代表输入/ /输出缓冲区首址输出缓冲区首址MOV AH, MOV AH, B B ; ;
39、形参形参B B代表代表DOSDOS调用号调用号INT 21HINT 21HENDMENDM 宏指令中的参数宏指令中的参数一、带几个符的参数一、带几个符的参数 在宏调用中,有时实参是一串带间隔符的字符串,为了不致混在宏调用中,有时实参是一串带间隔符的字符串,为了不致混淆,应该尖括号将它们括起来,说明为一个参数淆,应该尖括号将它们括起来,说明为一个参数. . 例如,每一个程序都需要定义堆栈段例如,每一个程序都需要定义堆栈段, ,只是堆栈的大小和初值不只是堆栈的大小和初值不一样一样 .可以讲定义堆栈的语句写成宏定义可以讲定义堆栈的语句写成宏定义: : DEF_STACKDEF_STACK MACRO
40、 MACRO A A STACK SEGMENT USE16 STACK STACK SEGMENT USE16 STACK DB DB A A STACK ENDS STACK ENDS ENDM ENDM 如果需要建立如果需要建立200200个字节、初值均为个字节、初值均为1 1的堆栈段,宏调用应为:的堆栈段,宏调用应为: DEF_STACK DEF_STACK 其中实参为一个重复子句,它中间带有空格,因此要用尖括号括起来 宏指令中的参数宏指令中的参数二、宏体中的变量与标号二、宏体中的变量与标号例例1. 1. 以下程序段的功能为以下程序段的功能为: :求从求从AAAA开始连续开始连续BBB
41、B个奇数个奇数( (或偶数或偶数) )的和送的和送AX.AX.AAAA=1=1BBBB=50=50MOVMOVBX,AABX,AAMOVMOVCX,BBCX,BBMOVMOVAX,0AX,0NEXT:ADDNEXT:ADDAX,BXAX,BXADDADDBX,2BX,2LOOPLOOPNEXTNEXT其宏定义和宏调用如下其宏定义和宏调用如下: :SUMSUMMACROMACROAA, BBAA, BBMOVMOVBX, AABX, AAMOVMOVCX, BBCX, BBMOVMOVAX, 0AX, 0NEXT:NEXT:ADDADDAX, BXAX, BXADDADDBX,2BX,2LOOP
42、LOOPNEXTNEXTENDMENDM SUMSUM1, 501, 50 SUMSUM10, 2010, 20 查看说明查看说明查看宏定义查看宏定义 宏指令中的参数宏指令中的参数+ +MOVMOVBX, 1BX, 1+ +MOVMOVCX, 50CX, 50+ +MOVMOVAX, 0AX, 0+ +NEXT:ADDNEXT:ADDAX, BX ;AX, BX ;标号标号NEXTNEXT第一次出现第一次出现+ +ADDADDBX, 2BX, 2+ +LOOPLOOPNEXTNEXT + +MOVMOVBX, 10BX, 10+ +MOVMOVCA, 20CA, 20+ +MOVMOVAX,
43、0AX, 0+ +NEXT:ADDNEXT:ADDAX, BX ;AX, BX ;标号标号NEXTNEXT第二次出现第二次出现, ,重复定义重复定义+ +ADDADDBX, 2BX, 2+ +LOOPLOOPNEXTNEXT 宏指令中的参数宏指令中的参数处理方式处理方式: : 1. 1. 将标号定义成形参将标号定义成形参, ,每次调用均用实参代替每次调用均用实参代替. .但会造成参数但会造成参数过多过多, ,给编程带来麻烦给编程带来麻烦; ; 2.2.使用伪指令使用伪指令LOCAL,LOCAL,让机器自动生成不同标号让机器自动生成不同标号. .格式格式: LOCAL : LOCAL 形式参数形
44、式参数,形式参数形式参数 功能功能: : 宏拓展时宏拓展时, ,汇编程序自动为其后形参生成特殊顺序号汇编程序自动为其后形参生成特殊顺序号, ,范围为范围为?OOOO - ?FFFFH,?OOOO - ?FFFFH,并用之取代形参并用之取代形参, ,避免重复避免重复定义定义. .注意注意: :该语句只能做宏体中的第一个语句该语句只能做宏体中的第一个语句. . 宏指令中的参数宏指令中的参数修改后的宏定义为修改后的宏定义为: :SUMSUMMACROMACROAA, BBAA, BBLOCALLOCALNEXTNEXTMOVMOVBX, AABX, AAMOVMOVCX,BBCX,BBMOVMOVA
45、X, 0AX, 0NEXT:NEXT:ADDADDAX, BXAX, BXADDADDBX, 2BX, 2LOOPLOOPNEXTNEXTENDMENDM相应的宏拓展为相应的宏拓展为: :+ +MOVMOVBX, 1BX, 1+ +MOVMOVCX, 50CX, 50+ +MOVMOVAX, 0AX, 0+ +?0000?0000:ADD:ADDAX,BX;AX,BX;标号标号NEXTNEXT转换转换?0000?0000+ +ADDADDBX, 2BX, 2+ +LOOP LOOP ?0000?0000+ +MOVMOVBX, 10BX, 10+ +MOVMOVCX, 20CX, 20+ +M
46、OVMOVAX, 0AX, 0+ +?0001?0001:ADD:ADDAX, BX;AX, BX;标号标号NEXTNEXT转换转换?0001?0001+ +ADDADDBX, 2BX, 2+ +LOOP LOOP ?0001?0001 宏库的使用宏库的使用 对于经常使用的宏定义,用户可将它们集中在一起,建成对于经常使用的宏定义,用户可将它们集中在一起,建成宏库供自己或别人随时调用。由于宏库为文本文件,可用一宏库供自己或别人随时调用。由于宏库为文本文件,可用一般编辑程序建立或修改,文件名也可由用户任意指定。般编辑程序建立或修改,文件名也可由用户任意指定。 例如:我们利用编辑程序,建立了一个宏库
47、例如:我们利用编辑程序,建立了一个宏库MACROMACROLIBLIB: : 当程序中需要调用时,应首先将宏库加入自己的源文件当程序中需要调用时,应首先将宏库加入自己的源文件中,然后按宏库中各宏定义的规定调用即可。中,然后按宏库中各宏定义的规定调用即可。将宏库加入源文件一起进行汇编将宏库加入源文件一起进行汇编可用伪指令可用伪指令INCLUDEINCLUDE实现。实现。 语句格式语句格式:INCLUDEINCLUDE 文本文件名文本文件名 功功 能能: 将指定的文本文件从本行起加入汇编,直到该将指定的文本文件从本行起加入汇编,直到该文本文件的最后一行汇编完后,再继续汇编文本文件的最后一行汇编完后
48、,再继续汇编INCLUDEINCLUDE后面的后面的语句。语句。 查看宏库查看宏库宏库调用宏库调用 宏库的使用宏库的使用宏库内容宏库内容: :READREADMACROMACROA ALEALEADX, ADX, AMOVMOVAH, 10AH, 10INTINT21H21HENDMENDMWRITEWRITEMACROMACROA ALEALEADX, ADX, AMOVMOVAH, 9AH, 9INTINT21H21HENDMENDMOUT1OUT1MACROMACROA AMOVMOVDL, ADL, AMOVMOVAH, 2AH, 2INTINT21H21HENDMENDMCRLFCR
49、LFMACROMACROOUT1OUT10AH0AHOUT1OUT10DH0DHENDMENDMSTACK0STACK0 MACROMACROA ASTACKSTACKSEGMENTSEGMENTUSE16 STACKUSE16 STACKDBDBA ASTACKSTACKENDSENDSENDMENDM 宏库的使用宏库的使用INCLUDE MACRO.LIBINCLUDE MACRO.LIB; ;将指定的宏库加入本程序一起汇编将指定的宏库加入本程序一起汇编.386.386DATADATASEGMENTSEGMENTUSE16USE16BUFBUFDB 80, 0, 80 DUP(0)DB 8
50、0, 0, 80 DUP(0)DATADATAENDSENDSSTACK0 STACK0 CODECODESEGMENT USE16SEGMENT USE16ASSUME DS: DATA, SS:STACK, CS: CODEASSUME DS: DATA, SS:STACK, CS: CODESTART:START: MOVMOVAX, DATAAX, DATAMOVMOVDS, AXDS, AXREADREADBUFBUF ; ;输入一字符串输入一字符串BUFBUF缓冲区缓冲区CRLFCRLF ; ;输出回车换行输出回车换行LEALEASI, BUF+2SI, BUF+2MOVMOVCL