资源预览内容
第1页 / 共71页
第2页 / 共71页
第3页 / 共71页
第4页 / 共71页
第5页 / 共71页
第6页 / 共71页
第7页 / 共71页
第8页 / 共71页
第9页 / 共71页
第10页 / 共71页
亲,该文档总共71页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第6章 子程序设计6.1 子程序子程序的调用与返回指令的调用与返回指令 6.1.1 子程序的子程序的调用指令调用指令CALL 6.1.2 返回指令返回指令RET 下一节下一节第6章 子程序设计6.1.1 子程序的子程序的调用指令调用指令CALL指令格式:指令格式: CALL OPD注:过程名或子程序名就是子程序入口处的符号地址。执行注:过程名或子程序名就是子程序入口处的符号地址。执行CALL指令时,首先要保留断点地址于堆栈中,然后程序转移到指定指令时,首先要保留断点地址于堆栈中,然后程序转移到指定的子程序入口地址处去执行子程序。的子程序入口地址处去执行子程序。由于子程序与调用它的程序可能在同一个段中,也可以不在同一由于子程序与调用它的程序可能在同一个段中,也可以不在同一个段中,个段中, CALL指令在转移到子程序入口地址时有两种寻址方指令在转移到子程序入口地址时有两种寻址方式:直接寻址方式和间接寻址方式或者称为直接调用和间接调式:直接寻址方式和间接寻址方式或者称为直接调用和间接调用。用。前面提到,指令指针寄存器前面提到,指令指针寄存器IP总是指向下一条将要执行的指令。在总是指向下一条将要执行的指令。在执行指令执行指令CALL时,堆栈中保存的就是原程序的断点地址时,堆栈中保存的就是原程序的断点地址(CALL指令后面指令后面1条指令的地址称为断点地址,也即返回地址)条指令的地址称为断点地址,也即返回地址)。第6章 子程序设计1.段内直接调用段内直接调用在调用指令的目的操作数中直接给出过程名或子程序名。如在调用指令的目的操作数中直接给出过程名或子程序名。如CALL PROC1执行的操作:(执行的操作:(SP)(SP)-2 (SP)+1,(,(SP)(IP) (IP)(IP)+16位的位移量位的位移量指令中的过程名或子程序名为指令中的过程名或子程序名为NEAR属性,给出了转向地址(即子属性,给出了转向地址(即子程序的入口地址,亦子程序的第一条指令的地址)。程序的入口地址,亦子程序的第一条指令的地址)。【例例6.1】CALL DISPLAY1 DISPLAY1 PROC NEAR RET第6章 子程序设计2.段内的间接调用段内的间接调用 子程序的入口地址存放在一个子程序的入口地址存放在一个16位通用寄存器或位通用寄存器或字存储单元中。在调用指令的目的操作数是除立即数字存储单元中。在调用指令的目的操作数是除立即数寻址的某种寻址方式确定的有效地址寻址的某种寻址方式确定的有效地址EA。执行的操作是:(执行的操作是:(SP)(SP)-2 (SP)+1,(,(SP)(IP) (IP)(EA)【例例6.2】CALL BX ; CALL WORD PTR BX第6章 子程序设计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第6章 子程序设计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章 子程序设计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根据调用的不同,返回指令也分为:根据调用的不同,返回指令也分为:第6章 子程序设计1段内返回执行的操作:(IP)(SP)+1,(SP) (SP)(SP)+22段内带立即数返回 RET N执行的操作:(IP)(SP)+1,(SP) (SP)(SP)+2 (SP)(SP)+N返回本章首返回本章首第6章 子程序设计6.2 子程序的设计方法子程序的设计方法 6.2.1 子程序的定义子程序的定义 6.2.2 子程序的调用与返回子程序的调用与返回 6.2.3 信息的保存与恢复信息的保存与恢复 下一节下一节第6章 子程序设计6.2.1 子程序的定义子程序的定义 子程序的定义是由过程定义伪指令子程序的定义是由过程定义伪指令PROC和和ENDP来完来完成的。其格式如下:成的。其格式如下: 过程名过程名 PROC NEAR/FAR 过程名过程名 ENDP 其中其中PROC表示过程定义开始,表示过程定义开始,ENDP表示过程定义结表示过程定义结束。过程名是过程入口地址的符号表示。束。过程名是过程入口地址的符号表示。 一般过程名同标号一样,具有三种属性,即段属性、偏一般过程名同标号一样,具有三种属性,即段属性、偏移地址属性以及类型属性。移地址属性以及类型属性。 当子程序和调用程序在同一个当子程序和调用程序在同一个段时,子程序定义为段时,子程序定义为NEAR属性;当子程序和调用程序不属性;当子程序和调用程序不在同一个段时,子程序定义为在同一个段时,子程序定义为FAR属性属性.第6章 子程序设计【例6.5】主程序和子程序在同一个代码段时的调用和定义CODE SEGMENT MAIN PROC FAR CALL SUBPROG1 RETMAIN ENDP ;这一条指令也可以写在子程序结束之后SUBPROG1 PROC NEAR RETSUBPROG1 ENDPCODE ENDS第6章 子程序设计【例6.6】主程序和子程序不在同一个代码段时的调用和定义CODE SEGMENT MAIN PROC FAR CALL SUBPROG1 RETMAIN ENDPCODE1 SEGMENT SUBPROG1 PROC NEAR RETSUBPROG1 ENDPCODE1 ENDS返回本章首返回本章首第6章 子程序设计6.2.2 子程序的调用与返回子程序的调用与返回 子程序的正确执行是由子程序的正确调子程序的正确执行是由子程序的正确调用和正确返回保证的。汇编语言中子程序的用和正确返回保证的。汇编语言中子程序的调用指令调用指令CALL和返回指令和返回指令RET来完成调用和来完成调用和返回功能。返回功能。 在前面学习在前面学习CALL和和RET指令时,在调指令时,在调用子程序时要把返回地址入堆栈,在返回时用子程序时要把返回地址入堆栈,在返回时要把返回地址出栈,因此在子程序的设计中要把返回地址出栈,因此在子程序的设计中一定要特别注意堆栈的使用。一定要特别注意堆栈的使用。返回本章首返回本章首第6章 子程序设计6.2.3 信息的保存与恢复信息的保存与恢复 由于主程序和子程序都具有相互独立的属性,而由于主程序和子程序都具有相互独立的属性,而CPU中的寄存器是共用的,因此主程序和子程序在中的寄存器是共用的,因此主程序和子程序在使用寄存器时有可能会发生冲突,也就是说主程序在使用寄存器时有可能会发生冲突,也就是说主程序在调用子程序之前的某一个寄存器中的内容在从子程序调用子程序之前的某一个寄存器中的内容在从子程序返回后还要使用,而该寄存器在子程序中恰好被使用返回后还要使用,而该寄存器在子程序中恰好被使用过,这样执行完子程序,相应的寄存器的内容就被改过,这样执行完子程序,相应的寄存器的内容就被改变,不是调用前主程序中该寄存器中原有的内容,从变,不是调用前主程序中该寄存器中原有的内容,从而当子程序执行完成后返回主程序执行时,主程序执而当子程序执行完成后返回主程序执行时,主程序执行错误。为了避免类似这种错误,需要在进入子程序行错误。为了避免类似这种错误,需要在进入子程序时,将子程序中涉及到主程序中的相应的寄存器内容时,将子程序中涉及到主程序中的相应的寄存器内容进行保护,而在退出子程序之前恢复到原寄存器中,进行保护,而在退出子程序之前恢复到原寄存器中,称这个为现场进行保护。称这个为现场进行保护。第6章 子程序设计【例例6.7】若子程序若子程序PROG中改变了寄存器中改变了寄存器AX,BX,CX,DX的值,的值,则可采用如下方法保护和恢复现场。则可采用如下方法保护和恢复现场。PROG PROCPUSH AXPUSH BXPUSH CX ;保护现场;保护现场PUSH DX POP DXPOP CXPOP BX ;恢复现场;恢复现场POP AXRET ;返回断点处;返回断点处PROC ENDP返回本章首返回本章首第6章 子程序设计6.3 主程序与子程序参数传递方式主程序与子程序参数传递方式 6.3.1 寄存器法寄存器法 6.3.2 用参数表传递参数用参数表传递参数 6.3.3 堆栈法堆栈法 下一节下一节第6章 子程序设计6.3 主程序与子程序参数传递方式主程序与子程序参数传递方式 调调用用程程序序在在调调用用子子程程序序时时,经经常常需需要要向向子子程程序序传传递递一一些些参参数数,子子程程序序运运行行结结束束后后,有有时时候候也也需需要要向向调调用用程程序序返返回回一一些些数数据据。这这种种在在调调用用程程序序和和子子程程序序之之间间的的信信息息的的传传递递称称为为参参数数的的传传递递(也也中中变变量量的的传传递递)。汇编语言中,参数的传递方式有:汇编语言中,参数的传递方式有:第6章 子程序设计 6.3.1 寄存器法寄存器法 此种方法,多用于参数较少的情况。其方法就此种方法,多用于参数较少的情况。其方法就是将要传递的参数放入指定的寄存器中,然后在子程是将要传递的参数放入指定的寄存器中,然后在子程序中再从指定的寄存器中将参数读出。序中再从指定的寄存器中将参数读出。 【例例6.8】从键盘输入一个十进制数从键盘输入一个十进制数,判断它的奇偶性判断它的奇偶性,若为偶若为偶,在屏幕上显示在屏幕上显示”0”;若为奇若为奇,则显示则显示”1”。 程序中用寄存器程序中用寄存器BL进行参数的传递进行参数的传递:第6章 子程序设计CODE SEGMENT ASSUME CS:CODESTART: MOV AH,01H INT 21H CLC RCR AL,1 JNC EVN MOV AL, 31H MOV BL,AL CALL DISP第6章 子程序设计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第6章 子程序设计MOV DL, 0DHINT 21HMOV DL,BLINT 21HRETDISP ENDPCODE ENDSEND START返回本章首返回本章首第6章 子程序设计6.3.2 用参数表传递参数用参数表传递参数 这这种种参参数数传传递递方方式式通通过过定定义义一一组组连连续续的的存存储储单单元元,即即参参数数来来进进行行参参数数的的传传递递,将将要要传传送送的的参参数数存存放放在在参参数数表表相相应应的的存存储储单单元元内内,然然后后把把参参数数表表的的首首地地址址通通过过BX寄寄存存器器传传送送到到子子程程序序中中去去。子子程程序序通通过过访访问问参参数数表表中中相相应应的的存存储储单单元来获取所需的参数。元来获取所需的参数。返回本章首页返回本章首页第6章 子程序设计【例例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第6章 子程序设计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第6章 子程序设计 LEA BX,TABLE CALL ADDA3 CALL SUBA4 RET MAIN ENDPADDA3 PROC NEAR PUSH AX PUSH CX PUSH SI PUSH DI MOV CX,BX+4第6章 子程序设计T1:MOV AL,BX ADD AL,BX+2 MOV BX+6,AL DEC CX INC BX CMP CX,0 JNZ T1第6章 子程序设计POP DIPOP SIPOP CXPOP AXRETADDA3 ENDPSUBA4 PROC NEARPUSH AXPUSH CXPUSH SIPUSH DIMOV CX,BX+4第6章 子程序设计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 RETSUBA4 ENDPCODE ENDS END MAIN返回本章首返回本章首第6章 子程序设计 6.3.3 堆栈法堆栈法 此种方法适用于参数多、子程序嵌套调此种方法适用于参数多、子程序嵌套调用和递归调用的情况。使用方法是调用程序用和递归调用的情况。使用方法是调用程序在被调用子程序之前将参数压入堆栈,子程在被调用子程序之前将参数压入堆栈,子程序从堆栈中取得参数。序从堆栈中取得参数。第6章 子程序设计【例例6.10】【例例6.10】在数据段中存放着某班的三门课的成绩,求每门课的最在数据段中存放着某班的三门课的成绩,求每门课的最高分,并分别存入到三个单无中。高分,并分别存入到三个单无中。DATA SEGMENTSCORE1 DB 91,62,63,84,76,76,78,55,64,64LEN1 EQU $-SCORE1SCORE2 DB 66,64,64,65,45,62,77,89,99,69LEN2 EQU $-SCORE2SCORE3 DB 77,88,92,63,21,64,83,88,81,53LEN3 EQU $-SCORE3MAX1 DB ?MAX2 DB ?第6章 子程序设计 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 FARSTART:MOV AX,STACK MOV SS,AX PUSH SS MOV AX,DATA MOV DS,AX XOR AX,AX第6章 子程序设计MOV SP,OFFSET TOPPUSH AXMOV BX,OFFSET SCORE1PUSH BXMOV BX,OFFSET MAX1PUSH BXMOV DX,LEN1PUSH DXMOV BX,OFFSET SCORE2PUSH BXMOV BX,OFFSET MAX2PUSH BXMOV DX,LEN2PUSH DXMOV BX,OFFSET SCORE3PUSH BXMOV BX,OFFSET MAX3第6章 子程序设计PUSH BXMOV DX,LEN3PUSH DXCALL PROCMAXCALL PROCMAXCALL PROCMAXPOP AXPOP DSPOP SSRETMAIN ENDPPROCMAX PROC NEARPOP CXPOP DIPOP BX第6章 子程序设计T1:CMP AL,BX JAE T2 XCHG AL,BX T2: INC BX LOOP T1 MOV DI,AL RET PROCMAX ENDPCODE ENDS END START返回本章首返回本章首第6章 子程序设计6.4 子程序的嵌套与递归调用子程序的嵌套与递归调用 6.4.1 子程序的嵌套子程序的嵌套 6.4.2 子程序的递归调用子程序的递归调用下一节下一节第6章 子程序设计6.4.1子程序的嵌套子程序的嵌套 子程序不但可以被主程序调用,而且也子程序不但可以被主程序调用,而且也可以被其他子程序调用。把一个子程序调用可以被其他子程序调用。把一个子程序调用另一个子程序称为子程序的嵌套调用。另一个子程序称为子程序的嵌套调用。 子程序的嵌套调用示意图:子程序的嵌套调用示意图:返回本章首返回本章首第6章 子程序设计主程序主程序CALL 子子程程序序1CALL 子子程程序序1CALL 子子程程序序2CALL 子子程程序序2CALL 子子程程序序NCALL 子子程程序序NRET断点断点NRET断点断点2RET断点断点1程程序序顺顺序序执执行行入入口口第6章 子程序设计【例例6.11】【例例6.11】 要求从键盘接受本班同学的某科成要求从键盘接受本班同学的某科成绩,并按成绩排名输出学生学号,最多为绩,并按成绩排名输出学生学号,最多为50个人。个人。 程序的嵌套调用过程为:程序的嵌套调用过程为:第6章 子程序设计开始开始调用调用INPUT子程序,输入成绩子程序,输入成绩调用调用RANKP子程序,对成绩进行排序子程序,对成绩进行排序调用调用OUTPUT子程序,按学号输出排序结果子程序,按学号输出排序结果结束结束图6.1图6.1图6.1图6.1图6.1图6.1图6.1图6.1图6.1第6章 子程序设计子程序子程序INPUT开始开始调用调用DECIBIN子程序,将每次输入的字符串转换成二进制数子程序,将每次输入的字符串转换成二进制数调用回车换行,在下一行显示输出排序结果调用回车换行,在下一行显示输出排序结果结束结束第6章 子程序设计子程序子程序OUTPUT开始开始调用调用BINIDEC子程序,将二进制数转换成十进制数每一位输出子程序,将二进制数转换成十进制数每一位输出调用回车换行,在下一行显示输出排序结果调用回车换行,在下一行显示输出排序结果结束结束第6章 子程序设计调用调用DEC_DIV子程序,将二进制数转换为十进制数的百位子程序,将二进制数转换为十进制数的百位调用回车换行,在下一行显示输出排序结果调用回车换行,在下一行显示输出排序结果结束调用调用DEC_DIV子程序,将二进制数转换为十进制数的十位子程序,将二进制数转换为十进制数的十位调用调用DEC_DIV子程序,将二进制数转换为十进制数的个位子程序,将二进制数转换为十进制数的个位子程序子程序BINIDEC开始开始第6章 子程序设计程序代码为:程序代码为: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 ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATA MAIN PROC FAR第6章 子程序设计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第6章 子程序设计 MOV COUNT,0 ENTER:CALL DECIBIN INC COUNT CMP DL, JE STORE CMP DL,13 JE EXIT2 JNE ERRORSTORE: MOV GRADESI,BX ADD SI,2 MOV DL,00H MOV AH,02H INT 21H JMP ENTER第6章 子程序设计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,0LOOP1: MOV AX,GRADEBX MOV WORD PTR RANKBX,0 MOV CX,COUNT LEA SI,GRADE第6章 子程序设计NEXT: CMP AX,SI JG NO_COUNT INC WORD PTR RANKBXNO_COUNT:ADD SI,2 LOOP NEXT ADD BX,2 DEC DI JNE LOOP1 RET RANKP ENDP OUTPUT PROC NEAR第6章 子程序设计 LEA DX,MESS3 MOV AH,09 INT 21H MOV SI,0 MOV DI,COUNTNEXT1: MOV BX,RANKSI CALL BINIDEC MOV DL, MOV AH,02 INT 21H ADD SI,2 DEC DI JNZ NEXT1 CALL CRLF RET第6章 子程序设计OUTPUT ENDPDECIBIN 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第6章 子程序设计XIT1:RETDECIBIN ENDPBINIDEC 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第6章 子程序设计BINIDEC ENDPDEC_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 RETDEC_DIV ENDPCRLF PROC NEAR第6章 子程序设计 MOV DL,0AH MOV AH,02 INT 21H MOV DL,0DH MOV AH,02 INT 21H RETCRLF ENDPCODE ENDS END START返回本章首返回本章首第6章 子程序设计6.4.2 子程序的递归调用子程序的递归调用 子程序的递归调用是指一个子子程序的递归调用是指一个子程序直接或间接地调用自己。递归程序直接或间接地调用自己。递归子程序一般对应于数学上对函数的子程序一般对应于数学上对函数的递归定义,它往往能设计出效率较递归定义,它往往能设计出效率较高的程序,完成相当复杂的计算,高的程序,完成相当复杂的计算,因而是很有用的。因而是很有用的。第6章 子程序设计【例例6.12】 【例例6.12】试编制计算试编制计算N! (N0)的程序。)的程序。N!=N*(N-1)*(N-2)*1 其递归定义如下:其递归定义如下: 0!=1 N!=N*(N-1)! (N1)第6章 子程序设计【例例4.16】STACK SEGMENT STACK DB 200 DUP(0)STACK ENDSDATA SEGMENT N DW 5 RESULT DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE, SS:STACK,DS:DATASTART:MOV AX,DATA第6章 子程序设计MOV DS,AXMOV AX,NCALL FACTMOV AX,RESULTMOV AH,4CHINT 21HFACT PROCCMP AX,0JNE L1MOV RESULT,1JMP EXIT第6章 子程序设计L1:PUSH AX DEC AX CALL FACT POP AX MOV RESULT MOV RESNLT,AXEXIT:RET FACT ENDP CODE ENDS END START返回本章首返回本章首第6章 子程序设计6.5 子程序应用举例子程序应用举例 【例例6.13】将一个给定的二进制数按位转换成相应的将一个给定的二进制数按位转换成相应的ASCII码字符串,送到指定的存储单元码字符串,送到指定的存储单元并显示。如二进制数并显示。如二进制数10010011转换成转换成字符串为字符串为10010011。要求将转换。要求将转换过程写成子程序,且子程序应具有较过程写成子程序,且子程序应具有较好的通用性,而必须能实现对好的通用性,而必须能实现对8倍和倍和16倍二进制数的转换。倍二进制数的转换。 入口参数:入口参数:DX存放待转换的二进制数存放待转换的二进制数 CX存放待转换数的位数(存放待转换数的位数(8位或位或16位)位) DI存放存放ASCII码首地址码首地址 出口参数:转换后的字符串存放在以出口参数:转换后的字符串存放在以DI作指针的字节作指针的字节存贮区中存贮区中 程序如下:程序如下: 第6章 子程序设计DATA SEGMENT NUM8 DB 93H NUM16 DW ABCDH ASCBUF DB 20 DUP(0)DATA ENDSCODE SEGMENT ASSUME DS:DATA,CS:CODE, SS:STACKSTART:MOV AX,DATA MOV DS,AX MOV DX,0 MOV DL,NUM8 ;转换二进制数送转换二进制数送DX MOV CX,8 ;置位数置位数8 LEA DI,ASCBUF ;字符串首址字符串首址DI CAL BTASC ;调用子程序调用子程序BTASC第6章 子程序设计MOV DI,BYTE PTR 0DHMOV DI+1,BYTE PTR 0AHMOV DI+2,BYTE PTR $LEA DX,ASCBUFMOV AH,9INT 21HMOV DX,NUM16MOV CX,16 ;置位数16LEA DI,ASCBUFCALL BTASCMOV DL,BYTE PTR 0DHMOV DL+1,BYTE PTR 0AHMOV DL+2,BYTE PTR ;显示转换后的字符串LEA DX, ASCBUF 第6章 子程序设计 MOV AH,9 INT 21HBTASC 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 AL,1 ;CF移入AL最低位 ADD AL,30H MOV DI,AL第6章 子程序设计 INC DI LOOP L1 POP AX RETBTASC ENDPCODE ENDSEND START第6章 子程序设计【例例6.14】 【例例6.14】从键盘接受一个十进制数,并以十从键盘接受一个十进制数,并以十六进制数形式在屏幕上显示。程序设计结构六进制数形式在屏幕上显示。程序设计结构如下:如下: 第6章 子程序设计开始开始调用调用INPUTBIN,输入一个十进制数,并保存在,输入一个十进制数,并保存在BX中中调用调用CRLF,完成回车换行,完成回车换行调用调用CHANGE,完成十六进制的转换及输出,完成十六进制的转换及输出调用调用CRLF,完成回车换行,完成回车换行结束结束第6章 子程序设计程序的代码为:CODE SEGMENT ASSUME CS:CODEMAIN PROC FAR CALL DECIBIN CALL CRLF CALL BINIHEX CALL CRLF RETMAIN ENDPDECIBIN PROC NEAR MOV BX,0第6章 子程序设计NEWCHAR:MOV AH,01 INT 21H SUB AL,30H JL EXIT CMP AL,9D JG EXIT CBW XCHG AX,BX MOV CX,10D MUL CX XCHG AX, BX ADD BX,AX JMP NEWCHAR EXIT RET 第6章 子程序设计 DECIBIN ENDP BINIHEX PROC NEAR MOV CH,4ROTATE: MOV CL,4 ROL BX,CL MOV AL,BL AND AL,0FH ADD AL,30H CMP AL,3AH JL PRINTIT ADD AL,7H第6章 子程序设计PRINTIT: MOV DL,AL MOV AH,2 INT 21H DEC CH JNZ ROTATE RETBINIHEX ENDP CRLF PROC NEAR MOV DL,0DH MOV AH,2 INT 21H MOV DL,0AH第6章 子程序设计 MOV AH,2 INT 21H RETCRLF ENDPCODE ENDSEND MAIN第6章 子程序设计课后习题:课后习题:1、子程序是如何定义和调用的,请简要说明调用子程、子程序是如何定义和调用的,请简要说明调用子程序和从子程序返回主程序的过程。序和从子程序返回主程序的过程。2、用子程序实现,从键盘接受一个字符串,将大写字、用子程序实现,从键盘接受一个字符串,将大写字母转换为小写,将小写字母转换为大写,并显示原串母转换为小写,将小写字母转换为大写,并显示原串和转换后的字符串。和转换后的字符串。3、利用子程序,完成数组、利用子程序,完成数组A1和和A2的和与差,并将结果的和与差,并将结果保存在保存在A3和和A4中。?中。?4、编写一个子程序,完成、编写一个子程序,完成N!。!。第6章 子程序设计Thank you very much !本章到此结束,谢谢您的光临本章到此结束,谢谢您的光临 !返回本章首页返回本章首页结结 束束
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号