子程序与宏指令设计.ppt
《子程序与宏指令设计.ppt》由会员分享,可在线阅读,更多相关《子程序与宏指令设计.ppt(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 SEGMENTMAINPROC FARCALLSUB1RETMAINENDPSUB1
2、PROCRETSUB1ENDPCODEENDSENDMAIN,2调用程序和子程序在不同段的程序结构(SUB2既被段间调用又被段内调用,必须是FAR属性。CALL要显式说明是FAR属性)CODE1SEGMENTMAINPROC FARCALLFAR PTR SUB2RETMAINENDPCODE1ENDSCODE2SEGMENTSUB1PROCFARCALL FAR PTR SUB2RETSUB1ENDPSUB2PROCFARRETSUB2ENDPCODE2ENDSENDMAIN,6.1.2 设计子程序时应注意的问题1子程序说明2寄存器的保存与恢复3密切注意堆栈状态,6.2 子程序参数传递,可以
3、通过给子程序传递参数使其更通用。常用的参数传递方法如下:通过寄存器传递;若调用程序和子程序在同模块(源程序)中,子程序可以直接访问模块中的变量;通过地址表传递参数地址;通过堆栈传递参数或参数地址。,6.2.1 通过寄存器传递这种传递方式使用方便,适用于参数较少的情况。例1把BX中的16位二进制数转换成十进制并显示在屏幕上。,STASGSEGMENTDW 32 DUP(?)STASG ENDSCODE SEGMENTASSUME CS:CODEMAIN PROC FARMOV BX,162EHCALL TERN MOV AX,4C00H INT 21HMAIN ENDP,程序6.3,TERN P
4、ROC;二十并显示。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;转换个位数RETTERN ENDP,DEC_DIVPROC;CX中为十进制的位权MOV AX,BXMOV DX,0 DIV CX;商为转换后的一位十进制数MOV BX,DXMOV DL,AL ADD DL,30H;转换成ASCII码 MOV AH,2;显示INT 21H RETDEC_DIVENDPC
5、ODE ENDS END MAIN,6.2.2 同模块中的子程序可直接访问模块中的变量 若调用程序和子程序在同模块中,子程序可以直接访问模块中的变量。例2实现数组求和功能。要求数组求和(不考虑溢出情况)由子程序实现,其数组元素及结果均为字型数据。见程序6.4。,STACKSGSEGMENT STACK STKDW 32 DUP(S)STACKSG ENDSDATA SEGMENTARY DW 1,2,3,4,5,6,7,8,9,10COUNT DW($-ARY)/2;数组元素个数SUM DW?;数组和的地址DATA ENDS,程序6.4,CODE1 SEGMENTMAIN PROC FAR A
6、SSUME CS:CODE1,DS:DATA PUSH DS XOR AX,AX PUSH AX MOV AX,DATA MOV DS,AX CALL FAR PTR ARY_SUM RETMAIN ENDPCODE1 ENDS,CODE2 SEGMENT ASSUME CS:CODE2ARY_SUM PROC FAR;数组求和子程序 PUSH AX;保存寄存器 PUSH CX PUSH SI LEA SI,ARY;取数组起始地址 MOV CX,COUNT;取元素个数 XOR AX,AX;清0累加器,NEXT:ADD AX,SI;累加和 ADD SI,TYPE ARY;修改地址指针 LOOP
7、NEXT MOV SUM,AX;存和 POP SI;恢复寄存器 POP CX POP AX RET ARY_SUM ENDPCODE2 ENDS END MAIN,6.2.3 通过地址表传递参数地址适用于参数较多的情况。具体方法是先建立一个地址表,该表由参数地址构成。然后把表的首地址通过寄存器或堆栈传递给子程序。例3编写一个数组求和子程序,其数组元素及结果均为字型数据。另定义两个数组,并编写一个主程序,通过调用数组求和子程序分别求出两个数组的和。见程序6.5。,程序6.5,STACKSG SEGMENT STACK STK DW 32 DUP(S)STACKSG ENDSDATA SEGMEN
8、TARY DW 1,2,3,4,5,6,7,8,9,10;数组1COUNT DW($-ARY)/2;数组1的元素个数SUM DW?;数组1的和地址NUM DW 10,20,30,40,50;数组2CT DW($-NUM)/2;数组2的元素个数TOTAL DW?;数组2的和地址TABLE DW 3 DUP(?);地址表DATA ENDS,CODE1SEGMENTMAINPROC FAR ASSUME CS:CODE1,DS:DATA PUSH DS XOR AX,AX PUSH AX MOV AX,DATA MOV DS,AX;构造数组1的地址表 MOV TABLE,OFFSET ARY MOV
9、 TABLE+2,OFFSET COUNT MOV TABLE+4,OFFSET SUM LEA BX,TABLE;传递地址表首地址 CALL FAR PTR ARY_SUM,;构造数组2的地址表 MOV TABLE,OFFSET NUM MOV TABLE+2,OFFSET CT MOV TABLE+4,OFFSET TOTAL LEA BX,TABLE;传递地址表的首地址 CALL FAR PTR ARY_SUM;段间调用调用数组求和子程序 RETMAIN ENDPCODE1 ENDS,CODE2 SEGMENT ASSUME CS:CODE2ARY_SUM PROC FAR;数组求和子程
10、序 PUSH AX;保存寄存器 PUSH CX PUSH SI PUSH 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 NEXT MOV DI,AX;存和 POP DI;恢复寄存器 POP SI POP CX POP AX RET ARY_SUM ENDPCODE2 ENDS END MAIN,6.2.4 通过堆栈传递参数或参数地址这种方式适用于参数较多,或子程序有多
11、层嵌套、递归调用的情况。步骤:主程序把参数或参数地址压入堆栈;子程序使用堆栈中的参数或通过栈中参数地址取到参数;子程序返回时使用RET n指令调整SP指针,以便删除堆栈中已用过 的参数,保持堆栈平衡,保证程序的正确返回。,例4完成数组求和功能,求和由子程序实现,要求通过堆栈传递参数地址。STACKSG SEGMENT STACK STK DW 16 DUP(?)STACKSG ENDSDATA SEGMENTARY DW 1,2,3,4,5,6,7,8,9,10COUNT DW($-ARY)/2SUM DW?DATA ENDS,程序6.6,CODE1 SEGMENTMAIN PROC FAR
12、ASSUME CS:CODE1,DS:DATA PUSH DS;XOR AX,AX PUSH AX;MOV AX,DATA MOV DS,AX,LEA BX,ARY PUSH BX;压入数组起始地址 LEA BX,COUNT PUSH BX;压入元素个数地址 LEA BX,SUM PUSH BX;压入和地址 CALL FAR PTR ARY_SUM;调用求和子程序 RET;MAIN ENDPCODE1 ENDS,CODE2 SEGMENT ASSUME CS:CODE2ARY_SUM PROC FAR;数组求和子程序 PUSH BP;保存BP值 MOV BP,SP;BP是堆栈数据的地址指针 P
13、USH 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 NEXT MOV DI,AX;存和 POP DI;恢复寄存器内容 POP SI;POP CX;POP AX;POP BP;RET 6;返回并调整SP指针ARY_SUM ENDPCODE2 ENDS END MAIN,返回,程序6.6中所有入栈操作对堆栈的
14、影响,返回,程序6.6中主程序的RET执行前堆栈状态,例5完成数组求和功能,其中求和由子程序实现,要求使用结构访问堆栈中的参数。编码见程序6.7。,返回,SS,SP,BP,程序6.7的堆栈及结构数据示意图,结构,程序6.7,STACKSG SEGMENT STACK STK DW 16 DUP(S)STACKSG ENDSDATA SEGMENTARY DW 1,2,3,4,5,6,7,8,9,10COUNT DW($-ARY)/2SUM DW?DATA ENDS,CODE1 SEGMENTMAIN PROC FAR ASSUME CS:CODE1,DS:DATA PUSH DS XOR AX
15、,AX PUSH AX MOV AX,DATA MOV DS,AX,LEA BX,ARY PUSH BX;压入数组起始地址 LEA BX,COUNT PUSH BX;压入元素个数地址 LEA BX,SUM PUSH BX;压入和地址 CALL FAR PTR ARY_SUMRETMAIN ENDPCODE1 ENDS,CODE2 SEGMENT ASSUME CS:CODE2STACK_STRC STRUC;定义结构SAVE_BP DW?SAVE_CS_IP DW 2 DUP(?)SUM_ADDR DW?COUNT_ADDR DW?ARY_ADDR DW?STACK_STRC ENDS,ARY
16、_SUMPROC FAR;数组求和子程序 PUSH BP;保存BP值 MOV BP,SPPUSH AX PUSH CX PUSH SI PUSH DI MOV SI,BP.ARY_ADDR;数组始地址 MOV DI,BP.COUNT_ADDR MOV CX,DI MOV DI,BP.SUM_ADDR;得到和地址 XOR AX,AX,NEXT:ADD AX,SI;累加 ADD SI,TYPE ARY;修改地址指针 LOOP NEXT MOV DI,AX;存和 POP DI POP SI POP CX POP AX POP BP RET 6;返回并调整SP指针ARY_SUM ENDPCODE2 E
17、NDS END MAIN,子程序嵌套示意图,返回,6.3 嵌套与递归子程序,1.子程序嵌套,以下是求N!递归过程的描述。编码见程序6.8。,2.递归子程序,BEGINFACT(N,RESULT)SAVEREGISTER ON STACKIF N=0RESULT1ELSEPUSH ADDRESS OF RESULT ONTO STACKPUSH N-1 ONTO STACKCALL FACT(N-1,RESULT)RESULTN*RESULTENDIFRESTORE REGISTERS FROM STACKDELETE PARAMETERS FROM STACK,N!流程图,返回,程序6.8,S
18、TACKSG SEGMENTSTACK S;定义堆栈DW 128 DUP(ST)STACKSG ENDSDATA SEGMENTN_VAL DW3;定义N值RESULT DW?;结果DATA ENDS,CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKSGFRAMESTRUC;定义帧结构SAV_BPDW?;保存BP值SAV_CS_IPDW 2 DUP(?);保存返回地址NDW?;当前N值RESULT_ADDRDW?;结果地址FRAMEENDS,MAIN PROCFAR MOVAX,DATA MOVDS,AX LEABX,RESULT PUSHBX;结果地址
19、入栈 PUSHN_VAL;N值入栈 CALLFARPTRFACT;调用递归子程序R1:MOVAX,4C00H INT21HMAIN ENDP,FACTPROC FAR;N!递归子程序 PUSH BP;保存BP值 MOV BP,SP;BP指向帧基地址 PUSH BX PUSH AX MOV BX,BP.RESULT_ADDRMOV AX,BP.N;取帧中N值 CMP AX,0 JE DONE;N0时退出子程序嵌套 PUSH BX;为下一次调用压入结果地址 DEC AX PUSH AX;为下一次调用压入(N1)值 CALL FAR PTR FACT,R2:MOVBX,BP.RESULT_ADDR
20、MOVAX,BX;取中间结果(N1)!MULBP.N;N*(N1)!JMPSHORT RETURNDONE:MOVAX,1;0!1RETURN:MOVBX,AX;存中间结果 POP AX POP BX POP BP RET 4FACT ENDPCODE ENDS END MAIN,程序6.8的运行情况:主程序把结果地址和N的初始值压入堆栈,然后调用FACT子程序。在FACT中,它不断调用自身,每调用一次都要在堆栈中形成一帧,该帧由以下信息组成:子程序中要用到的寄存器内容、中间结果地址、(N1)的值、子程序返回地址,自身调用直到N0为止。,当N0时开始返回。通过BP.RESULT_ADDR和BP
21、.N取出堆栈中本次使用的参数,计算N*(N-1)!的值,保存中间结果,恢复寄存器的值,用RET 4返回并废除已用过的N和中间结果地址。重复第步,逐层返回直到N等于初始值为止。,6.4 宏 指 令,在高级汇编语言技术中,一段共用语句序列除了可以设计成子程序外,还可以设计成宏指令的形式。,6.4.1 宏定义、宏调用、宏扩展,宏指令是源程序中一段有独立功能的程序代码。宏指令由宏定义伪指令定义,它只需在源程序中定义一次,便可以多次被调用。,宏指令名 MACRO 形式参数表;宏指令体ENDM,宏定义伪指令格式:,宏调用,宏指令一经定义,就可以在程序中调用它,这被称为宏调用。宏调用格式:宏指令名 实参数表
22、,宏扩展,宏扩展就是用宏定义体替换宏指令名,并用实参数替换形式参数。,例1输入一个字符的宏定义、宏调用、宏扩展,;宏定义INCHARMACROMOVAH,1 INT21H;输入的字符在ALENDM;宏调用 INCHAR当汇编程序汇编到宏指令INCHAR时,则对其扩展如下:1 MOV AH,11 INT 21H,指令前的“1”表示该语句是扩展时替换得到的。,设计宏指令时应注意的问题,由于宏指令也像子程序那样可以被多次调用或被多个程序共享,所以在设计时需要注意以下问题:1宏指令说明 2寄存器的保存与恢复 3宏指令中的符号说明,6.4.2 LOCAL伪指令,格式:LOCAL 局部符号表功能:对局部符
23、号表中的每个符号,在汇编时每扩展一次便建立一个惟一的符号,形如?xxxx(xxxx的值在0000FFFF之间)。以保证汇编时生成名字的惟一性。,例2以下是定义一个延时程序的宏指令delay,并且在同一个程序中两次被调用的扩展情况。,;宏定义DELAYMACROLOCALLOPMOVCX,2801LOP:LOOPLOPENDM,宏调用:DELAYDELAY汇编时宏扩展如下:DELAY0009 B9 0AF11 MOV CX,2801 000C E2 FE1?0000:LOOP?0000 DELAY000E B9 0AF11 MOV CX,2801 0011 E2 FE1?0001:LOOP?00
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 子程序 指令 设计
链接地址:https://www.31ppt.com/p-6564271.html