收藏 分享(赏)

Ch06 子程序与宏指令设计.ppt

上传人:tkhy51908 文档编号:8252400 上传时间:2019-06-16 格式:PPT 页数:129 大小:628KB
下载 相关 举报
Ch06 子程序与宏指令设计.ppt_第1页
第1页 / 共129页
Ch06 子程序与宏指令设计.ppt_第2页
第2页 / 共129页
Ch06 子程序与宏指令设计.ppt_第3页
第3页 / 共129页
Ch06 子程序与宏指令设计.ppt_第4页
第4页 / 共129页
Ch06 子程序与宏指令设计.ppt_第5页
第5页 / 共129页
点击查看更多>>
资源描述

1、第六章 子程序与宏指令设计,为了程序共享或模块化设计的需要,可以把一段公共语句序列设计成子程序或宏指令的形式。,6.1 子程序结构及设计方法 6.2 子程序参数传递 6.3 嵌套与递归子程序 6.4 宏 指 令 6.5 宏指令库 6.6 重复伪指令 6.7 条件伪指令,6.1 子程序结构及设计方法,6.1.1 含有子程序的程序结构在汇编语言中用过程定义伪指令定义子程序。过程定义伪指令格式:过程名 PROC 属型过程名 ENDP,1调用程序和子程序在同一个代码段的程序结构(子程序类型可缺省,注意END后必须跟主程序名)CODE SEGMENTMAIN PROC FARCALL SUB1RETMA

2、IN ENDPSUB1 PROC RETSUB1 ENDPCODE ENDSEND MAIN,2调用程序和子程序在不同段的程序结构 (SUB2既被段间调用又被段内调用,必须是FAR属性。CALL要显式说明是FAR属性)CODE1 SEGMENT MAIN PROC FARCALL FAR PTR SUB2RETMAIN ENDPCODE1 ENDSCODE2 SEGMENTSUB1 PROC FAR CALL FAR PTR SUB2RETSUB1 ENDPSUB2 PROC FAR RETSUB2 ENDPCODE2 ENDSEND MAIN,6.1.2 设计子程序时应注意的问题1子程序说明

3、 2寄存器的保存与恢复 3密切注意堆栈状态,6.2 子程序参数传递,可以通过给子程序传递参数使其更通用。常用的参数传递方法如下:通过寄存器传递;若调用程序和子程序在同模块(源程序)中,子程序可以直接访问模块中的变量;通过地址表传递参数地址;通过堆栈传递参数或参数地址。,6.2.1 通过寄存器传递这种传递方式使用方便,适用于参数较少的情况。例1把BX中的16位二进制数转换成十进制并显示在屏幕上。,STASG SEGMENTDW 32 DUP(?) STASG ENDS CODE SEGMENTASSUME CS:CODE MAIN PROC FARMOV BX,162EHCALL TERN MO

4、V AX,4C00HINT 21H MAIN ENDP,程序6.3,TERN PROC ;二十并显示。MOV CX,10000CALL DEC_DIV ;转换万位数MOV CX,1000CALL DEC_DIV ;转换千位数MOV CX,100CALL DEC_DIV ;转换百位数MOV CX,10CALL DEC_DIV ;转换十位数MOV CX,1CALL DEC_DIV ;转换个位数RET TERN ENDP,DEC_DIV PROC ;CX中为十进制的位权MOV AX,BXMOV DX,0DIV CX ;商为转换后的一位十进制数MOV BX,DXMOV DL,ALADD DL,30H

5、;转换成ASCII码MOV AH,2 ;显示INT 21HRET DEC_DIV ENDP CODE ENDSEND MAIN,6.2.2 同模块中的子程序可直接访问模块中的变量若调用程序和子程序在同模块中,子程序可以直接访问模块中的变量。例2实现数组求和功能。要求数组求和(不考虑溢出情况)由子程序实现,其数组元素及结果均为字型数据。见程序6.4。,STACKSG SEGMENT STACK STKDW 32 DUP(S)STACKSG ENDSDATA SEGMENTARY DW 1,2,3,4,5,6,7,8,9,10COUNT DW ($-ARY)/2 ;数组元素个数SUM DW ? ;

