1 / 69

第六章 子程序设计

第六章 子程序设计. 一、子程序的定义 二、子程序的结构形式 三、子程序的设计和调用 四、子程序的参数传递方法 五、子程序的嵌套和递归调用 六、子程序的设计举例 七、多模块程序设计 八、汇编语言和高级语言的混合编程. 一、子程序的定义. 1、子程序的概念和特点 2、子程序的定义 3、子程序的调用和返回. 1、子程序的概念和特点. 子程序: 把在程序中多次出现,具有独立功能的程序段写成程序模块,该模块可被多次调用,称之为子程序。. 特点: ①可重复使用(调用) ②具有通用性(可通过入口参数实现)

kaia
Download Presentation

第六章 子程序设计

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第六章 子程序设计 一、子程序的定义 二、子程序的结构形式 三、子程序的设计和调用 四、子程序的参数传递方法 五、子程序的嵌套和递归调用 六、子程序的设计举例 七、多模块程序设计 八、汇编语言和高级语言的混合编程

  2. 一、子程序的定义 1、子程序的概念和特点 2、子程序的定义 3、子程序的调用和返回

  3. 1、子程序的概念和特点 子程序:把在程序中多次出现,具有独立功能的程序段写成程序模块,该模块可被多次调用,称之为子程序。 特点:①可重复使用(调用) ②具有通用性(可通过入口参数实现) ③可浮动性(存放位置灵活) ④可递归性和可重入性

  4. 2、子程序的定义 子程序的定义是由过程定义伪指令PROC和ENDP来完成的。其格式如下: 过程名PROC [NEAR/FAR] ┆ 过程名ENDP 其中PROC表示过程定义开始,ENDP表示过程定义结束。过程名是过程入口地址的符号表示。 一般过程名同标号一样,具有三种属性,即段属性、偏移地址属性以及类型属性。

  5. 3、子程序的调用和返回 • 调用 ①段内直接调用 格式:CALL 子程序名 功能:将子程序返回地址(断点)入栈 SP←SP-2 (SP)←IP, 并转到子程序入口地址去执行子程序。 IP←IP+(子程序入口地址与CALL之间的偏移量)

  6. 例:段内直接调用,显示字符P CODE SEGMENT ASSUME CS:CODE START:CALL DISP MOV AH,4CH INT 21H DISP PROC MOV DL,’P’ MOV AH,2 INT 21H RET DISP ENDP CODE ENDS END START

  7. ②段内间接调用 格式:CALL DST 或 CALL WORD PTR DST (DST为寄存器或字存储器) 功能:断点入栈,转子程序执行。 SP←SP-2 (SP)←IP IP←(EA) 例: CALL BX CALL WORD PTR [SI]

  8. ③段间直接调用 格式:CALL FAR PTR DST(DST为子程序名) 功能:段点(CS和IP)入栈,并转到子程序处执行。 SP←SP-2 (SP)←CS SP←SP-2 (SP)←IP IP←子程序入口地址的偏移地址 CS←子程序入口地址的段地址

  9. 例: 段内间接调用,显示一个字符P CODE1 SEGMENT ASSUME CS:CODE1 START:CALL DISP MOV AH,4CH INT 21H CODE1 ENDS CODE2 SEGMENT ASSUME CS:CODE2 DISP PROC FAR MOV DL,’P’ MOV AH,2 INT 21H RET DISP ENDP CODE2 ENDS END START

  10. ④段间间接调用 例:CALL DWORD PTR [BX] CALL DWORD PTR ADDR • 返回指令 • 格式:RET • 功能:返回堆栈中存放的断点,并返回到CALL指令的后续指令继续执行。

  11. 二、子程序的结构形式 • 子程序设计考虑四部分: • 保护现场(保存寄存器原有的内容)、处理部分、恢复现场(恢复寄存器原有的内容)、子程序的返回。 “现场”:子程序执行中要用到的寄存器。 保护现场:一般通过压栈实现(进入子程序前) 恢复现场:一般通过出栈实现(返回子程序前)

  12. 1、子程序的调用方法说明 (1)子程序名:供调用时使用 (2)入口参数:子程序执行需要的数据 (3)出口参数(输出参数):说明子程序执行后结果存放在何处。 (4)占用寄存器:说明子程序执行时需要使用那些寄存器。那些改变,那些不变。 注意:作为存放出口参数用的寄存器不能保护。

  13. 2.信息的保护与恢复 例如:若子程序PROG中改变了寄存器AX,BX,CX,DX的值,则可采用如下方法保护和恢复现场。 PROG PROC PUSH AX PUSH BX PUSH CX ;保护现场 PUSH DX ┆

  14. POP DX POP CX POP BX ;恢复现场 POP AX RET ;返回断点处 PROC ENDP

  15. 三、子程序的设计和调用举例 例6-2 多字节二进制数加法子程序 ;子程序名:MBTADD ;功能:两个多字节二进制相加 ;入口参数:SI,DI分别存放两个数的首地址,BX存放和的首地址,CX存放多字节数的长度。 ;出口参数:BX存放和的首地址

  16. MBTADD PROC PUSH SI PUSH DI PUSH BX PUSH AX PUSH CX CLC ;CF=0 保护现场

  17. NEXT:MOV AL,[SI] ADC AL,[DI] MOV [BX],AL INC SI INC DI INC BX LOOP NEXT POP CX POP AX POP BX POP DI POP SI RET MBTADD ENDP 返回现场

  18. 例:求最大公约数子程序。 入口参数:AX,BX 出口参数:CX MCDST PROC PUSH AX PUSH BX PUSH DX AGAIN:XOR DX,DX DIV BX AND DX,DX JZ EXIT MOV AX,BX MOV BX,DX JMP AGAIN EXIT: MOV CX,BX POP DX POP BX POP AX RET MCDST ENDP

  19. 例6-3:将在BUFFER为首地址的缓冲区的一个字符串中的所有大写字母都转换成小写字母,并在屏幕显示出来。例6-3:将在BUFFER为首地址的缓冲区的一个字符串中的所有大写字母都转换成小写字母,并在屏幕显示出来。 程序清单如下: DATA SEGMENT ORG 200H STRING DB ‘ABsDFAIViop’STRLEN EQU $-STRING ;字符串长度 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA ;设置数据段 MOV DS,AX

  20. MOV SI,OFFSET STRING;取串首地址赋给SI MOV CX,STRLEN ;串长送CX CALL STRDTX;调用子程序 MOV DX,OFFSET STRING;打印转换后的字符串 MOV AH,9 INT 21H MOV AH,4CH INT 21H

  21. JA NEXT1 ADD AL,20H MOV [SI],AL NEXT1:INC SI JMP NEXT EXIT: POP SI POP CX POP AX RET STRDTX ENDP CODE ENDS END START ;大小写转换子程序 STRDTX PROC NEAR PUSH AX PUSH CX PUSH SI NEXT:MOV AL,[SI] CMP CX,0 JZ EXIT CMP AL,‘A’ JB NEXT1 CMP AL,‘Z’

  22. 四、主程序与子程序参数传递方式 • 通过寄存器传递参数 • 通过堆栈传递参数 • 通过存储单元传递参数

  23. 1、通过寄存器传递参数 主程序将原始参数放入约定的寄存器,然后调用子程序;子程序把处理结果放入约定的寄存器,并返回主程序。 例6-5数据块传送子程序 分析: 入口参数:源操作块首地址、目的块首地址和块长度。分别用SI、DI和CX来传递参数。

  24. DATA SEGMENT BLOCK1 DB 23H,45H,13H,2FH,1AH,94H LENS EQU $-BLOCK1 BLOCK2 DB LENS DUP(?) DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START:MOV AX,DATA MOV DS, AX

  25. MOV SI,OFFSET BLOCK1 MOV DI,OFFSET BLOCK2 MOV CX, LENS CALL MOVSTOK MOV AH,4CH INT 21H MOVSTOK PROC NEAR PUSH AX NEXT: MOV AL,[SI] MOV [DI],AL INC SI INC DI LOOP NEXT POP AX RET MOVSTOK ENDP CODE ENDS END START

  26. 例: 在ADRM和ADRN单元中分别存放两个正整数M、N,求最大公约数,并将结果存入RESULT单元中。 入口参数:AX,BX 出口参数:CX 算法: (1)判断如M>N,转(2),否则交换M、N (2)M/N得到余数R (3)判断若R=0,则N为最大公约数,否则 (4)更新被除数和除数,M←N,N←R,转(2)执行。

  27. 2、通过堆栈传递参数 主程序的入口参数用堆栈保存,不占用存储单元,在子程序中弹出入口参数,执行完子程序后,释放堆栈空间。 例6-5用堆栈传递参数,实现数据块传送。 入口参数:源数据块首地址,目的数据块首地址及数据块长度。均用寄存器AX把3个参数压栈。

  28. DATA SEGMENT BLOCK1 DB 23H,45H,13H,2FH,1AH,94H LENS EQU $-SOUCE BLOCK2 DB LENS DUP(?) DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX

  29. MOV AX,OFFSET BLOCK1 PUSH AX MOV AX, OFFSET BLOCK2 PUSH AX MOV AX, LENS PUSH AX CALL MOVSTOK MOV AH,4CH INT 21H

  30. MOVSTOK PROC NEAR PUSH SI PUSH DI PUSH CX PUSH BP MOV BP,SP MOV SI,[BP+14] MOV DI,[BP+12] MOV CX,[BP+10] LOP1:MOV AL,[SI] MOV [DI],AL INC SI INC DI LOOP LOP1 RET MOVSTOK ENDP CODE ENDS END START

  31. 例:利用堆栈传递参数,实现对2个已定义数组分别求和。主程序与子程序不在同一代码段中。例:利用堆栈传递参数,实现对2个已定义数组分别求和。主程序与子程序不在同一代码段中。 入口参数:数组的首地址和数组长度。使用寄存器AX将入口参数压栈。

  32. DATA SEGMENT ARYA DB 06H,33H,0AH,88H,13H SUMA DW ? ARYB DB 9FH,97H,34H,22H,33,13H SUMB DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX

  33. MOV AX,SUMA-ARYA PUSH AX MOV AX,OFFSET ARYA PUSH AX CALL SUM MOV AX,SUMB-ARYB PUSH AX MOV AX,OFFSET ARYB PUSH AX CALL SUM MOV AH,4CH INT 21H CODE ENDS

  34. PROCE SEGMENT ASSUME CS:PROCE,DS:DATA SUM PROC FAR PUSH AX PUSH BX PUSH CX PUSH BP MOV BP,SP PUSHF MOV CX,[BP+14] MOV BX,[BP+12]

  35. MOV AX,0 LOP1:ADD AL,[BX] ADC AH,0 INC BX LOOP LOP1 MOV [BX],AX POPF POP BP POP CX POP BX POP AX RET 4 SUM ENDP PROCE ENDS END START

  36. 3、用存储单元传递参数 主程序中入口参数送入存储单元,子程序中取出入口参数进行处理,执行结果存入存储单元。 例6.7 同例6.5 用存储器参数传递法编写程序

  37. DATA SEGMENT BLOCK1 DB 23H,45H,13H,2FH,1AH,94H LENS EQU $-SOUCE BLOCK2 DB LENS DUP(?) DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX

  38. XOR SI,SI XOR DI,DI MOV CX, LENS CALL MOVSTOK MOV AH,4CH INT 21H MOVSTOK PROC NEAR PUSH AX NEXT: MOV AL, BLOCK1[SI] MOV BLOCK2[DI], AL INC SI INC DI LOOP NEXT POP AX RET MOVSTOK ENDP CODE ENDS END START

  39. 五、子程序的嵌套和递归调用 • 嵌套:子程序中再调用其它子程序 • 递归:子程序体中调用它本身,一般用于数学上函数的递归定义 。 嵌套与递归的共同之处就是都要用到堆栈操作,用于保护断点。 1、子程序的嵌套调用

  40. 主程序: 子程序: 子程序: …… …… CALL SUB1 (断点1:) …… …… HLT SUB1: …… CALL SUB2 (断点2: ) …… RET SUB2: …… …… RET • 子程序的嵌套调用

  41. 例: 找出BUF区存放的若干字节的最小值。并以十六进制形式显示。 • 程序利用嵌套实现 • DISP—— 显示一位十六进制数,被显示的内容存放在DL低4位。 • SEARCH—— 在BUF区中搜索最小无符号数 入口参数:SI—— 被搜索数据区的首地址。 CX—— 存放数据的个数。 出口参数:DL中存放最小值

  42. DISP PROC CMP DL,9 JBE DISP1 ADD DL,7 DISP1:ADD DL,30H MOV AH,2 INT 21H RET DISP ENDP CODE ENDS END START …… CALL SEARCH …… SEARCH PROC …… CALL DISP …… CALL DISP …… RET SEARCH ENDP

  43. 子程序的递归调用 例6-10:求N的阶乘 算法: =1(N=1) N!= =N*(N-1)!(N>1) 入口参数:N的值,利用寄存器AX 出口参数:阶乘值,用寄存器DX

  44. DATA SEGMENT N DW 6 RESU DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV AX,N CALL FACT MOV RESU ,DX

  45. MOV AH,4CH INT 21H FACT PROC CMP AX,0 JNE NEXT MOV DX,1 JMP EXIT NEXT:PUSH AX DEC AX CALL FACT POP AX MUL DL MOV DX,AX EXIT:RET FACT ENDP CODE ENDS END START

  46. 六、子程序设计举例 汇编语言在源程序的编写时,常用到输入和输出,当丛键盘输入一个数据时,输入设备实际是将数据(二进制、十六进制或十进制)的ASCII码输入计算机。而在输出时,不管是2、16或10进制的输出,都需要将计算机内部的二进制转换成相应进制的各位的ASCII码。

  47. 标准输出 STDOUT PROC PUSH DX MOV DL,AL MOV AH,2 INT 21H POP DX RET STDOUT ENDP 入口参数:输出字符ASCII码送AL

  48. 输入输出子程序 • 标准输入 STDIN PROC MOV AH,1 INT 21H RET STDIN ENDP 入口参数:等待输入字符 出口参数:输入字符的ASCII码存入AL寄存器

  49. 例1:将ASCII 码表示的16进制数,转换成1个字的二进制数。 入口参数:从输入设备输入的一个十六进制数。 出口参数:一个字的二进制数,在DX寄存器中。

More Related