汇编语言第6章子程序设计.ppt_第1页
汇编语言第6章子程序设计.ppt_第2页
汇编语言第6章子程序设计.ppt_第3页
汇编语言第6章子程序设计.ppt_第4页
汇编语言第6章子程序设计.ppt_第5页
已阅读5页,还剩66页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

6.1 子程序的调用与返回指令,6.1.1 子程序的调用指令CALL 6.1.2 返回指令RET,下一节,6.1.1 子程序的调用指令CALL,指令格式: CALL OPD 注:过程名或子程序名就是子程序入口处的符号地址。执行CALL指令时,首先要保留断点地址于堆栈中,然后程序转移到指定的子程序入口地址处去执行子程序。 由于子程序与调用它的程序可能在同一个段中,也可以不在同一个段中, CALL指令在转移到子程序入口地址时有两种寻址方式:直接寻址方式和间接寻址方式或者称为直接调用和间接调用。 前面提到,指令指针寄存器IP总是指向下一条将要执行的指令。在执行指令CALL时,堆栈中保存的就是原程序的断点地址(CALL指令后面1条指令的地址称为断点地址,也即返回地址)。,1.段内直接调用,在调用指令的目的操作数中直接给出过程名或子程序名。如CALL PROC1 执行的操作:(SP)(SP)-2 (SP)+1,(SP)(IP) (IP)(IP)+16位的位移量 指令中的过程名或子程序名为NEAR属性,给出了转向地址(即子程序的入口地址,亦子程序的第一条指令的地址)。 【例6.1】CALL DISPLAY1 DISPLAY1 PROC NEAR RET,2.段内的间接调用,子程序的入口地址存放在一个16位通用寄存器或字存储单元中。在调用指令的目的操作数是除立即数寻址的某种寻址方式确定的有效地址EA。 执行的操作是:(SP)(SP)-2 (SP)+1,(SP)(IP) (IP)(EA) 【例6.2】CALL BX ; CALL WORD PTR BX,3.段间直接调用,调用指令的目的操作数中直接给出过程名或子程序名。如:CALL PROC2 注:在不同的逻辑段中进行调用,直接调用的属性为FAR类型。 执行的操作:(SP)(SP)-2 (SP)+1,(SP)(CS) (IP)(EA) (SP)(SP)-2 (SP)+1,(SP)(IP) (IP)偏移地址 (CS)子程序的段基址 【例6.3】CALL DISPLAY2 DISPLAY2 PROC FAR RET,4.段内间接调用,子程序的入口地址存放在一个双字存储单元中,低地址的字单元存放入口地址的偏移量,高地址的字单元存放入口地址的段基址。 执行的操作:(SP)(SP)-2 (SP)+1,(SP)(CS) (IP)(EA) (SP)(SP)-2 (SP)+1,(SP)(IP) (IP)(EA) (CS)(EA+2) 【例6.4】CALL DWORD PTR BX,返回本章首,6.1.2 返回指令RET,RET指令放在子程序的末尾,它使子程序的功能完成后返回到调用程序继续执行,而返回地址是调用指令时存入堆栈中的,回此RET指令的操作就是返回IP寄存器和CS寄存器的值。 语句格式:RET 执行段内RET指令时,从堆栈顶部弹出一个字(返回地址)送IP。执行段间RET指令时,从堆栈顶部弹出两个字(返回地址),分别送入IP和CS中。 语句格式:RET n(n为偶数) 指令中参数N 应为偶数,如:2,4,6等。此指令先从堆顶弹出返回地址送IP或者IP和CS中,然后用参数N修改堆栈指针SP的值。SP=(SP)+N 根据调用的不同,返回指令也分为:,1段内返回 执行的操作:(IP)(SP)+1,(SP) (SP)(SP)+2 2段内带立即数返回 RET N 执行的操作:(IP)(SP)+1,(SP) (SP)(SP)+2 (SP)(SP)+N,返回本章首,6.2 子程序的设计方法,6.2.1 子程序的定义 6.2.2 子程序的调用与返回 6.2.3 信息的保存与恢复,下一节,6.2.1 子程序的定义,子程序的定义是由过程定义伪指令PROC和ENDP来完成的。其格式如下: 过程名 PROC NEAR/FAR 过程名 ENDP 其中PROC表示过程定义开始,ENDP表示过程定义结束。过程名是过程入口地址的符号表示。 一般过程名同标号一样,具有三种属性,即段属性、偏移地址属性以及类型属性。 当子程序和调用程序在同一个段时,子程序定义为NEAR属性;当子程序和调用程序不在同一个段时,子程序定义为FAR属性.,【例6.5】主程序和子程序在同一个代码段时的调用和定义 CODE SEGMENT MAIN PROC FAR CALL SUBPROG1 RET MAIN ENDP ;这一条指令也可以写在子程序结束之后 SUBPROG1 PROC NEAR RET SUBPROG1 ENDP CODE ENDS,【例6.6】主程序和子程序不在同一个代码段时的调用和定义 CODE SEGMENT MAIN PROC FAR CALL SUBPROG1 RET MAIN ENDP CODE1 SEGMENT SUBPROG1 PROC NEAR RET SUBPROG1 ENDP CODE1 ENDS,返回本章首,6.2.2 子程序的调用与返回,子程序的正确执行是由子程序的正确调用和正确返回保证的。汇编语言中子程序的调用指令CALL和返回指令RET来完成调用和返回功能。 在前面学习CALL和RET指令时,在调用子程序时要把返回地址入堆栈,在返回时要把返回地址出栈,因此在子程序的设计中一定要特别注意堆栈的使用。,返回本章首,6.2.3 信息的保存与恢复,由于主程序和子程序都具有相互独立的属性,而CPU中的寄存器是共用的,因此主程序和子程序在使用寄存器时有可能会发生冲突,也就是说主程序在调用子程序之前的某一个寄存器中的内容在从子程序返回后还要使用,而该寄存器在子程序中恰好被使用过,这样执行完子程序,相应的寄存器的内容就被改变,不是调用前主程序中该寄存器中原有的内容,从而当子程序执行完成后返回主程序执行时,主程序执行错误。为了避免类似这种错误,需要在进入子程序时,将子程序中涉及到主程序中的相应的寄存器内容进行保护,而在退出子程序之前恢复到原寄存器中,称这个为现场进行保护。,【例6.7】若子程序PROG中改变了寄存器AX,BX,CX,DX的值,则可采用如下方法保护和恢复现场。 PROG PROC PUSH AX PUSH BX PUSH CX ;保护现场 PUSH DX POP DX POP CX POP BX ;恢复现场 POP AX RET ;返回断点处 PROC ENDP,返回本章首,6.3 主程序与子程序参数传递方式,6.3.1 寄存器法 6.3.2 用参数表传递参数 6.3.3 堆栈法,下一节,6.3 主程序与子程序参数传递方式,调用程序在调用子程序时,经常需要向子程序传递一些参数,子程序运行结束后,有时候也需要向调用程序返回一些数据。这种在调用程序和子程序之间的信息的传递称为参数的传递(也中变量的传递)。汇编语言中,参数的传递方式有:,6.3.1 寄存器法,此种方法,多用于参数较少的情况。其方法就是将要传递的参数放入指定的寄存器中,然后在子程序中再从指定的寄存器中将参数读出。 【例6.8】从键盘输入一个十进制数,判断它的奇偶性,若为偶,在屏幕上显示”0”;若为奇,则显示”1”。 程序中用寄存器BL进行参数的传递:,CODE SEGMENT ASSUME CS:CODE START: MOV AH,01H INT 21H CLC RCR AL,1 JNC EVN MOV AL, 31H MOV BL,AL CALL DISP,EVN: MOV AL,30H MOV BL,AL CALL DISP MOV AH, 4CH INT 21H DISP PROC NEAR MOV AH, 02H MOV DL, 0AH INT 21H,MOV DL, 0DH INT 21H MOV DL,BL INT 21H RET DISP ENDP CODE ENDS END START,返回本章首,6.3.2 用参数表传递参数,这种参数传递方式通过定义一组连续的存储单元,即参数来进行参数的传递,将要传送的参数存放在参数表相应的存储单元内,然后把参数表的首地址通过BX寄存器传送到子程序中去。子程序通过访问参数表中相应的存储单元来获取所需的参数。,返回本章首页,【例6.9】,【例6.9】定义两个长度相同的数组A1、A2分别对两个数组求和、求差,并将结果保存数 组A3、A4中。 DATA SEGMENT A1 DB 24,35,67,45,89,90,99 LEN EQU ($-A1) A2 DB 22,30,45,34,12,2,6 A3 DB LEN DUP (?) A4 DB LEN DUP (?) TABLE DW 0,0,0,0,0 DATA ENDS,CODE SEGMENT ASSUEM CS:CODE,DS:DAT MAIN PROC FAR PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX MOV TABLE,OFFSET A1 MOV TABLE+2,OFFSET A2 MOV TABLE+4,LEN MOV TABLE+6,A3 MOV TABLE+8,A4,LEA BX,TABLE CALL ADDA3 CALL SUBA4 RET MAIN ENDP ADDA3 PROC NEAR PUSH AX PUSH CX PUSH SI PUSH DI MOV CX,BX+4,T1:MOV AL,BX ADD AL,BX+2 MOV BX+6,AL DEC CX INC BX CMP CX,0 JNZ T1,POP DI POP SI POP CX POP AX RET ADDA3 ENDP SUBA4 PROC NEAR PUSH AX PUSH CX PUSH SI PUSH DI MOV CX,BX+4,T1: MOV AL,BX SUB AL,BX+2 MOV BX+8,AL DEC CX INC BX CMP CX,0 JNZ T1 POP DI POP SI POP CX POP AX RET SUBA4 ENDP CODE ENDS END MAIN,返回本章首,6.3.3 堆栈法,此种方法适用于参数多、子程序嵌套调用和递归调用的情况。使用方法是调用程序在被调用子程序之前将参数压入堆栈,子程序从堆栈中取得参数。,【例6.10】,【例6.10】在数据段中存放着某班的三门课的成绩,求每门课的最高分,并分别存入到三个单无中。 DATA SEGMENT SCORE1 DB 91,62,63,84,76,76,78,55,64,64 LEN1 EQU $-SCORE1 SCORE2 DB 66,64,64,65,45,62,77,89,99,69 LEN2 EQU $-SCORE2 SCORE3 DB 77,88,92,63,21,64,83,88,81,53 LEN3 EQU $-SCORE3 MAX1 DB ? MAX2 DB ?,MAX3 DB ? DATA ENDS STACK SEGMENT TABLE DW 9 DUP (?) TOP LABEL WORD STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK MAIN PROC FAR START:MOV AX,STACK MOV SS,AX PUSH SS MOV AX,DATA MOV DS,AX XOR AX,AX,MOV SP,OFFSET TOP PUSH AX MOV BX,OFFSET SCORE1 PUSH BX MOV BX,OFFSET MAX1 PUSH BX MOV DX,LEN1 PUSH DX MOV BX,OFFSET SCORE2 PUSH BX MOV BX,OFFSET MAX2 PUSH BX MOV DX,LEN2 PUSH DX MOV BX,OFFSET SCORE3 PUSH BX MOV BX,OFFSET MAX3,PUSH BX MOV DX,LEN3 PUSH DX CALL PROCMAX CALL PROCMAX CALL PROCMAX POP AX POP DS POP SS RET MAIN ENDP PROCMAX PROC NEAR POP CX POP DI POP BX,T1:CMP AL,BX JAE T2 XCHG AL,BX T2: INC BX LOOP T1 MOV DI,AL RET PROCMAX ENDP CODE ENDS END START,返回本章首,6.4 子程序的嵌套与递归调用,6.4.1 子程序的嵌套 6.4.2 子程序的递归调用,下一节,6.4.1子程序的嵌套,子程序不但可以被主程序调用,而且也可以被其他子程序调用。把一个子程序调用另一个子程序称为子程序的嵌套调用。 子程序的嵌套调用示意图:,返回本章首,【例6.11】,【例6.11】 要求从键盘接受本班同学的某科成绩,并按成绩排名输出学生学号,最多为50个人。 程序的嵌套调用过程为:,图6.1,图6.1,图6.1,图6.1,图6.1,图6.1,图6.1,图6.1,图6.1,程序代码为:,DATA SEGMENT GRADE DW 50 DUP(?) RANK DW 50 DUP (?) COUNT DW ? MESS1 DB GRADE?,$ MESS2 DB 13,10,INPUT ERROR!,13,10,$ MESS3 DB RANK:,$ DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA MAIN PROC FAR,START: PUSH DS SUB AX,AX PUSH AX MOV AX,DATA MOV DS,AX CALL INPUT CALL RANKP CALL OUTPUT RET MAIN ENDP INPUT PROC NEAR LEA DX,MESS1 MOV AH,09H INT 21H MOV SI,0,MOV COUNT,0 ENTER:CALL DECIBIN INC COUNT CMP DL, JE STORE CMP DL,13 JE EXIT2 JNE ERROR STORE: MOV GRADESI,BX ADD SI,2 MOV DL,00H MOV AH,02H INT 21H JMP ENTER,ERROR: LEA DX,MESS2 MOV AH,09 INT 21H EXIT2: MOV GRADESI,BX CALL CRLF RET INPUT ENDP RANKP PROC NEAR MOV DI,COUNT MOV BX,0 LOOP1: MOV AX,GRADEBX MOV WORD PTR RANKBX,0 MOV CX,COUNT LEA SI,GRADE,NEXT: CMP AX,SI JG NO_COUNT INC WORD PTR RANKBX NO_COUNT:ADD SI,2 LOOP NEXT ADD BX,2 DEC DI JNE LOOP1 RET RANKP ENDP OUTPUT PROC NEAR,LEA DX,MESS3 MOV AH,09 INT 21H MOV SI,0 MOV DI,COUNT NEXT1: MOV BX,RANKSI CALL BINIDEC MOV DL, MOV AH,02 INT 21H ADD SI,2 DEC DI JNZ NEXT1 CALL CRLF RET,OUTPUT ENDP DECIBIN PROC NEAR MOV BX,0 NEWCHAR: MOV AH,1 INT 21H MOV DL,AL SUB AL,30H JL EXIT1 CMP AL,9D JG EXIT1 CBW XCHG AX,BX MOV CX,10D MUL CX XCHG AX,BX ADD BX,AX JMP NEWCHAR,XIT1:RET DECIBIN ENDP BINIDEC PROC NEAR PUSH BX PUSH CX PUSH SI PUSH DI MOV CX,100D CALL DEC_DIV MOV CX,10D CALL DEC_DIV MOV CX,1D CALL DEC_DIV POP DI POP SI POP CX POP BX RET,BINIDEC ENDP DEC_DIV PROC NEAR MOV AX,BX MOV DX,0 DIV CX MOV BX,DX MOV DL,AL ADD DL,30H MOV AH,02H INT 21H RET DEC_DIV ENDP CRLF PROC NEAR,MOV DL,0AH MOV AH,02 INT 21H MOV DL,0DH MOV AH,02 INT 21H RET CRLF ENDP CODE ENDS END START,返回本章首,6.4.2 子程序的递归调用,子程序的递归调用是指一个子程序直接或间接地调用自己。递归子程序一般对应于数学上对函数的递归定义,它往往能设计出效率较高的程序,完成相当复杂的计算,因而是很有用的。,【例6.12】,【例6.12】试编制计算N! (N0)的程序。N!=N*(N-1)*(N-2)*1 其递归定义如下: 0!=1 N!=N*(N-1)! (N1),【例4.16】,STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS DATA SEGMENT N DW 5 RESULT DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE, SS:STACK,DS:DATA START:MOV AX,DATA,MOV DS,AX MOV AX,N CALL FACT MOV AX,RESULT MOV AH,4CH INT 21H FACT PROC CMP AX,0 JNE L1 MOV RESULT,1 JMP EXIT,L1:PUSH AX DEC AX CALL FACT POP AX MOV RESULT MOV RESNLT,AX EXIT:RET FACT ENDP CODE ENDS END START,返回本章首,6.5 子程序应用举例,【例6.13】将一个给定的二进制数按位转换成相应的ASCII码字符串,送到指定的存储单元并显示。如二进制数10010011转换成字符串为10010011。要求将转换过程写成子程序,且子程序应具有较好的通用性,而必须能实现对8倍和16倍二进制数的转换。 入口参数:DX存放待转换的二进制数 CX存放待转换数的位数(8位或16位) DI存放ASCII码首地址 出口参数:转换后的字符串存放在以DI作指针的字节存贮区中 程序如下:,DATA SEGMENT NUM8 DB 93H NUM16 DW ABCDH ASCBUF DB 20 DUP(0) DATA ENDS CODE SEGMENT ASSUME DS:DATA,CS:CODE, SS:STACK START:MOV AX,DATA MOV DS,AX MOV DX,0 MOV DL,NUM8 ;转换二进制数送DX MOV CX,8 ;置位数8 LEA DI,ASCBUF ;字符串首址DI CAL BTASC ;调用子程序BTASC,MOV DI,BYTE PTR 0DH MOV DI+1,BYTE PTR 0AH MOV DI+2,BYTE PTR $ LEA DX,ASCBUF MOV AH,9 INT 21H MOV DX,NUM16 MOV CX,16 ;置位数16 LEA DI,ASCBUF CALL BTASC MOV DL,BYTE PTR 0DH MOV DL+1,BYTE PTR 0AH MOV DL+2,BYTE PTR ;显示转换后的字符串 LEA DX, ASCBUF,MOV AH,9 INT 21H BTASC PROC PUSH AX ;保存AX MOV AL,0 CMP CX,8 ;比较8位数 JNE L1 ;直接转换16位数 MOV DH,DL ;8位数转换送DH L1: ROL DX,,1 ;DX最高位移入CF RCL

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论