6、数组和的地址DATA ENDS,程序6.4,CODE1 SEGMENT MAIN PROC FARASSUME CS:CODE1,DS:DATAPUSH DSXOR AX,AXPUSH AXMOV AX,DATAMOV DS,AXCALL FAR PTR ARY_SUMRET MAIN ENDP CODE1 ENDS,CODE2 SEGMENTASSUME CS:CODE2 ARY_SUM PROC FAR ;数组求和子程序PUSH AX ;保存寄存器PUSH CXPUSH SILEA SI,ARY ;取数组起始地址MOV CX,COUNT ;取元素个数XOR AX,AX ;清0累加器,NEX

7、T: ADD AX,SI ;累加和ADD SI,TYPE ARY ;修改地址指针LOOP NEXTMOV SUM,AX ;存和POP SI ;恢复寄存器POP CXPOP AXRET ARY_SUM ENDP CODE2 ENDSEND MAIN,6.2.3 通过地址表传递参数地址适用于参数较多的情况。具体方法是先建立一个地址表,该表由参数地址构成。然后把表的首地址通过寄存器或堆栈传递给子程序。例3编写一个数组求和子程序,其数组元素及结果均为字型数据。另定义两个数组,并编写一个主程序,通过调用数组求和子程序分别求出两个数组的和。见程序6.5。,程序6.5,STACKSG SEGMENT STA

8、CK STKDW 32 DUP(S) STACKSG ENDS DATA SEGMENT ARY DW 1,2,3,4,5,6,7,8,9,10 ;数组1 COUNT DW ($-ARY)/2 ;数组1的元素个数 SUM DW ? ;数组1的和地址 NUM DW 10,20,30,40,50 ;数组2 CT DW ($-NUM)/2 ;数组2的元素个数 TOTAL DW ? ;数组2的和地址 TABLE DW 3 DUP(?) ;地址表 DATA ENDS,CODE1 SEGMENTMAIN PROC FARASSUME CS:CODE1,DS:DATAPUSH DSXOR AX,AXPUSH

9、 AXMOV AX,DATAMOV DS,AX ;构造数组1的地址表MOV TABLE,OFFSET ARYMOV TABLE+2,OFFSET COUNTMOV TABLE+4,OFFSET SUMLEA BX,TABLE ;传递地址表首地址CALL FAR PTR ARY_SUM,;构造数组2的地址表MOV TABLE,OFFSET NUMMOV TABLE+2,OFFSET CTMOV TABLE+4,OFFSET TOTALLEA BX,TABLE;传递地址表的首地址CALL FAR PTR ARY_SUM;段间调用调用数组求和子程序RET MAIN ENDP CODE1 ENDS,C

10、ODE2 SEGMENTASSUME CS:CODE2 ARY_SUM PROC FAR ;数组求和子程序PUSH AX ;保存寄存器PUSH CXPUSH SIPUSH DI MOV SI,BX ;取数组起始地址MOV DI,BX+2 ;取元素个数地址MOV CX,DI ;取元素个数MOV DI,BX+4 ;取结果地址XOR AX,AX ;清0累加器,NEXT: ADD AX,SI ;累加和ADD SI,TYPE ARY ;修改地址指针LOOP NEXTMOV DI,AX ;存和POP DI ;恢复寄存器POP SIPOP CXPOP AXRET ARY_SUM ENDP CODE2 END

11、SEND MAIN,6.2.4 通过堆栈传递参数或参数地址这种方式适用于参数较多,或子程序有多层嵌套、递归调用的情况。 步骤: 主程序把参数或参数地址压入堆栈; 子程序使用堆栈中的参数或通过栈中参数地址取到参数; 子程序返回时使用RET n指令调整SP指针,以便删除堆栈中已用过 的参数,保持堆栈平衡,保证程序的正确返回。,例4完成数组求和功能,求和由子程序实现,要求通过堆栈传递参数地址。STACKSG SEGMENT STACK STKDW 16 DUP(?)STACKSG ENDSDATA SEGMENTARY DW 1,2,3,4,5,6,7,8,9,10COUNT DW ($-ARY)/

