第09章-子程序设计及系统调用_第1页
第09章-子程序设计及系统调用_第2页
第09章-子程序设计及系统调用_第3页
第09章-子程序设计及系统调用_第4页
第09章-子程序设计及系统调用_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

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

文档简介

第9章子程序设计及系统调用

9.1调用程序与子程序对于在不同的代码段,以及在不同的源程序中用到同一个程序段的问题,不宜用循环程序设计技术来解决。有必要将需要重复或经常使用的程序段编制成独立的程序,在需要的位置使用特定的指令调用该独立的程序,执行后再返回到上述的调用位置继续执行其后的指令。这种独立的程序就称为子程序,也称为过程,而调用子程序的程序称为调用程序。9.2调用与返回指令(表9.1)

CALL、RET与转移和循环指令类似,对IP、CS值的改变不同于一般指令。

CALL指令将顺序排列的下一指令的地址压入堆栈以便返回,而将该指令给出的转移目标地址送IP,也即将该指令指定位置的指令作为要执行的下一指令。(若CALL指令为远调用指令,CS的内容将是该指令指定位置的段地址)RET将处于栈顶的地址弹至IP以实现返回(对于远调用,RET指令还要恢复调用前CS的内容)。

9.2调用与返回指令【例9.1】

设在执行以下程序段之前(BX)=4200H,(SP)=1034H,则指令指针IP,堆栈指针SP及堆栈在CALL指令和RET指令执行前后的状况是怎样的?……D020:0083

CALL

BXD020:0085

NOP

……

D020:4200

……

……

D020:42B1

RET9.3子程序设计(1)将需要重复或经常使用的程序段编制成独立程序,并通过一定的格式来定义,该工作称为子程序的定义。(2)在调用程序的若干个适当位置使用CALL指令调用子程序。(3)在子程序中设置RET指令,以便返回调用程序。(4)在子程序起始处保护调用时的现场,在子程序返回前恢复调用时的现场。所谓现场,是指有关寄存器及存储单元的内容。保护和恢复现场的目的在于,避免因调用子程序而破坏调用程序所使用的寄存器和内存单元内容。(5)实现调用程序与子程序之间的参数传递。包括调用程序为子程序提供入口参数,子程序向调用程序提供出口参数。9.3.1子程序的定义

1.子程序定义的格式子程序按照过程形式定义,其格式有以下两种:(1)标号PROC

NEAR;其中NEAR可省略。

……

标号ENDP(2)标号PROC

FAR

……

标号ENDP9.3.1子程序的定义

2.子程序的结构子程序在遵循上述格式的基础上,

通常有如下结构:标号

PROC

NEAR或FAR

保护现场根据入口参数进行处理产生出口参数恢复现场RET标号

ENDP9.3.2子程序的调用与返回

【例9.2】

以下程序用于计算=m!/(n!*(m-n)!)的值(m,n为自然数,且m>n)。(1)解决这一问题需要三次计算阶乘值X!,而且并非连续重复这一计算工作,故宜于将计算阶乘值X!的工作用子程序来实现。在调用程序中于三个适当位置使用CALL指令来调用子程序。在子程序中设置RET指令返回调用程序。(2)在调用子程序计算m!,n!及(m-n)!时,应分别将m,n及m-n的值送CX,即为子程序提供入口参数。(3)子程序根据入口参数计算出对应的阶乘值,并将其作为出口参数通过AX提供给调用程序。(4)该子程序使用CX传递入口参数,用AX传递出口参数(无需保护现场和恢复现场)。SSEGSEGMENT

STACKDB

80H

DUP(0)SSEGENDS……CSEGSEGMENT……MOV

CX,NCALL

SUB1;调用子程序计算n!MOV

BX,AX;BX←n!;MOV

CX,MCALL

SUB1;调用子程序计算m!DIV

BX;AX←m!/n!MOVBX,AX

MOV

CX,MSUB

CX,NCALLSUB1;调用子程序计数(m-n)!XCHGBX,AXDIV

BX;AX←m!/n!/(m-n)!。MOV

ANS,AX……SUB1

PROCMOV

AX,1NT:MUL

AX,CXLOOPNTRETSUB1

ENDPCSEGENDS9.3.3保护现场与恢复现场1.保护现场与恢复现场的必要性2.保护现场与恢复现场的位置(1)在调用程序中保护现场与恢复现场。即在CALL指令前保护现场,而在CALL指令后恢复现场。(2)在子程序中保护现场与恢复现场。即在子程序的起始处保护现场,而在其返回指令,即RET指令前恢复现场。这种方法较为常用。

9.3.4参数的传递1.约定寄存器法2.约定存储单元法3.堆栈法

【例9.7】编写程序,用以统计字节数组中零元素的个数。分析:(1)将统计字节数组中零元素个数的工作用子程序来实现。(2)对于一个首地址为ARRAYB,字节数为COUNT的字节数组来说,应将ARRAYB及COUNT作为入口参数提供给子程序;而子程序应在统计出ARRAYB开始的COUNT个字节数中零元素个数后,将零元素个数作为出口参数提供给调用程序。【例9.7】编写程序,用以统计字节数组中零元素的个数。1)使用约定寄存器法传递参数SI←ARRAYB(入口参数)CX←COUNT(入口参数)AX←零元素个数(出口参数)

