收藏 分销(赏)

ch10-子程序设计.doc

上传人:xrp****65 文档编号:7686781 上传时间:2025-01-12 格式:DOC 页数:17 大小:138KB 下载积分:10 金币
下载 相关 举报
ch10-子程序设计.doc_第1页
第1页 / 共17页
ch10-子程序设计.doc_第2页
第2页 / 共17页


点击查看更多>>
资源描述
第6章 子程序设计 为什么用子程序? UML中的设计模式? 6.1. 子程序结构 主程序与子程序间的关系 6.1.1 子程序的定义 过程名 PROC 属性 . . . RET/RETF [过程名] ENDP 属性: NEAR, FAR 1.主程序与子程序在同一代码段内 例 6.1.1 CODE SEGMENT MAIN PROC FAR … CALL SUB1 … RET MAIN ENDP SUB1 PROC NEAR … CALL SUB2 … RET SUB1 ENDP SUB2 PROC NEAR … RET SUB2 ENDP … CODE ENDS END MAIN 2.主程序与子程序不在同一个代码段 例6.1.2 CODE1 SEGMENT MAIN1 PROC FAR … … CALL SUB3 … MAIN1 ENDP SUB3 PROC FAR … RET SUB3 ENDP CODE1 ENDS CODE2 SEGMENT MAIN2 PROC FAR … CALL SUB3 … MAIN2 ENDP CODE2 ENDS END MAIN1 6.1.2 子程序的调用和返回 CALL RET 对堆栈的使用。 CALL RETF 6.1.3 现场的保存与恢复 为什么要保存现场与恢复现场? 1. 利用栈指令进行现场的保存与恢复 例6.1.3 SUB4 PROC NEAR PUSH AX PUSH BX PUSH CX …子程序体 POP CX POP BX POP AX RET SUB4 ENDP **注意保存与恢复的顺序. 2. 利用数据传送指令进行现场的保存与恢复 DATA SEGMENT BUFFER DW 4 DUP(?) DATA ENDS SUB5 PROC NEAR LEA DI, BUFFER MOV [DI], AX MOV [DI+2], BX MOV [DI+4], CX Mov [DI+6], DX …子程序体 LEA DI, BUFFER MOV AX, [DI] MOV BX, [DI+2] MOV CX, [DI+4] MOV DX, [DI+6] RET SUB5 ENDP **现场保存在子程序的数据空间. **有什么问题? DI? 3. 利用PUSHA和POPA进行现场的保存与恢复(286以上) SUB6 PROC NEAR PUSHA …子程序体 POPA RET SUB6 ENDP 4. 利用PUSHAD和POPAD指令进行现场的保存与恢复(386以上) SUB7 PROC NEAR PUSHAD …子程序体 POPAD RET SUB7 ENDP **保存的原则:子程序使用的寄存器,这些寄存器要保存与恢复. 6.1.4 子程序的参数传送 传送参数方法: 通过通用寄存器(RC); 通过存储单元; 通过堆栈 1.通过通用寄存器传送参数 例6.1.7 用寄存器传送参数方式, 编制5位10进制加法程序。 要求(1)SUB8子程序把键入5位以内的10进制数转(<65536)换成2进制数年存入CX,键入非数字键返主程序。 (2)SUB9子程序完成把CX中的2进制数转换成10进制数显示在CRT上. (3)在主程序MAIN中求和,两数之和小于等于65535. (4)MAIN,SUB8,SUB9在同一代码段中. CODE SEGMENT ASSUME CS:CODE //主程序 MAIN PROC FAR CALL SUB8 ;取被加数 MOV BX,CX CALL SUB8 ;取加数 ADD CX, BX ;求和 CALL SUB9 ;显示 MOV AH, 4CH INT 21H //子程序把键入5位以内的10进制数转(<65536)换成2进制数年存入CX,键入非数字键返主程序。 SUB8 PROC NEAR PUSH AX PUSH BX PUSH DX XOR CX,CX ; mov cx, 0 CX中保存结果 AA2: MOV AH, 1 INT 21H //界限0~9 CMP AL, 30H JC AA1 CMP AL, 3AH JNC AA1 //x10 ADD CX, CX MOV BX, CX ADD CX, CX ADD CX, CX ADD CX, BX AND AX, 0FH ADD CX, AX ;键入的值加到CX中。 JMP AA2 AA1: POP DX POP BX POP AX RET SUB8 ENDP //把CX中的2进制数转换成10进制数显示在CRT上 SUB9 PROC NEAR PUSH AX PUSH BX PUSH DX //最高位不显示0 CMP CX,10000 JNC AA12 ;JAE AA12 大于等于1000时显示万位 CMP CX, 1000 JNC AA4 CMP CX, 100 JNC AA6 CMP CX, 10 JNC AA8 JMP AA10 //万位计数,并显示 MOV DL, 0 AA3: CMP CX, 10000 JC DISP1 INC DL SUB CX, 1000 JMP AA3 DISP1: OR DL, 30H MOV AH, 2 INT 21H AA12: MOV DL, -1 AA3: SUB CX, 10000 INC DL JNC AA3 ADD CX, 10000 OR DL, 30H MOV AH, 2 INT 21H //千位计数,并显示 AA4: MOV DL, -1 AA5: SUB CX, 1000 INC DL JNC AA5 ADD CX, 1000 OR DL, 30H MOV AH, 2 INT 21H //百位计数,并显示 AA6: MOV DL, -1 AA7: SUB CX, 100 INC DL JNC AA7 ADD CX, 100 OR DL, 30H MOV AH, 2 INT 21H //十位计数,并显示 AA8: MOV DL, -1 AA9: SUB CX, 10 INC DL JNC AA9 ADD CX, 10 OR DL, 30H MOV AH, 2 INT 21H //个位计数, 并显示 AA10: MOV DL, CL OR DL, 30H MOV AH, 2 INT 21H POP DX POP BX POP AX RET SUB9 ENDP MAIN ENDP CODE ENDS END MAIN **以上的程序子程序中用到AX,BX,CX,DX. 其中CX用于传送参数及结果,而AX,BX,DX用于中间运算, 内部使用,为了不修改主程序中的AX,BX,DX,要保存现场. 2.通过存储单元传送参数 利用存储单元存放调用子程序的输入参数, 子程序把运算结果(输出参数)也用存储单元保存. 例6.1.8 用存储单元传送参数方式,编写求无符号多字节2进制数的和,然后以16进制数形式显示在CRT上. 要求: NUMBER1放8个字节的数. NUMBER2放8个字节的数. NUMBER3放求和结果,8个字节单元 SUB10 求和子子程序 SUB11 显示子程序. DATA SEGMENT NUMBER1 DB 99, 22, 33, 44, 99, 77, 88, 11 NUMBER2 DB 99, 88, 77, 66, 55, 44, 33, 22 NUMBER3 DB 8 DUB(?) DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS: DATA //主程序 MAIN PROC FAR MOV AX, DATA MOV DS, AX CALL SUB10 LEA BX, NUMBER3+7 CALL SUB 11 MOV AH, 4CH INT 21H //8字节求和子程序 SUB10 PROC NEAR PUSH AX PUSH CX PUSH BX PUSH SI PUSH DI LEA SI, NUMBER1 LEA DI, NUMBER2 LEA BX, NUMBER3 MOV CX, 8 AND AL, AL ; CLC Cß0 AA1: MOV AL,[SI] ADC AL,[DI] MOV [BX], AL INC SI INC DI INC BX LOOP AA1 POP DI POP SI POP BX POP CX POP AX RET SUB10 ENDP //显示子程序 SUB11 PROC NEAR PUSH DX PUSH CX PUSH AX MOV DH, 8 ; 循环次数 //一个字节的高4位显示 AA4: MOV DL,[BX] ; 从高位NUMBER3+7开始计数 MOV CL, 4 SHR DL, CL ;高4位 OR DL, 30H ; 30H~3FH CMP DL, 3AH JC AA2 ; jb AA2 ADD DL, 7 ; 3AH+7 = 41H AA2: MOV AH, 2 INT 21H //一个字节的低4位显示 MOV DL, [BX] AND DL, 0FH OR DL, 30H CMP DL, 3AH JC AA3 ADD DL, 7 AA3: MOV AH, 2 INT 21H DEC BX DEC DH JNZ AA4 ;循环8次 MOV DL, ‘H’ MOV AH, 2 INT 21H POP AX POP CX POP DX SUB11 ENDP MAIN ENDP CODE ENDS END MAIN 3.通过堆栈传送参数或参数表地址 例 6.1.9用堆栈传送参数和参数表地址方式,编制键入8位的非压缩BCD码加法并显示的源程序。 要求: NUMBER1~NUMBER1+7存放键入的被加数(非压缩BCD码); NUMBER2~NUMBER2+7存放键入的加数(非压缩BCD码); NUMBER3~NUMBER3+8存放和(非压缩BCD码); SUB12接收8位非压缩BCD码,接收被加数、加数(输出:接收结果存入堆栈中) SUB13显示9位非压缩BCD码,显示和(输入:参数地址表在堆栈中) DATA SEGMENT NUMBER1 DB 8 DUB(0) ;被加数 NUMBER2 DB 8 DUB(0) ;加数 NUMBER3 DB 9 DUB(0) ;和 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA MAIN PROC FAR MOV AX, DATA MOV DS, AX //1.取被加数 CALL SUB12 POP CX LEA BX, NUMBER1 AA3: POP AX MOV [BX], AL INC BX LOOP AA3 //2.取加数 CALL SUB12 POP CX LEA BX, NUMBER2 AA4: POP AX MOV [BX], AL INC BX LOOP AA3 //3.计算和 LEA SI, NUMBER1 LEA DI, NUMBER2 LEA BX, NUMBER3 MOV CX, 8 ; 计数次数 OR CX, CX ; CLC AA5: MOV AL, [SI] ADC AL, [DI] AAA MOV [BX], AL INC SI INC DI INC BX LOOP AA5 ADC CL, AH MOV [BX], CL //4.显示和 LEA AX, NUMBER3+8 PUSH AX CALL SUB13 //5.清被加数与加数单元为0 MOV CX, 16 LEA BX, NUMBER1 XOR AL, AL ;MOV AL, 0 QQQ2: MOV [BX], AL INC BX LOOP QQQ2 //6.退出 MOV AH, 4CH INT 21H //7. 接收8位非压缩BCD码子程序, 接收被加数、加数(输出:接收结果存入堆栈中) SUB12 PROC NEAR POP BX ;保存子程序返回地址 SUB CX, CX ; MOV CX, 0 AA1: MOV AH, 1 个数(N) 数据N 数据N-1 … 数据4 数据3 数据2 数据1 INT 21H CMP AL, 30H JC AA2 CMP AL, 3AH JNC AA2 INC CX ;个数加1 PUSH AX ;键入的数压入栈 JMP AA1 AA2: PUSH CX ; 键入数字的个数 PUSH BX; 子程序返回地址入栈 RET SUB12 ENDP //8. 显示9位非压缩BCD码子程序, 显示和(输入:参数地址表在堆栈中) SUB13 PROC NEAR POP AX ;子程序返回地址出栈 POP BX ;参数表地址出栈 PUSH AX ;子程序返回地址入栈 MOV CX, 9 ;和数是9位,循环计数次数 AA6: MOV DL, [BX] ADD DL, 30H ;OR DL, 30H MOV AH, 2 INT 21H DEC BX LOOP AA6 RET SUB13 ENDP MAIN ENDP CODE ENDS END MAIN 6.2. 嵌套与递归子程序 6.2.1 子程序的嵌套 例6.2.1 试编写在ARRAY1无符号数组中,选出最大值及其所在的位置,然后以16进制数显示在CRT上显示的程序. 要求: SUB14找出最大值及其位置子程序; 输入:个数(CX),首地址(SI) 输出:最大值(CX),位置(SI) SUB15 显示子程序 输入:BX ; 例20FF SUB16 十六进制显示子程序 输入:DL ;0~F之间的数 DATA SEGMENT ARRAY1 DW 100 DUB(?) COUNT EQU ($-ARRAY1)/2 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA MAIN PROC FAR MOV AX, DATA MOV DS, AX //1.在数组中找最大值及位置 LEA SI, ARRAY1 MOV CX, COUNT CALL SUB14 ; 找到最大数在CX中,位置在SI中 MOV DI, CX ; 保存找到的最大值在DI中 //2.显示段地址 MOV BX, DATA CALL SUB15 //3.显示’:’字符 MOV DL, ‘:’ MOV AH, 2 INT 21H //4.显示偏移地址 MOV BX, SI CALL SUB15 //5.显示空格 MOV DL, 20H MOV AH, 2 INT 21H //6.显示最大值 MOV BX, DI CALL SUB15 //7.退出 MOV AH, 4CH INT 21H //找出最大值及其位置子程序; 输入:个数(CX),首地址(SI) 输出:最大值(CX),位置(SI) SUB14 PROC NEAR PUSH AX PUSH DI MOV DI, SI ;DI中保存最大值的地址 MOV AX, [SI] ;从ARRAY1数组中取第一个数 AA1: CMP AX, [SI] JNC AA2 ; JAE AA2 MOV AX, [SI] ;AX中保存最大值 MOV DI, SI ;DI中保存最大值地址 AA2: ADD SI, 2 LOOP AA1 ;子程序输入参数CX中有个数 MOV SI, DI ;最大值地址值 MOV CX, AX ;最大值 POP DI POP AX ret SUB14 ENDP //显示子程序. 输入:BX ; 例20FF SUB15 PROC NEAR //显示BH中高4位 MOV DL, BH MOV CL, 4 SHR DL, CL CALL SUB16 //显示BH中低4位 MOV DL, BH AND DL, 0FH CALL SUB16 //显示BL中高4位 MOV DL, BL MOV CL, 4 SHR DL, CL CALL SUB16 //显示BL中低4位 MOV DL, BL AND DL, 0FH CALL SUB16 RET SUB15 ENDP //十六进制显示子程序. 输入:DL ;0~F之间的数. SUB16 PROC NEAR OR DL, 30H CMP DL, 3AH JC AA3 ;JB AA3 ADD DL, 7 ;41H~46H, 3AH+7=41H AA3: MOV AH, 2 INT 21H RET SUB16 ENDP MAIN ENDP CODE ENDS END MAIN 6.2.2 递归子程序 子程序递归调用: 子程序调用自身子程序. 例6.2.2 试编写计算N!的递归子程序 1. 用缓冲区存放N、N-1、…、2、1,然后再依次取出作1x2x3x…xN运算的方式。 FACT1递归子程序 输入:个数(AL), 缓冲区首地址(SI) 输出: 计数结果(AX) DATA SEGMENT BUFF1 DB 3 DUP(?) NN1 DB 3 RESULT1 DW 0 DATA ENDS SET1 SEGMENT ‘STACK’ DW 100 DUP(?) SET1 ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA, SS:SEG1 START:MOV AX, DATA MOV DS, AX MOV AL, NN1 LEA SI, BUFF1 CALL FACT1 ;调用递归子程序 AA2: MOV RESULT1, AX ;保存结果 MOV AH, 4CH INT 21H ;递归子程序. ;输入:个数(AL), 缓冲区首地址(SI) ;输出: 计数结果(AX) FACT1 PROC NEAR CMP AL, 0 JNZ AA1 ;递归中止条件 MOV AL, 1 AA4: RET ;转到AA3 AA1: MOV [SI],AL ; 存放N、N-1、…、2、1 DEC AL INC SI CALL FACT1 ;调用自身,每调用一次会把AA3压入栈 AA3: DEC SI MOV BL, [SI] MUL BL ;AXß al*bl AA5 : RET ;转到AA3、转到AA3、。。。、转到AA2 FACT1 ENDP CODE ENDS END START 2. 2.用堆栈依次压入N、N-1、…、2、1,然后再依次取出作1x2x3x…xN运算的方式。 FACT1递归子程序 输入:个数(AX) 输出: 计数结果(AX) DATA SEGMENT N DW 3 RESULT1 DW 0 DATA ENDS SET1 SEGMENT ‘STACK’ DW 100 DUP(?) SET1 ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA, SS:SEG1 START:MOV AX, DATA MOV DS, AX MOV AX, N CALL FACT1 ;调用递归子程序,求N! AA2: MOV RESULT1, AX ;保存结果 MOV AH, 4CH INT 21H ;递归子程序. ;输入:个数(AX) ;输出: 计数结果(AX) FACT1 PROC NEAR CMP AX, 0 JNZ AA1 ;递归中止条件 MOV AX, 1 AA4: RET ;转到AA3 AA1: PUSH AX ; N、N-1、…、2、1依次入栈 DEC AX CALL FACT1 ;调用自身,每调用一次会把AA3压入栈 AA3: POP BX MUL BL ; axßal*bl AA5 : RET ;转到AA3、转到AA3、。。。、转到AA2 FACT1 ENDP CODE ENDS END START 作业:P223 6.1, 6.2, 6.3
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 教育专区 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服