12、2SUM DW ?DATA ENDS,程序6.6,CODE1 SEGMENT MAIN PROC FARASSUME CS:CODE1,DS:DATAPUSH DS ;XOR AX,AXPUSH AX ;MOV AX,DATAMOV DS,AX,LEA BX,ARYPUSH BX ;压入数组起始地址LEA BX,COUNTPUSH BX ;压入元素个数地址LEA BX,SUMPUSH BX ;压入和地址CALL FAR PTR ARY_SUM;调用求和子程序RET ; MAIN ENDP CODE1 ENDS,CODE2 SEGMENTASSUME CS:CODE2 ARY_SUM PROC

13、FAR ;数组求和子程序PUSH BP ;保存BP值MOV BP,SP ;BP是堆栈数据的地址指针PUSH AX ;保存寄存器内容PUSH CX ;PUSH SI ;PUSH DI ;MOV SI,BP+10 ;得到数组起始地址MOV DI,BP+8 ;得到元素个数地址MOV CX,DI ;得到元素个数MOV DI,BP+6 ;得到和地址XOR AX,AX,NEXT: ADD AX,SI ;累加ADD SI,TYPE ARY ;修改地址指针LOOP NEXTMOV DI,AX ;存和POP DI ;恢复寄存器内容POP SI ;POP CX ; POP AX ;POP BP ;RET 6 ;返

14、回并调整SP指针 ARY_SUM ENDP CODE2 ENDSEND MAIN,返回,程序6.6中所有入栈操作对堆栈的影响,返回,程序6.6中主程序的RET执行前堆栈状态,例5完成数组求和功能,其中求和由子程序实现,要求使用结构访问堆栈中的参数。编码见程序6.7。,返回,SS,SP,BP,程序6.7的堆栈及结构数据示意图,结构,程序6.7,STACKSG SEGMENT STACK STKDW 16 DUP(S) STACKSG ENDS DATA SEGMENT ARY DW 1,2,3,4,5,6,7,8,9,10 COUNT DW ($-ARY)/2 SUM DW ? DATA END

15、S,CODE1 SEGMENT MAIN PROC FARASSUME CS:CODE1,DS:DATAPUSH DSXOR AX,AXPUSH AXMOV AX,DATAMOV DS,AX,LEA BX,ARYPUSH BX ;压入数组起始地址LEA BX,COUNTPUSH BX ;压入元素个数地址LEA BX,SUMPUSH BX ;压入和地址CALL FAR PTR ARY_SUMRET MAIN ENDP CODE1 ENDS,CODE2 SEGMENTASSUME CS:CODE2 STACK_STRC STRUC ;定义结构 SAVE_BP DW ? SAVE_CS_IP DW

16、2 DUP(?) SUM_ADDR DW ? COUNT_ADDR DW ? ARY_ADDR DW ? STACK_STRC ENDS,ARY_SUM PROC FAR ;数组求和子程序PUSH BP ;保存BP值MOV BP,SPPUSH AXPUSH CXPUSH SIPUSH DIMOV SI,BP.ARY_ADDR;数组始地址MOV DI,BP.COUNT_ADDRMOV CX,DIMOV DI,BP.SUM_ADDR;得到和地址XOR AX,AX,NEXT: ADD AX,SI ;累加ADD SI,TYPE ARY ;修改地址指针LOOP NEXTMOV DI,AX ;存和POP

17、DIPOP SIPOP CXPOP AXPOP BPRET 6 ;返回并调整SP指针 ARY_SUM ENDP CODE2 ENDSEND MAIN,子程序嵌套示意图,返回,6.3 嵌套与递归子程序,1.子程序嵌套,以下是求N!递归过程的描述。编码见程序6.8。,2.递归子程序,BEGIN FACT(N,RESULT)SAVE REGISTER ON STACKIF N=0RESULT1ELSEPUSH ADDRESS OF RESULT ONTO STACKPUSH N-1 ONTO STACKCALL FACT(N-1,RESULT)RESULTN*RESULTENDIFRESTORE R

18、EGISTERS FROM STACKDELETE PARAMETERS FROM STACK,N!流程图,返回,程序6.8,STACKSG SEGMENT STACK S ;定义堆栈DW 128 DUP(ST) STACKSG ENDS DATA SEGMENT N_VAL DW 3 ;定义N值 RESULT DW ? ;结果 DATA ENDS,CODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACKSG FRAME STRUC ;定义帧结构 SAV_BP DW ? ;保存BP值 SAV_CS_IP DW 2 DUP(?) ;保存返回地址 N DW ? ;当前