ZNUM

PROCXOR

AX,AXNT:CMP

BYTE

PTR[SI],0JNZNZINCAXNZ:INC

SILOOP

NTRETZNUMENDP

DSEGSEGMENTARRAYBDB(若干个字节数)COUNT

EQU

$-ARRAYBANS

DW?DSEG

ENDSCSEGSEGMENT……

LEA

SI,ARRAYB

MOV

CX,COUNTCALL

ZNUM

MOV

ANS,AXMOV

AH,4CHINT

21HZNUM

PROCXOR

AX,AXNT:CMP

BYTE

PTR[SI],0JNZNZINCAXNZ:INC

SILOOP

NTRETZNUMENDP;CSEGENDSEND

ST【例9.7】编写程序,用以统计字节数组中零元素的个数。2)使用约定存储单元法传递参数PARA1←ARRAYB(入口参数)PARA2←COUNT(入口参数)PARA3←零元素个数(出口参数)ZNUM

PROC

MOV

SI,PARA1

MOVCX,PARA2

XOR

AX,AXNT:CMP

BYTE

PTR[SI],0JNZNZINCAXNZ:INC

SILOOP

NT

MOVPARA3,AX

RETZNUMENDPARRAYB DB(若干个字节数)COUNT EQU

$-ARRAYBANS

DW?PARA1

DW?PARA2

DW?PARA3

DW?DSEG

ENDS……

LEA

SI,ARRAYB

MOVPARA1,SI

MOVPARA2,COUNT

CALL

ZNUM

MOVAX,PARA3

MOV

ANS,AXMOV

AH,4CHINT

21HZNUM

PROC

MOV

SI,PARA1

MOVCX,PARA2

XOR

AX,AXNT:CMP

BYTE

PTR[SI],0JNZNZINCAXNZ:INC

SILOOP

NT

MOVPARA3,AX

RETZNUMENDP;CSEGENDSEND

ST【例9.7】编写程序,用以统计字节数组中零元素的个数。3)使用堆栈法传递参数在CALL指令前将入口参数压入堆栈,在子程序起始处将入口参数弹出堆栈以便子程序使用,以实现入口参数的传递;在RET指令前将出口参数压入堆栈,在CALL指令后将出口参数弹出堆栈以便调用程序使用。

ZNUMPROCMOV

BP,SP

MOV

CX,[BP+2]

MOV

SI,[BP+4]

XOR

AX,AXNT:CMP

BYTE

PTR[SI],0JNZ

NZINC

AXNZ:INC

SILOOP

NT

MOV

[BP+4],AXRET

2ZNUM

ENDPDSEGSEGMENTARRAYBDB(若干个字节数)COUNT

EQU

$-ARRAYBANS

DW?DSEG

ENDSCSEGSEGMENT……

LEA

SI,ARRAYBMOV

CX,COUNT

PUSH

SI

PUSH

CXCALL

ZNUM

POP

AXMOV

ANS,AX……ZNUMPROCMOV

BP,SP

MOV

CX,[BP+2]

MOV

SI,[BP+4]

XOR

AX,AXNT:CMP

BYTE

PTR[SI],0JNZ

NZINC

AXNZ:INC

SILOOP

NT

MOV

[BP+4],AXRET

2ZNUM

ENDPCSEGENDS三种参数传递方法的比较优点缺点约定寄存器法参数传递快,编程较方便,且节省内存单元寄存器个数很有限,只适用于需传递的参数较少的情况约定存储单元法子程序要处理的数据或送出的处理结果都有独立的存储单元,参数个数相对不受限制参数传递慢且要占用一定数量的存储单元堆栈法参数不占用寄存器,也无需开辟专门的内存单元,而是使用公用的堆栈区参数和子程序的返回地址混在一起,在计算参数在堆栈中的位置时易于失误9.4程序的嵌套和递归

9.4.1子程序的嵌套子程序可以调用另一个子程序,这种调用结构称为子程序的嵌套。

9.4.2子程序的递归

子程序调用本身,或通过调用另一个子程序调用本身的结构称为子程序的递归。前者称为直接递归,后者称为间接递归。这样的子程序称为递归子程序。

在递归子程序设计时必须设置递归结束条件,在每次递归调用中均要对该条件进行判断,递归结束条件不成立则继续递归调用,条件成立则结束递归调用。【例9.11】编写计算N!的程序。

用递归子程序完成这一计算。假设N≤8,即N!不超出两字节无符号数的范围。分析:由阶乘的定义可知:1N=0N!=

N(N-1)!N>0由上式可知,当N>0时,要计算N!就必须计算(N-1)!;要计算(N-1)!就要计算(N-2)!;……要计算1!就要计算0!。【例9.11】编写计算N!的程序。

可以在递归子程序中通过自身调用将N,N-1,…1依次压入堆栈。这里是否已将1压入堆栈就是递归结束条件。一旦递归结束条件满足,则依次将堆栈中的1,2,…N出栈相乘,从而算出N!。FACTPROCPUSH

DXMOV

DX,AXCMP

AX,0JZ

FR;结束递归调用的控制

温馨提示

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

评论

0/150

提交评论