第6章 高级汇编语言和模块化程序设计.ppt
第6章 高级汇编语言和模块化程序设计6.1 子程序6.2 宏6.3 多模块程序设计6.4 结构和记录6.1 子程序1 堆栈2 子程序的概念3 子程序格式和有关指令子程序的格式调用与返回指令4 子程序设计方法5 子程序的嵌套与递归调用6 子程序应用举例返回本章返回本章1 堆栈v进栈/出栈指令v寄存器入栈v寄存器出栈堆栈:以字为单位、按照先今后出的方式存取的内存。堆栈:以字为单位、按照先今后出的方式存取的内存。堆栈用来传递参数、临时存放数据、保存和恢复寄存器。堆栈用来传递参数、临时存放数据、保存和恢复寄存器。返回本节返回本节进栈/出栈指令v入栈指令语句格式:PUSH R16|M16|SEG功能:堆栈指针减2,将寄存器、段寄存器或存储器中的一个字数据压入堆栈。v出栈指令语句格式:POP R16|M16|SEG功能:将栈顶元素弹出送至某一寄存器、段寄存器(除CS外)或存储器,堆栈指针加2。返回本节返回本节寄存器入栈v格式:PUSHA 功能:所有16位寄存器(AX、BX、CX、DX、SI、DI、SP、BP)依次入栈,SP做相应的移动。指令执行后,(SP)-16 SPv格式:PUSHAD 功能:所有32位寄存器(EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP)依次入栈,SP做相应的移动。指令执行后,(SP)-32 SP返回本节返回本节寄存器出栈v格式:POPA 功能:栈顶内容依次出栈存于各16位寄存器(AX、BX、CX、DX、SI、DI、SP、BP)中,同时,SP做相应的移动。指令执行后,(SP)+16 SPv格式:POPAD 功能:栈顶内容依次出栈存于各32位寄存器(EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP)中,同时,SP做相应的移动。指令执行后,(SP)+32 SPPUSHA和POPA的执行图示返回本节返回本节执行前执行前PUSHASPSPAXCXDXBX原SPBPDISIPOPASPAXCXDXBX原SPBPDISI2 子程序的概念v在程序设计中,我们会发现一些多次无规律重复的程序段或语句序列。解决此类问题一个行之有效的方法就是将它们设计成可供反复调用的独立的子程序结构,以便在需要时调用。在汇编语言中,子程序又称过程。v调用子程序的程序称为主调程序或主程序。/主程序ST:CALL S1断点/子程序S1S1PROCST:RETS1ENDP子程序的特点1、功能独立2、通用性3、可浮动性:子程序可放在存储区任意地址4、可递归性:子程序调用其自身5、可重入性:子程序可被中断,在中断处理中又被中断服务程序调用,且都能提供正确结果。子程序的优点1、简化程序设计过程,节省设计时间2、缩短程序长度,节省汇编时间和程序执行空间3、增加程序可读性,便于修改与调试4、方便程序模块化、结构化和自顶向下程序设计方法返回本节返回本节调用与返回指令过程的正确执行由子程序的正确调用和返回保证。主程序中,通过CALL指令完成子程序调用,将CALL指令的下一条地址入栈保存,并修改IP为子程序的入口地址,即转子程序处执行。子程序中,通过RET指令完成子程序的返回,IP为栈顶出栈的内容,即转到主程序中调用语句的下一条语句处执行。1)段内调用与返回2)段间调用与返回调用与返回指令1)段内调用与返回*调用格式CALL NEAR PTR 子程序名功能:PUSH(IP),(IP)子程序入口的偏移地址子程序入口的偏移地址CALL WORD PTR 通用寄存器或存储器功能:功能:PUSH(IP),(IP)(IP)+D16注意:定义子程序的要求子程序是NEAR型,且与调用程序定义在同一代码段内*返回功能RET(IP)POP()RET EXP(IP)POP(),(SP)(SP或ESP)+D16调用与返回指令2)段间调用与返回*调用格式CALL FAR PTR 子程序名功能:PUSH(CS),PUSH(IP),(IP)子程序入口的偏移地址子程序入口的偏移地址CALL DWORD PTR 存储器功能:功能:PUSH(CS),PUSH(IP),(IP)(EA)(CS)(EA+2或或4)*返回RET功能:(IP)POP(),(CS)POP()RET 表达式功能:(IP)POP(),(CS)POP()(SP或ESP)(SP或ESP)+D16子程序的调用与返回DATASEGMENTMEQU8NEQU3RESDW?DATAENDSCODE SEGMENTASSUME CS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AXMOVCX,NCALLSUB1MOVBX,AXMOVCX,MCALLSUB1DIVBXMOVBX,AX SUBCX,NCALLSUB1XCHG BX,AXDIVBXMOVRES,AXMOVAX,4C00HINT 21HSUB1PROCMOVAX,1NEXT1:MULCXLOOP NEXT1RETSUB1ENDPCODE ENDSENDSTART例:计算例:计算例:计算例:计算HTOASCproc;将AL低4位表达的一位16进制数转换为ASCII码and al,0fhcmp al,9jbe htoasc1add al,37h;是0AH0FH,加37Hret;子程序返回htoasc1:add al,30h;是09,加30Hret;子程序返回HTOASCendp题子程序可以具有多个出口题子程序可以具有多个出口返回本节返回本节子程序的格式子程序的格式如下:过程名 PROC NEAR/FAR RET过程名 ENDP子程序和主程序在同一代码段中,定义为子程序和主程序在同一代码段中,定义为NEAR。书例。书例6.1子程序和主程序不在同一代码段中,定义为子程序和主程序不在同一代码段中,定义为FAR。书例。书例6.2可将主程序定义成可将主程序定义成FAR型供型供DOS调用调用子程序的说明:子程序的说明:1 1、子程序名、子程序名供供调用使用调用使用2 2、子程序功能、子程序功能供供选择子程序选择子程序3 3、占用寄存器、占用寄存器4 4、入口参数:执行子程序应具备的条件、入口参数:执行子程序应具备的条件5 5、输出参数:子程序执行后结果应放何处、输出参数:子程序执行后结果应放何处6 6、子程序调用示例:说明子程序调用格式、子程序调用示例:说明子程序调用格式一般过程名同标号一样,具有三种属性,即段属性、偏移地址属性以及类型属性。子程序可以嵌套定义。书例6.1例题v阅读下列子程序,写出子程序的功能、入口参数、出口参数SUB PROC NEAR/FARPUSH CXPUSH DXPUSH BXPUSH AXMOV CX,16BIN:ROL BX,1MOV DL,BLAND DL,1ADD DL,30HMOV AH,2INT 21HLOOP BINPOP AXPOP BXPOP DXPOP CX RETSUB ENDP功能:输出16位数的每一位二进制位入口参数:BX出口参数:输出每位二进制数4 子程序设计方法v信息的保护与恢复v主程序向子程序传递参数的方式v练习返回本节返回本节信息的保护与恢复v例如CR PROC FARMOV AH,2 MOV DL,13 INT 21H MOV DL,10 INT 21H RETCR ENDP主程序主程序MOV AX,102HMOV BX,304HCALL CRADDAX,BX 寄存器相当于全局量,为了在调用子程序时不破坏它在原来主程序中内容,需要在子程序功能实现前,将子程序要用到的寄存器原有的内容保护起来,在子程序功能实现后,将取出原数据存回原寄存器。这就是信息的保护与恢复。信息的保护与恢复v修改CR PROC FAR PUSHAXPUSHDXMOV AH,2 MOV DL,13 INT 21H MOV DL,10 INT 21HPOPDX POPAX RETCR ENDP主程序主程序MOV AX,102HMOV BX,304HCALL CRADDAX,BX 现场保护现场恢复例.求两个数的最大公约数的子程序分析:辗转相除法分析:辗转相除法1、取两个正数、取两个正数M,N2、RM MOD N3、若、若R为为0则则 N为当前最大公约数,算法结为当前最大公约数,算法结束;否则,束;否则,MN,NR,转转2子程序名:子程序名:MSDST功能:求两个正数的最大公约数功能:求两个正数的最大公约数入口参数:入口参数:AX,BX放两个正数放两个正数出口参数:出口参数:CX放最大公约数放最大公约数寄存器占用:寄存器占用:AX,BX,CX,DX MSDST PROC NEARPUSH AXPUSH BXPUSH CXPUSH DXAGAIN:XOR DX,DXDIV BX /AX-商,DX-余数AND DX,DXJZ EXITMOV AX,BXMOV BX,DX JMP AGAINEXIT:MOV CX,BXPOP DXPOP BX POP AXRETMSDST ENDP新问题新问题?返回本节返回本节作为入口参数的寄存器可以进行现场保作为入口参数的寄存器可以进行现场保护与恢复,但一定要匹配;作为出口参护与恢复,但一定要匹配;作为出口参数的寄存器不能进行现场保护与恢复。数的寄存器不能进行现场保护与恢复。主程序向子程序传递参数的方式v参数的形式:数据本身(传值)数据的地址(传址)v传递的方法:(1)寄存器法(2)约定单元法(3)堆栈法(4)通过地址表传递参数入口参数:主程序调用子程序前,将要加工的数据传给子程序出口参数:子程序执行完后,将结果传回主程序返回本节返回本节以求校验和为例以求校验和为例例.求校验和v子程序计算数组元素的“校验和”v校验和是指不记进位的累加入口参数:数组的逻辑地址(传址)元素个数(传值)出口参数:求和结果(传值)(1)寄存器法(2)约定单元法(3)堆栈法v把参数存于约定的寄存器中,可以传值,也可以传址。v子程序对带有出口参数的寄存器不能保护和恢复(主程序视具体情况进行保护)v子程序对带有入口参数的寄存器可以保护,也可以不保护;但最好一致入口参数:CX元素个数,DS:BX数组的段地址:偏移地址出口参数:AL校验和用寄存器传递参数特点:特点:传递参数方便、直观传递参数方便、直观传递参数的个数有限传递参数的个数有限mov bx,offset array;BX数组的偏移地址mov cx,count;CX数组的元素个数call checksuma;调用求和过程mov result,al;处理出口参数主程序主程序Checksuma procxor al,al;累加器清0suma:add al,bx;求和inc bx;指向下一个字节loop sumaretChecksuma endp 子程序子程序v主程序和子程序直接采用同一个变量名共享同一个变量,实现参数的传递v不同模块间共享时,需要声明入口参数:count元素个数,array数组名(含段地址:偏移地址)出口参数:result校验和用变量传递参数特点:可传递多个参数特点:可传递多个参数call checksumb 主程序子程序checksumbprocpush axpush bxpush cxxor al,al;累加器清0mov bx,offset array;BX数组的偏移地址mov cx,count;CX数组的元素个数sumb:add al,bx;求和inc bxloop sumbmov result,al;保存校验和pop cxpop bxpop axretchecksumbendpv主程序将子程序的入口参数压入堆栈,子程序从堆栈中取出参数v子程序将出口参数压入堆栈,主程序弹出堆栈取得它们入口参数:顺序压入偏移地址和元素个数出口参数:AL校验和用堆栈传递参数mov ax,offset arraypush axmov ax,countpush axcall checksumcadd sp,4add sp,4add sp,4add sp,4mov result,al 主程序主程序子程序子程序Checksumc procpush bpmov bp,sp ;利用BP间接寻址存取参数push bxpush cxmov bx,bp+6 mov cx,bp+4 xor al,alsumc:add al,bx inc bxloop sumcpop cxpop bxpop bpretretretretChecksumc endp 要要注注意意堆堆栈栈的的分分配配情情况况,保保证证参参数数存存取取正正确确、子子程程序序正正确确返返回回,并并保保持堆栈平衡持堆栈平衡4(1)寄存器法DATASEGMENTBCDBUF DB 56H,23H,74H,23H,67H DB 45H,28H,91H,83H,57HCOUNT EQU$-BCDBUFASCBUF DB 20 DUP(?)DATAENDSSTACK SEGNMENT PARA STACKSTAPN DB 20 DUP(?)TOP EQU LENGTH STAPNSTACK ENDSCODESEGMENTASSUME CS:CODE,DS:DATA,SS:STACKSTART:MOVAX,DATAMOVDS,AXMOVAX,STACKMOVSS,AXMOV AX,TOPMOVSP,AXLEASI,BCDBUFLEADI,ASCBUFMOVCX,COUNTCLDLP:LODSBMOVBL,ALANDAL,0FHORAL,30HMOVDL,ALSTOSBCALL DISPMOV AL,BLPUSHCXMOVCL,4SHRAL,CLORAL,30HMOVDL,ALSTOSBCALL DISPPOPCXLOOP LPMOVAX,4C00H INT21HDISPPROCMOVAH,2INT21HMOVDL,MOVAH,2INT21HRETDISPENDPCODE ENDSENDSTART(2)约定单元法DATASEGMENTBCDBUF DB 56H,23H,74H,23H,67H DB 45H,28H,91H,83H,57HCOUNT EQU$-BCDBUFASCBUF DB 20 DUP(?)DATAENDSSTACK SEGNMENT PARA STACKSTAPN DB 20 DUP(?)TOP EQU LENGTH STAPNSTACK ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACKSTART:MOVAX,DATAMOVDS,AXMOVAX,STACKMOVSS,AXMOV AX,TOPMOVSP,AXLEASI,BCDBUFLEADI,ASCBUFMOVCX,COUNTCLDLP:LODSBMOVBL,ALANDAL,0FHORAL,30H/MOVDL,ALSTOSBCALL DISPMOV AL,BLPUSHCXMOVCL,4SHRAL,CLORAL,30H/MOVDL,ALSTOSBCALL DISPPOPCXLOOP LPMOVAX,4C00H INT21HDISPPROCPUSHDIDECDIMOVDL,DIMOVAH,2INT21HPOPDIMOVDL,MOVAH,2INT21HRETDISPENDPCODE ENDSENDSTART(3)堆栈法DATASEGMENTBCDBUF DB 56H,23H,74H,23H,67H DB 45H,28H,91H,83H,57HCOUNT EQU$-BCDBUFASCBUF DB 20 DUP(?)DATAENDSSTACK SEGNMENT PARA STACKSTAPN DB 20 DUP(?)TOP EQU LENGTH STAPNSTACK ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACKSTART:MOVAX,DATAMOVDS,AXMOVAX,STACKMOVSS,AXMOV AX,TOPMOVSP,AXLEASI,BCDBUFLEADI,ASCBUFMOVCX,COUNTCLDLP:LODSBMOVBL,ALANDAL,0FHORAL,30HMOVAH,0PUSHAXSTOSBCALL DISPMOV AL,BLPUSHCXMOVCL,4SHRAL,CLORAL,30H POPCXMOVAH,0PUSHAXSTOSBCALLDISPLOOP LPMOVAX,4C00H INT21HDISPPROCPOP DXMOVAH,2INT21HMOVDL,MOVAH,2INT21HRETDISPENDPCODE ENDSENDSTARTprog segmentorg 100hassume cs:prog,ds:prog,ss:progmainprocfarmov ax,progmovds,axmovss,axmovtable,offset arymovtable+2,offset countmovtable+4,offset summovbx,offset tablecallproaddretmainendpproaddprocnearpushaxpushcxpushsipushdimovsi,bxmovdi,bx+2通过地址表传递参数movcx,dimovdi,bx+4xorax,axnext:addax,siaddsi,2loopnextmovdi,axpopdipopsipopcxpopaxretproadd endparydw100 dup(?)countdw100sumdw?tabledw3 dup(?)progendsendmain练习sub1procnearpushdipushdxpushcxpushaxmovcx,0leadi,tbuffdec1:pushcxmovax,dxmovdx,0movcx,10divcxxchgax,dxaddal,30hmovdi,alincdipopcxinccxcmpdx,0;*jnzdec1dec2:decdimoval,dicallsuboutloopdec2pop axpopcxpopdxpopdiretsub1endp子程序的功能?子程序的功能?标标*号处指令的注释?号处指令的注释?子程序的入口参数和出口参数?子程序的入口参数和出口参数?dx寄存器中的数转换成十进制数存于寄存器中的数转换成十进制数存于TBUFF中并显示中并显示被除数是被除数是0吗?吗?入口参数:入口参数:dx:待转换成十进制数的数待转换成十进制数的数出口参数:分解出的每一位十进制数字存于出口参数:分解出的每一位十进制数字存于DI指向的指向的TBUFF缓存中缓存中练习v编写子程序实现字节数据块的传送入口参数:SI指向源块首地址,DI指向目的块首地址,CX存放数据块长度.出口参数:SI指向源块首地址,DI指向目的块首地址.返回本节返回本节5 子程序的嵌套与递归调用v子程序的嵌套 子程序不但可以被主程序调用,而且也可以被其他子程序调用。我们把一个子程序调用另一个子程序称为子程序的嵌套调用。v子程序的递归调用 子程序的递归调用是指一个子程序直接或间接地调用自己。递归子程序一般对应于数学上对函数的递归定义,它往往能设计出效率较高的程序,完成相当复杂的计算,因而是很有用的。IP子5(AX)=IIP子4(AX)=IP子6(AX)=TIP子IP子子程序嵌套实例IP子IP子v以子程序嵌套的方法实现显示以”0”结尾的字符串DATASEGMENTMSGDBFIX IT!,0DATAENDSSTACKSEGMENTDW 20H DUP(?)TOPLABEL WORDSTACKENDSCODESEGMENTASSUME CS:CODE,DS:DATA,SS:STACKSTART:MOV AX,DATAMOV DS,AXMOV AX,STACKMOV SS,AXLEA SP,TOPCLDMOV SI,OFFSET MSGCALL DPSTRMOV AH,4CHINT 21HDPSTR PROCPUSH AXL1:LODSBCMP AL,0JZ L2CALL DPSTRPOP AX CALL DPCHAR JMP L3L2:POP AX L3:RETDPSTR ENDP40HIP主(AX)主IP子1(AX)=FDPCHAR PROCMOV DL,ALMOV AH,2INT 21HRETDPCHAR ENDPCODEENDSEND STARTIP子2(AX)=IIP子3(AX)=XIP子7(AX)=!地址递减IP子8(AX)=0IP子IP子IP子递归调用实例试编制计算N!(N0)的程序。N!=N*(N-1)*(N-2)*1其递归定义如下:0!=1N!=N*(N-1)!(N1)计算N!的子程序FACT的流程图如下。计算5!的程序示例,RESULT是保存阶乘的存储单元。STACKSEGMENT STACKDB 200 DUP(0)STACKENDSDATASEGMENTNDW 5RESULTDW?DATAENDSCODESEGMENT ASSUME CS:CODE,SS:STACK,DS:DATASTART:MOVAX,DATA MOVDS,AXMOV AX,NCALL FACTMOV AX,RESULTMOV AX,4C00HINT21HFACTPROCCMP AX,0JNEL1MOV RESULT,1JMPEXITL1:PUSH AXDECAXCALL FACTPOPCXMULCLMOV RESULT,AXEXIT:RETFACTENDPCODE ENDSENDSTART返回本节返回本节6 子程序应用举例v代码转换子程序十六进制数的ASCII转换成二进制数二进制数转换成十进制数十进制数转换成v十进制数用BCD码表示v十进制数用ASCII码表示子程序的设计方法作为独立和通用的程序段,设计子程序时应注意以下问题:1、子程序要利用过程定义伪指令声明,获得子程序名和调用属性2、子程序最后要用RET伪指令返回主程序。3、子程序子程序开始时应注意保护用到的寄存器内容,子程序返回前进行相应的恢复。对堆栈的压入和弹出操作要成对使用,保持堆栈的平衡。SUB1 PROC将子程序用到的寄存器入栈保存子程序的功能段将堆栈的内容弹出到相应的寄存器SUB1 ENDP4、子程序可以与主程序共用一个数据段,也可是用不同的数据段。5、子程序在代码段的主程序开始执行之前的位置,也可放在主程序执行终止后的位置(返回DOS后,汇编结束END伪指令前)6、处理好参数传递,并提供必要的子程序说明。7、子程序允许嵌套和递归。4位十六进制数的ASCII转换成16位二进制数v入口参数:AL(键盘输入1位十六进制数)v出口参数:一个16位二进制数存于DXHEX16IN PROC NEAR/FARPUSH CXPUSH AXPUSH BXMOV BL,4MOV DX,0L1:MOV AH,1INT 21HSUB AL,30HJL L3CMP AL,9JLE L2SUB AL,7CMP AL,0AHJL L3CMP AL,0FHJG L3L2:CBWMOV CL,4SAL DX,CLADD DX,AXDEC BLJNZ L1L3:POP BXPOP AXPOP CXRETHEX16IN ENDP16位二进制数转换成十进制数的ASCIIv入口参数:DX(16位二进制数)v出口参数:以十进制数形式输出这个16位的二进制数DEC16OUT PROC NEAR/FARPUSH SIPUSH DIPUSH CXPUSH AXMOV CX,5LEA SI,DDEC;放位权的缓存放位权的缓存LEA DI,TBUFF;放十进制数的临时缓存放十进制数的临时缓存PUSH CXMOV AX,DXCONV:MOV BL,0RRR:SUB AX,SIJC NEXTINC BLJMP RRRNEXT:ADD AX,SIOR BL,30HMOV DI,BLINC SI;位权以字数据存放位权以字数据存放INC SIINC DILOOP CONVPOP CXCRT:DEC DIMOV DL,DIMOV AH,2INT 21HLOOP CRTPOP AXPOP CXPOP DIPOP SIRETDEC16OUT ENDP将将ASCIIASCII码表示的十进制数转换成码表示的十进制数转换成1616位的二进制数位的二进制数v入口参数:输入ASCII码表示的十进制数v出口参数:结果放在DXDEC16IN PROC NEAR/FARPUSH CXPUSH AXMOV DX,0L1:MOV AH,1INT 21HSUB AL,30HJL L2CMP AL,9JG L2CBWPUSH AXMOV AX,DXMOV CX,10MUL CXMOV DX,AXPOP AXADD DX,AXJMP L1L2:POP AXPOP CXRETDEC16IN ENDP【例】将一个给定的二进制数按位转换成相应的ASCII码字符串,送到指定的存储单元并显示。如二进制数10010011转换成字符串为10010011。要求将转换过程写成子程序,且子程序应具有较好的通用性,能实现对8位和16位二进制数的转换。入口参数:DX存放待转换的二进制数CX存放待转换数的位数(8位或16位)DI存放ASCII码首地址出口参数:转换后的字符串存放在以DI作指针的字节存贮区中程序如下:DATA SEGMENTNUM8DB93HNUM16DW0ABCDHASCBUFDB20DUP(0)DATA ENDSCODESEGMENT ASSUME DS:DATA,CS:CODE,SS:STACKSTART:MOVAX,DATAMOVDS,AXMOVDX,0MOVDL,NUM8;转换二进制数送DXMOVCX,8;置位数8LEADI,ASCBUF;字符串首址DICALLBTASC;调用子程序BTASCMOV BYTE PTR DI,0DHMOV BYTE PTR DI+1,0AH MOV BYTE PTR DI+2,$LEADX,ASCBUFMOVAH,9INT21HMOVDX,NUM16MOVCX,16;置位数16LEADI,ASCBUFCALLBTASC MOV BYTE PTR DL,0DHMOV BYTE PTR DL+1,0AHMOV BYTE PTR DL+2,LEADX,ASCBUF MOVAH,9 INT21H显示转换后的字符串显示转换后的字符串BTASCPROCPUSH AX;保存AXCMP CX,8;比较8位数JNE L1;直接转换16位数MOV DH,DL;8位数转换送DHL1:MOV AL,0ROL DX,1;DX最高位移入CFRCL AL,1;CF移入AL最低位ADD AL,30HMOV DI,ALINCDILOOP L1POPAXRETBTASC ENDPCODEENDSENDSTART返回本节返回本节6.2 宏v宏指令v宏指令的使用过程v宏操作符v局部符号伪指令LOCALv宏库的使用v重复汇编重复汇编v条件汇编v宏的递归与嵌套v宏与过程的区别宏宏具有宏名的一段汇编语句序列,具有宏名的一段汇编语句序列,宏定义宏定义时书写时书写宏指令宏指令这段汇编语句序列的缩写,这段汇编语句序列的缩写,宏调用宏调用时书写时书写宏展开宏展开宏指令处用这段宏代替的过程,宏指令处用这段宏代替的过程,宏汇编宏汇编时实现时实现返回本章返回本章 宏指令v在汇编语言程序设计过程中,可以将具有一定功能、需多次重复使用、比较短的程序段定义成一条宏指令。v使用宏指令语句可以减少程序书写错误,缩短源程序长度,使源程序编写像高级语言一样清晰、简洁。特别是使用宏库后,可以提高编程效率。返回本节返回本节宏指令的使用过程1)宏定义2)宏调用3)宏扩展程序员的工作汇编的工作 宏定义(1)带参宏定义的格式宏指令名宏指令名 MACRO 形参形参1,形参,形参2,宏体宏体 ENDM(2)无参宏定义的格式宏指令宏指令 MACRO宏体宏体ENDM例:例:PRINT MACRO BUFLEADX,BUFMOVAH,9INT21HENDM宏调用格式:宏指令名宏指令名 实参实参1,实参,实参2,例如:对上面的宏定义的三种调用形式为:PRINT BUF1PRINT BUF2PRINT BUF3宏扩展+LEA DX,BUF1+MOV AH,9+INT 21H+LEA DX,BUF2+MOV AH,9+INT 21H +LEADX,BUF3+MOVAH,9+INT21H 例如:上面三次宏调用,其展开的形式为:例如:上面三次宏调用,其展开的形式为:汇编时扫描到宏指令语句,将宏定义中宏体的程序段目标代码插入宏指令语句所在的位置上返回本节返回本节 宏操作符v连接操作符在宏定义时,放在形参前面或后面。在宏展开时,实参与它前/后的符号连接在一起构成新的符号。SHIFT_VAR MACRO R_M,DIRECT,COUNTMOV CL,COUNTS&DIRECT R_M,CLENDM宏调用宏调用SHIFT_VAR AX,HL,2宏展开宏展开+MOV CL,2+SHL AX,CL 宏操作符v文本操作符用途:实参由字符、空格、逗号等构成时需要用文本操作符将它们括起来作为单一的实参使用【例】在程序中定义大小及初值不同的堆栈段。可用如下宏定义:EXCHANGEMACRO W1,W2,R_MMOVR_M,W1XCHGAL,W2MOVW1,ALENDM宏调用宏调用EXCHANGE,AL宏展开宏展开+MOV AL,BYTE PTR DA_WORD1+XCHG AL,BYTE PTR DA_WORD2+MOV BYTE PTR DA_WORD1,AL【例】表达符操作%示例。DATA1MACROA,B,C,D DWA,B,CDBD DUP(0)ENDM如果宏调用为:X=10Y=20DATA1%X+2,5,%X+Y,%Y-5DATA1X+2,5,X+Y,Y-5宏展开宏展开DATA1+DW 12D,5D,30D+DB15 DUP(0)宏展开宏展开DATA1+DWX+2,5,X+Y+DBY-5 DUP(0)宏操作符返回本节返回本节v表达式操作符%格式:%表达式表达式功能:%告诉汇编程序获得表达式的值获得表达式的值局部符号伪指令LOCAL【例例】局部符号伪指令局部符号伪指令LOCAL应用。应用。SUM MACROX,YLOCAL LMOVCX,XMOVBX,YMOVAX,0L:ADDAX,BXINCBXLOOPLENDM如果两次调用宏指令如下:如果两次调用宏指令如下:SUM100,1 SUM50,1 用途:同一源程序中多次调用包含标号、变量定义的宏,在展开时不会产生多个相同变量或标号则宏扩展形式为:MOVCX,100MOVBX,1MOVAX,0?0000:ADDAX,BXINCBXLOOP?0000MOVCX,50MOVBX,10MOVAX,0?0001:ADDAX,BX INCBXLOOP?0001返回本节返回本节宏库的使用语句格式语句格式:INCLUDE 库文件名库文件名假设已建立一名为假设已建立一名为MACRO.LIB的宏库,其内容如下:的宏库,其内容如下:INPUTMACRO ALEADX,AMOVAH,10INT21HENDMPRINTMACRO ALEADX,AMOVAH,9INT21HENDMRETURNMACRO MOVAH,2MOVDL,0AHINT21HMOVDL,0DHINT21HENDM 为了提高程序员编程的效率,将经常用的功能代码段编写成宏,以文件的形式组成一个宏库,供其它源程序使用。OUT2MACRO AMOVDL,AMOVAH,2INT21HENDMSTACK0 MACRO A STACK SEGMENT STACKDBA STACKENDSENDM现要从键盘输入一串字符到系统缓冲区,然后将字符按相反顺序现要从键盘输入一串字符到系统缓冲区,然后将字符按相反顺序打印,采用调用宏库的办法,其程序如下打印,采用调用宏库的办法,其程序如下:INCLUDEMACRO.LIBSTACK0200DUP(0);定义堆;定义堆栈段栈段DATASEGMENTINF01DBINPUT STRING:INF02DBOUTPUT STRING:BUFADB81DB?DB80 DUP(0)BUFBDB 81 DUP(0)DATAENDSCODESEGMENTASSUME DS:DATA,SS:STACK,CS:CODESTART:MOVAX,DATAMOVDS,AX RETURN;输出回车换行;输出回车换行PRINT INFO1;输出字符变量;输出字符变量INFO1代表的字符串代表的字符串INPUT BUFA;键盘输入字符中到缓冲区;键盘输入字符中到缓冲区;LEA SI,BUFA+1MOV CH,0MOV CL,SIADD SI,CXLEA DI,BUFBNEXT:MOVAL,SIMOVDI,ALDECSIINCDILOOPNEXTMOVBYTE PTR DI,RETURN;输出回车换行;输出回车换行PRINTINF02;输出的字符串变量输出的字符串变量INF02代表代表PRINTBUFB;反向输出输入字符串反向输出输入字符串MOVAH,4CHINT21HCODEENDSENDSTART返回本节返回本节宏的递归与嵌套 v宏允许嵌套调用和递归调用。对这种宏中套宏的调用,汇编程序将逐次展开,直到展开后的结果不再含有宏调用为止。v 例例 宏嵌套调用的宏定义如下:宏嵌套调用的宏定义如下:SHIFT MACRO N1,N2SAL N2,1RCL N1,1ENDMMULT MACRO R1,R2,REG1,REG2PUSHFPUSH REG1PUSH REG2SHIFT R1,R2SHIFT R1,R2MOV REG1,R1MOV REG2,R2SHIFT R1,R2ADD R2,REG2ADC R1,REG1POP REG2POP REG1POPFENDM设DA为字型数据变量,宏调用为:MULT DA+2,DA,CX,DX宏展开后结果如下:+PUSHF+PUSH CX+PUSH DX+SAL DA,1+RCL DA+2,1+SAL DA,1+RCL DA+2,1+MOV CX,DA+2+MOV DX,DA+SAL DA,1+RCL DA+2,1+ADD DA,DX+ADC DA+2,CX+POP DX+POP CX+POPF宏的递归与嵌套 宏的递归与条件汇编一起使用宏的递归与条件汇编一起使用例:下面用条件汇编定义一个递归调用宏POW,该宏完成2N*X的运算,实际上是完成对X进行算术左移N位的操作 宏定义:宏定义:POW MACRO X,N SAL X,1 COUNT=COUNT+1IF COUNT-N ;当当COUNT=N时,递归调用结束时,递归调用结束 POW X,N ENDIFENDM宏调用:宏调用:COUNT=0POW AX,31 SAL AX,1;当;当COUNT=0时时1 SAL AX,1;当;当COUNT=1时时1 SAL AX,1;当;当COUNT=2时时返回本节返回本节宏展开:宏展开:重复汇编重复汇编重复汇编指在汇编过程中,重复展开一段(基本)相同的语句1)给定次数的重复汇编伪指令格式:REPT 表达式表达式重复块重复块ENDM功能:宏汇编程序将重复块连续地汇编表达式给定的次数。2)不定次数的重复汇编伪指令,有IRP和IRPC两种伪指令。格式:IRP 形参,形参,重复块重复块ENDM格式:IRPC 形参,字符串形参,字符串重复块重复块ENDM功能:对重复块重复汇编,重复汇编次数由实参个数决定。给定次数的重复汇编实例宏定义1char=AREPT 26 db char char=char+1ENDM汇编后宏展开 1db char;等效于db A 1char=char+1 1db char;等效于db B 1char=char+1.1db char;等效于db Z 1char=char+1宏定义2PUSH_TAB MACRO K PUSH TAB+KENDM宏调用 I=0 REPT 5 PUSH_TAB%I I=I+2 ENDM汇编后宏展开 2 PUSH TAB+0 2 PUSH TAB+2 2 PUSH TAB+4 2