19、N值 RESULT_ADDR DW ? ;结果地址 FRAME ENDS,MAIN PROC FARMOV AX,DATAMOV DS,AXLEA BX,RESULTPUSH BX ;结果地址入栈PUSH N_VAL ;N值入栈CALL FAR PTR FACT;调用递归子程序 R1: MOV AX,4C00HINT 21H MAIN ENDP,FACT PROC FAR ;N!递归子程序PUSH BP ;保存BP值MOV BP,SP ;BP指向帧基地址PUSH BXPUSH AXMOV BX,BP.RESULT_ADDRMOV AX,BP.N ;取帧中N值CMP AX,0JE DONE ;N

20、0时退出子程序嵌套PUSH BX;为下一次调用压入结果地址DEC AXPUSH AX;为下一次调用压入(N1)值CALL FAR PTR FACT,R2: MOV BX,BP.RESULT_ADDRMOV AX,BX ;取中间结果(N1)!MUL BP.N ;N*(N1)!JMP SHORT RETURN DONE: MOV AX,1 ;0!1 RETURN: MOV BX,AX ;存中间结果POP AXPOP BXPOP BPRET 4 FACT ENDP CODE ENDSEND MAIN,程序6.8的运行情况:主程序把结果地址和N的初始值压入堆栈,然后调用FACT子程序。在FACT中,它

21、不断调用自身,每调用一次都要在堆栈中形成一帧,该帧由以下信息组成:子程序中要用到的寄存器内容、中间结果地址、(N1)的值、子程序返回地址,自身调用直到N0为止。,当N0时开始返回。通过BP.RESULT_ADDR和BP.N取出堆栈中本次使用的参数,计算N*(N-1)!的值,保存中间结果,恢复寄存器的值,用RET 4返回并废除已用过的N和中间结果地址。重复第步,逐层返回直到N等于初始值为止。,6.4 宏 指 令,在高级汇编语言技术中,一段共用语句序列除了可以设计成子程序外,还可以设计成宏指令的形式。,6.4.1 宏定义、宏调用、宏扩展,宏指令是源程序中一段有独立功能的程序代码。宏指令由宏定义伪指

22、令定义,它只需在源程序中定义一次,便可以多次被调用。,宏指令名 MACRO 形式参数表 ;宏指令体ENDM, 宏定义伪指令格式:,宏调用,宏指令一经定义,就可以在程序中调用它,这被称为宏调用。宏调用格式:宏指令名 实参数表,宏扩展,宏扩展就是用宏定义体替换宏指令名,并用实参数替换形式参数。,例1输入一个字符的宏定义、宏调用、宏扩展,;宏定义 INCHAR MACROMOV AH,1INT 21H ;输入的字符在ALENDM ;宏调用INCHAR 当汇编程序汇编到宏指令INCHAR时,则对其扩展如下:1 MOV AH,11 INT 21H,指令前的“1”表示该语句是扩展时替换得到的。,设计宏指令

23、时应注意的问题,由于宏指令也像子程序那样可以被多次调用或被多个程序共享,所以在设计时需要注意以下问题:1宏指令说明2寄存器的保存与恢复3宏指令中的符号说明,6.4.2 LOCAL伪指令,格式:LOCAL 局部符号表功能:对局部符号表中的每个符号,在汇编时每扩展一次便建立一个惟一的符号,形如?xxxx(xxxx的值在0000FFFF之间)。以保证汇编时生成名字的惟一性。,例2以下是定义一个延时程序的宏指令delay,并且在同一个程序中两次被调用的扩展情况。,;宏定义 DELAY MACROLOCAL LOPMOV CX,2801 LOP: LOOP LOPENDM,宏调用:DELAYDELAY

24、汇编时宏扩展如下:DELAY 0009 B9 0AF1 1 MOV CX,2801 000C E2 FE 1 ?0000: LOOP ?0000 DELAY 000E B9 0AF1 1 MOV CX,2801 0011 E2 FE 1 ?0001: LOOP ?0001,宏指令中参数的使用,在宏定义时可以带有形式参数,而在宏调用时给出实参数即可。宏指令的参数可以是常数、寄存器、变量、表达式、操作码或操作码的一部分、指令或伪指令助记符等。,例3定义在两个字型内存变量之间传送数据的宏指令,并调用它,然后观察其扩展情况。,MOVE MOCRO X,YPUSH AXMOV AX,XMOV Y,AXP

25、OP AXENDM,DATA SEGMENTVAR1 DW 6543HVAR2 DW ?DATA ENDS;宏调用 ;宏扩展MOVE VAR1,VAR2 1 PUSH AX1 MOV AX,VAR11 MOV VAR2,AX1 POP AX,6.4.3 宏指令嵌套,宏指令嵌套有两种情况: 宏定义体中含有宏调用; 宏定义体中含有宏定义。,DMAC MACRO MNAME,OPER ;外层宏定义MNAME MACRO X,Y,Z ;内层宏定义PUSH AXMOV AX,XOPER AX,YMOV Z,AXPOP AXENDMENDM,例4宏定义体中嵌套宏定义的宏指令、宏调用及宏扩展示例。,A DW

26、 25 B DW 12 C DW ?DMAC ADDITION,ADD ;外层宏调用 1 ADDITION MACRO X,Y,Z 1 PUSH AX 1 MOV AX,X 1 ADD AX,Y 1 MOV Z,AX 1 POP AX 1 ENDM,ADDITION A,B,C ;内层宏调用 1 PUSH AX 1 MOV AX,A 1 ADD AX,B 1 MOV C,AX 1 POP AX,DMAC LOGIC_AND,AND ;外层宏调用 1 LOGIC_AND MACRO X,Y,Z 1 PUSH AX 1 MOV AX,X 1 AND AX,Y 1 MOV Z,AX 1 POP AX

27、 1 ENDM,LOGIC_AND A,B,C ;内层宏调用 1 PUSH AX 1 MOV AX,A 1 AND AX,B 1 MOV C,AX 1 POP AX使用适当的实参数,通过调用DMAC宏指令可以生成另一条新的宏指令,再调用新宏指令可以实现任何双操作数指令的操作,而且两个操作数可以同时为存储器操作数。这种方法使得宏的功能更强大。,PURGE伪指令,格式:PURGE 宏指令名,功能:从内存中删除指定的宏指令。例:PURGE INCHAR,6.4.4 宏操作符,这些操作符不仅适用于宏指令,也适用于重复汇编伪指令。宏操作符格式 名称注释 宏注释,1操作符&,在宏定义体中&可以作为形式参数

28、的前缀,而当宏扩展时则把&前后两个符号合并形成一个符号,这个符号可以是操作码、操作数或是一个字符串。例5下面定义的PutData宏指令中,参数TheName作为变量名的一部分,通过&把前后两个符号合并成一个变量名。在Jump宏指令中,参数Cond作为操作码的一部分,通过&把前后两个符号合并成一个指令助记符。, PUTDATA宏指令 PUTDATA MACRO THENAME, THEDATA PD_宏扩展1 PD_MYDATA DB 5, JUMP宏指令JUMP MACRO COND,LJ宏扩展1 JNE LAB1,在宏指令中,当使用宏定义 PUTDATA0 MACRO THENAME,THE

29、DATALOCAL PD_&THENAME PD_&THENAME DB THEDATAENDM,;宏调用PUTDATA0 MYDATA,5 ;宏扩展1 ?0000MYDATA DB 5 ;宏调用PUTDATA0 MYDATA,8 ;宏扩展1 ?0001MYDATA DB 8,返回,由操作符括起的内容作为一个整体原样传递。 例如,可以使用符号包围目标,从而使该目标作为单 一的参数而不是多个参数的列表。例6用不同的实参数调用PUTDATA宏指令,观察它们的变化。PUTDATA MACRO THENAME,THEDATAPD_宏扩展1 PD_MYDATA DB 5,2文本原样传递操作符,;宏调用2

30、PUTDATA MYDATA,;宏扩展1 PD_MYDATA DB 5,4,3,又如以下符号定义语句:Numeric = 10+2Textual equ 其汇编结果是: NUMERIC . . . . . . . .NUMBER 000C TEXTUAL . . . . . . . .TEXT 10+2可以看到,对Numeric已经求值,而Textual只是一串字符而已。,返回,3字符原意操作符!,!操作符指示MASM把后跟的一个字符原样传送,即把它只作为普通字符对待。 例如,若你需要把“! &%”符号中的一个作为宏指令中的字符,可以使用!操作符。,例7以下宏调用的第二个实参数是一串警告信息,

31、其中最后一个字符希望是感叹号“!”。但“!”是宏操作符,要想把“!”当做其原意感叹号对待,就需在它前边加上宏操作符!。,;宏定义 DEBUGMSG MACRO POINT,STRING MSG宏扩展1 MSG6 DB AT POINT 6:INSERTION FAILS!,4表达式操作符,在宏调用时,操作符强迫后跟的表达式立即求值,并把表达式的结果作为实参数替换,而不是表达式本身。例8定义Problem1宏指令,并比较两次调用Problem1宏指令的区别,其中一次调用中使用了操作符。Problem1宏指令功能:把由宏指令参数所指定的字型数组(array)的一个元素装入AX寄存器,该参数经汇编后

32、必须是一个常数表达式。,PROBLEM1 MACRO PARAMETERMOV AX,ARRAYPARAMETER*2ENDM ;宏调用1:希望取出ARRAY12,其中的参数“10+2“是表达式本身PROBLEM1 10+2 ;宏扩展1: 1 MOV AX, ARRAY10+2*2 ;实际取出的是ARRAY7,正确的表达是: ;宏调用2: PROBLEM1 %10+2 ;宏扩展2: 1 MOV AX,ARRAY12*2,注意:由于MASM在调用宏指令时对其中的参数经常是原文替换,所以有时产生的可能不是预期的结果。,考虑以下对PROBLEM1的宏调用及宏扩展: ;宏调用,要求装入ARRAY的元素

33、2PROBLEM1 2 ;宏扩展1 MOV AX,ARRAY2*2可以看到,宏扩展后结果正确。,;宏调用:装入ARRAY的元素10:INDEX = 8PROBLEM1 INDEX+2 ;宏扩展1 MOV AX,ARRAYINDEX+2*2因为MASM的地址表达式遵守操作符优先级的优先规则,则该语句宏扩展后不是预想的结果,它访问的是元素6(索引12),而不是元素10(索引20)。,为了能够得到正确的结果,可以在宏指令的参数表达式中用()把参数括起来: ;宏定义 PROBLEM2 MACRO PARAMETERMOV AX,ARRAY(PARAMETER)*2ENDM ;宏调用INDEX = 8P

34、ROBLEM2 INDEX+2 ;宏扩展1 MOV AX,ARRAY(INDEX+2)*2,5宏注释;,在宏定义中,若注释以一个分号开始,则该注释在宏扩展时出现。但若注释以两个分号开始,则该注释在宏扩展时不出现。举例见列表伪指令。,返回,6.4.5 列表伪指令,格式 功能.LALL 在列表文件中列出全部宏文本内容(以双分号开头的注释除外).SALL 在列表文件中不显示任何宏文本内容.XALL (缺省)在列表文件中只列出可产生目标代码的宏文本内容注意:这些列表伪指令只影响列表文件,并不影响目标码的生成。,6.5 宏指令库,为了使宏指令能让多个程序共享,可以把它们组织到一个文件中,并存放在磁盘上,

35、把这种文件称为宏指令库。 1.建立宏指令库可以把一些常用的宏指令集中在一个文件中形成宏指令库,用EDIT等任何文本编辑程序创建宏指令库,库名由用户自己起,而且对库的扩展名没有特殊要求。库中的宏指令以源代码形式出现。,假设MACRO.LIB中包含以下宏指令(详细内容见教材P174): SETMODE ;设置8025彩色显示模式 INCHAR ;接收一个字符,并返回在AL中 OUTCHAR X ;输出X字符 PUSHREG ;保存寄存器DX、CX、BX、AX、DI、SI、BP POPREG ;恢复寄存器BP、SI、DI、AX、BX、CX、DX,WINDOW MACROCollor,WleftTop

36、Row,WLeftTopCul, WRightBottomRow,WRightBottomCul;功能:开窗口 MOVE MOCRO X,Y ;字型数据X送Y变量 CLRSCRN ;清屏 CURSOR ;置光标,入口参数: DH:DL行,列号 RETURN ;返回操作系统,BIN_DEC MACRO ASC,BIN ;功能:把16位二进制数转换为十进制数的 ;ASCII值,ASC为5个字节的十进制数缓冲区, ;BIN为要转换的二进制数。 DISP MACRO ASC ;显示首址为ASC的字符串,2把宏指令库包含到应用程序中 格式:INCLUDE 源文件名 功能:把另一个源文件包含到当前 源文件

37、中。,3使用宏指令库中的宏指令例9实现32位二进制数除以16位二进制数,并把结果用十进制数形式显示在屏幕上。 编码见程序6.9。,程序6.9,INCLUDE MACRO.LIBPURGE SETMODE,INCHAR,OUTCHAR,WINDOW,MOVE,MUL STACKSG SEGMENT STACK SDW 16 DUP(?) STACKSG ENDS DATA SEGMENT A DD 7006652 ;被除数 B DW 1234 ;除数 C DW ? ;商 PROMPT DB The result is: $ ASCII DB 5 DUP(?),$ ;转换结果 DATA ENDS,

38、CODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACKSG MAIN PROC FARMOV AX,DATAMOV DS,AXMOV DX,WORD PTR A+2MOV AX,WORD PTR ADIV B,BIN_DEC ASCII,AXCLRSCRNDISP PROMPTDISP ASCIIRETURN MAIN ENDP CODE ENDSEND MAIN,4. 宏指令与子程序的区别,采用宏和子程序均能达到代码共享、简化源程序的目的,但它们的区别也是显而易见的。区别主要有以下几点:,(1) 工作方式的区别 (2) 参数传递的方便性 (3) 参数的多样性及

39、灵活性,通常: 宏指令被用在代码较短且参数 较多的场合; 子程序被用在代码较长的场合。,6.6 重复伪指令,当程序中需要重复书写相同或几乎相同的语句时,可以用重复伪指令定义重复块,以简化程序和减轻程序设计人员的工作量。绝大部分MASM版本提供了REPT、IRP和IRPC重复伪指令,而在MASM6.X中还提供了其它重复伪指令。,6.6.1 重复伪指令REPT,格式:REPT 数值表达式 ;重复块ENDM功能:汇编程序使重复块的内容重复多次,重复次数由表达式给出。说明:重复块中可以出现任何有效的汇编语句,数值表达式的计算结果应该是无符号常数。,DATA SEGMENT TABLE LABEL WO

40、RDX=5REPT 6 ;重复6次DW X*X*X ;定义立方值X=X+1ENDM DATA ENDS,汇编后的情况如下: (1) 0000 DATA SEGMENT (2) 0000 TABLE LABEL WORD (3) =0005 X=5 (4) REPT 6 (5) DW X*X*X (6) X=X+1 (7) ENDM,(8)0000 007D 1 DW X*X*X(9)0002 00D8 1 DW X*X*X(10)0004 0157 1 DW X*X*X(11)0006 0200 1 DW X*X*X(12)0008 02D9 1 DW X*X*X(13)000A 03E8 1

41、 DW X*X*X(14)000C DATA ENDS第(8)到第(13)行是汇编后的情况。在代码段中可以通过TABLE名来引用这些值。,MOV BX,10 REPT 2DEC BX ENDM 汇编后产生如下语句:MOV BX,10 1 DEC BX 1 DEC BX,CHARS MACRO NUMMOV AH,2CHAR=AREPT NUMMOV DL,CHARINT 21HCHAR=CHAR+1ENDMENDM,CODE SEGMENTASSUME CS:CODEMAIN PROC FARCHARS 26MOV AX,4C00HINT 21HMAIN ENDPCODE ENDSEND MA

42、IN从本例可以看出,重复伪指令可以出现在宏指令中。,CHARS MACRO NUMMOV AH,2CHAR=A REPT NUMMOV DL,CHARINT 21HCHAR=CHAR+1ENDMENDM,0000 CODE SEGMENTASSUME CS:CODE 0000 MAIN PROC FARCHARS 26 0000 B4 02 1 MOV AH,2 0002 B2 41 2 MOV DL,CHAR ;字符A 0004 CD 21 2 INT 21H 0006 B2 42 2 MOV DL,CHAR ;字符B 0008 CD 21 2 INT 21H,0066 B2 5A 2 MO

43、V DL,CHAR ;字符Z 0068 CD 21 2 INT 21H 006A B8 4C00 MOV AX,4C00H 006D CD 21 INT 21H 006F MAIN ENDP 006F CODE ENDSEND MAIN,6.6.2 不定重复伪指令,1IRP伪指令格式:IRP 形式参数,实参数 ;重复块ENDM功能:汇编程序使重复块的内容重复多次,重复次数由实参数个数决定。每次重复都用尖括号中的一个实参数替代形式参数,依次使用实参数,直到用完为止。,例1实参数可以是符号。IRP REG,PUSH REGENDM汇编后产生以下指令:1 PUSH AX1 PUSH BX1 PUSH

44、 CX1 PUSH DX,IRP X,DB XENDM 汇编后产生的.LST文件: 0000 01 1 DB 1 ;数字 0001 02 1 DB 2 ;数字 0002 08 1 DB 3+5 ;常数表达式 0003 45 44 49 54 1 DB EDIT ;ASCII值从目标码部分可以看出,数字1、2生成01、02,3+5计算后其值为8,EDIT生成相应的ASCII值45、44、49、54。,2IRPC伪指令,格式:IRPC 形式参数,数字串 ;重复块ENDM功能:汇编程序使重复块的内容重复多次,重复次数由数字串中数字位数决定。每次重复都用数字串中一个数字替代形参,依次使用串中的数字,直

45、到用完为止。说明:重复块中可以出现任何有效的汇编语句。,例2定义一串数字。IRPC Z,1235DB ZENDM汇编后生成的.LST文件如下:0001 01 1 DB 10002 02 1 DB 20003 03 1 DB 30004 05 1 DB 5 可以看出,目标代码列生成数字01、02、03、05。注意形参的位置只能是数字串,若为字符串则其中的字符必须是符号,否则汇编出错。,IRPC K,ABCDPUSH K&XENDM 汇编后生成的.LST文件如下: 0000 50 1 PUSH AX 0001 53 1 PUSH BX 0002 51 1 PUSH CX 0003 52 1 PUS

46、H DX,6.7 条件伪指令,一般格式:IFxx 自变量ELSEENDM注意:自变量必须在汇编程序第一遍扫描后成为确定的数值。,后四条伪指令IFxxx和IFxxxI 的区别是:IFxxxI 在比较字符时忽略大小写。,ALL_LT_50 MACRO LENTHVALUE=0IF LNGTH GE 50EXITMENDIFREPT LNGTHVALUE=VALUE+1DB VALUEENDM ENDM这个宏定义仅当LNGTH小于50时才分配表空间。在宏扩展过程中,若汇编程序遇到EXITM,则终止宏扩展,并在ENDM伪指令后重新开始。,.386 PROCESSOR = 80386 IF PROCES

47、SOR EQ 80386SHL AX,4 ELSE MOV CL,4SHL AX,CL ENDIF,汇编生成的列表文件如下:.386 =00013A02 PROCESSOR=80386IF PROCESSOR EQ 80386 0000 66| C1 E0 04 SHL AX,4 ENDIF,DISPLAY MACRO FUNCTION,ADDRESS,CHARMOV AH,FUNCTIONIFB MOV DL,&CHARELSELEA DX,ADDRESSENDIFINT 21H ENDM,CODE SEGMENTMAIN PROC FARASSUME CS:CODE,DS:CODEMOV AX,CODEMOV DS,AXDISPLAY 9,OP3 ;参数2不空,调用21H中断9号功能DISPLAY 2,E ;参数2为空,调用21H中断2号功能MOV AX,4C00HINT 21HOP3 DB ABC$MAIN ENDPCODE ENDSEND MAIN,IDT MACRO OPD ;定义宏 IFIDN ,ADD AX,1 ;1 若则汇编 ENDIF IFIDNI ,ADD AX,2 ;2 忽略大小写时;若则汇编 ENDIF,IFDIF ,ADD AX,3 ;3 若则汇编 ENDIF IFDIFI ,ADD AX,4 ;4 忽略大小写时;若则汇编 ENDIFENDM,

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

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

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


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

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

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