上一题下一题
跳转到
 
 
  世界如此多姿,发展如此迅速,窥一斑未必还能知全豹。但正如万花筒一样,每一个管窥都色彩斑斓。  
 
 
  知识通道 | 学习首页 | 教师首页 | PK首页 | 知识创造首页 | 企业首页 | 登录
 
本文对应知识领域
子程序的调用和返回指令
作者:未知 申领版权
2010年12月12日 共有 1770 次访问 【添加到收藏夹】 【我要附加题目
受欢迎度:

    子程序的调用和返回指令
    子程序的调用和返回是一对互逆操作,也是一种特殊的转移操作。
    一方面,之所以说是转移,是因为当调用一个子程序时,程序的执行顺序被改变,CPU将转而执行子程序中的指令序列,在这方面,调用子程序的操作含有转移指令的功能,子程序的返回指令的转移特性与此类似;
    另一方面,转移指令是一种“一去不复返”的操作,而当子程序完后,还要求CPU能转而执行调用指令之下的指令,它是一种“有去有回”的操作。
    为了满足子程序调用和返回操作的特殊性,在指令系统中设置了相应的特定指令。
    7.2.1 调用指令(CALL)
    调用子程序指令的格式如下:
    CALL  子程序名/Reg/Mem
    子程序的调用指令分为近(near)调用和远(far)调用。如果被调用子程序的属性是近的,那么,CALL指令将产生一个近调用,它把该指令之后地址的偏移量(用一个字来表示的)压栈,把被调用子程序入口地址的偏移量送给指令指针寄存器IP即可实现执行程序的转移。近调用指令的堆栈操作如图7.1所示。
    
    
    如果被调用子程序的属性是远的,那么,CALL指令将产生一个远调用。这时,调用指令不仅要把该指令之后地址的偏移量压进栈,而且也要把段寄存器CS的值压进栈。在此之后,再把被调用子程序入口地址的偏移量和段值分别送给IP和CS,这样完成了子程序的远调用操作。远调用指令的堆栈操作如图7.2所示。
    
    
    子程序调用指令本身的执行不影响任何标志位,但子程序体中指令的执行会改变标志位,所以,如果希望子程序的执行不能改变调用指令前后的标志位,那么,就要在子程序的开始处保护标志位,在子程序的返回前恢复标志位。
    
    

例如:
    
CALL  DISPLAY
    
;DISPLAY是子程序名
    
CALL  BX
    
;BX的内容是子程序的偏移量
    
CALL  WORD1
    
;WORD1是内存字变量,其值是子程序的偏移量
    
CALL  DWORD1
    
;DWORD1是双字变量,其值是子程序的偏移量和段值
    
CALL  word ptr [BX]
    
;BX所指内存字单元的值是子程序的偏移量
    
CALL  dword ptr [BX]
    
;BX所指内存双字单元的值是子程序的偏移量和段值
    

 
    7.2.2 返回指令(RET)
    当子程序执行完时,需要返回到调用它的程序之中。为实现此功能,指令系统提供了一条专用的返回指令。其格式如下:
    RET/RETN/RETF [Imm]
    子程序的返回在功能上是子程序调用的逆操作。为了与子程序的远、近调用相对应,子程序的返回也分:远返回和近返回。返回指令在堆栈操作方面是调用指令的逆过程(如图7.3所示)。其具体规定如下:
    
    

、在近类型的子程序中,返回指令RET是近返回,其功能是把栈顶之值弹出到指令指针寄存器IP中,SP会被加2(如图7.3所示);
    
、在远类型的子程序中,返回指令RET是远返回,其功能是:先弹出栈顶之值到IP中,再弹出栈顶之值到CS之中,SP总共会被加4(如图7.4所示)。
    

 
    
    如果返回指令后面带有立即数(其值通常为偶数),则表示在得到返回地址之后,SP还要增加的偏移量,它不是类似于高级语言中子程序的返回值(如图7.5所示)。 
    
    
    在MASM 5.0及其以后版本中,可用指令RETN或RETF来显式地告诉汇编程序是本子程序的返回是近返回,还是远返回。
    
    

例如:
    
RET
    
;可能是近返回,也可能是远返回
    
RETN
    
;近返回指令
    
RETF
    
;远返回指令
    
RET  6
    
;子程序返回后,(SP)←(SP)   6
    

 
    例7.1 编写一个子程序UPPER,实现把寄存器AL中存放的字符变大写。
    
    

解:
    
 
    
;子程序功能:把AL中存放的字符变大写
    
;入口参数:AL
    
;出口参数:AL
    
;算法描述:判断AL中字符必须在'a'~'z'之间才能把该字符变为大写
    
UPPER
    
PROC
    
CMP
    
AL, 'a'
    
;书写'a'的ASCII码61H也可以
    
JB
    
over
    
CMP
    
AL, 'z'
    
JA 
    
over
    
SUB
    
AL, 20H
    
;书写指令AND AL, 0DFH也可以
    
over:
    
RET
    
UPPER
    
ENDP
    

例7.2 编写一个求字符串长度的子程序StrLen,该字符串以0为结束标志,其首地址存放在DS:DX,其长度保存在CX中返回。
    
    

解:
    
 
    
;子程序功能:求字符串的长度
    
;入口参数:DS:DX存放字符串的首地址,该字符串以0为结束标志
    
;出口参数:CX存放该字符串的长度
    
;算法描述:用BX来指针来扫描字符串中的字符,如果遇到其结束标志,则停止扫描字符串操作
    
StrLen
    
PROC
    
PUSH
    
AX
    
PUSH
    
BX
    
;用堆栈来保存子程序所用到的寄存器内容
    
XOR
    
CX, CX
    
XOR
    
AL, AL
    
MOV
    
BX, DX
    
again:
    
CMP
    
[BX], AL
    
JZ
    
over
    
INC
    
CX
    
;增加字符串的长度
    
INC
    
BX
    
;访问字符串的指针向后移
    
JMP
    
again
    
over:
    
POP
    
BX
    
;恢复在子程序开始时所保存的寄存器内容
    
POP
    
AX
    
RET
    
StrLen
    
ENDP
    

 
    
    7.3 子程序的参数传递
    子程序一般都是完成某种特定功能的程序段。当一个程序调用一个子程序时,通常都向子程序传递若干个数据让它来处理;当子程序处理完后,一般也向调用它的程序传递处理结果,我们称这种在调用程序和子程序之间的信息传递为参数传递。
    用程序向子程序传递的参数称为子程序的入口参数,子程序向调用它的程序传递的参数称为子程序的出口参数。子程序的入口参数和出口参数都是任意项,对某个具体的子程序来说,要根据具体情况来确定其入口和出口参数,也可以二者都没有。
    程序和被调用子程 序之间的参数传递方法是程序员自己或和别人事先约定好的信息传递方法。这种信息传递方法可以是多种多样的,在本节,我们只介绍常用的、行之有效的参数传递 方法有:寄存器传递参数、约定存储单元传递参数和堆栈传递参数等。如果对其它的参数传递方法感兴趣的话,可参考其它《汇编语言程序设计》书籍。
    7.3.1 寄存器传递参数
    一方面,由于 CPU中的寄存器在任何程序中都是“可见”的,一个程序对某寄存器赋值后,在另一个程序中就能直接使用,所以,用寄存器来传递参数最直接、简便,也是最常 用的参数传递方式。但另一方面,CPU中寄存器的个数和容量都是非常有限,所以,该方法适用于传递较少的参数信息。
    例7.1是用寄存器传递参数的例子,子程序处理的数据被保存在寄存器AL中。假设有下列的程序段:
    例7.3 按五位十进制的形式显示寄存器BX中的内容,如果BX的值小于0,则应在显示数值之前显示负号'-'。
    例如:(BX)=123,显示:00123;(BX)=-234,显示:-00234;
    
    

 
    

    
MOV
    
AL, 'b'
    
CALL
    
UPPER
    
;子返回时,(AL)='B'
    

    
MOV
    
AL, '2'
    
CALL
    
UPPER
    
;子返回时,AL的值不变,因为'2'不是字母
    

    
解:
    
 
    
;子程序功能:把寄存器BX的内容按十进制有符号数显示出来
    
;入口参数:BX
    
;出口参数:无,只有显示信息
    
;算法描述:
    
1、定义6个字节的存储单元
    2、先判断BX是否小于零,如果是,则先显示负号'-',再取BX的绝对值;
    3、采用除10,得余数的方法,从低位向高位求出每位十进制位;
    4、输出数据的字符串。
    
SubData
    
SEGMENT
    
DB
    
 5 DUP('0'), 0ah, 0dh, '$'        ;0ah、0dh:换行、回车
    
SubData
    
ENDS
    
DISPBX
    
PROC
    
ASSUME
    
DS:SubData
    
PUSH
    
DS
    
PUSH
    
DX
    
PUSH
    
CX
    
PUSH
    
AX
    
MOV
    
AX, SubData
    
;取子程序所用的数据区段地址
    
MOV
    
DS, AX
    
CMP
    
BX, 0
    
JGE
    
next
    
MOV
    
DL, '-'
    
MOV
    
AH, 2
    
INT
    
21H
    
;显示负号'-'
    
NEG
    
BX
    
;求-BX,使其值为正数
    
next:
    
MOV
    
SI, 4
    
MOV
    
AX, BX
    
MOV
    
CX, 10D
    
again:
    
XOR
    
DX, DX
    
IDIV
    
CX
    
;DX存放余数,AX存放商
    
ADD
    
DL, '0'
    
MOV
    
[SI], DL
    
DEC
    
SI
    
JGE
    
again
    
XOR
    
DX, DX
    
MOV
    
AH, 9
    
INT
    
21H
    
;调用中断21的功能9,显示DS:DX指向的字符串
    
POP
    
AX
    
POP
    
CX
    
POP
    
DX
    
POP
    
DS
    
RET
    
DISPBX
    
ENDP
    

 

相关新闻

testtest
上善制度的炼成
新时代呼唤管理理论创新——大卫�梯斯与动态能力理论
创业的不变逻辑
创新管理需要回答的5个问题
十一、弥离
十、转院
九、生机
八、传染
七、求血

您可能对这些感兴趣  

干货分享|10本最受国外孩子喜爱的英文词典——上
从孩子的表现看父母的缺点!请家长对号入座,看看你是哪一类?
20条制作PPT的视觉原则
培训简史:培训者必知的历史轨迹
广田丰管理培训生人才培养调查报告
第4讲 作为上司的职业经理
第3讲 作为同事的职业经理
第2讲 作为下属的职业经理
第1讲 培养经理人的管理素养
酒店前台新员工上岗培训计划

题目筛选器
日期:
类型:
状态:
得分: <=
分类:
作者:
职业:
关键字:
搜索

 
 
 
  焦点事件
 
  知识体系
 
  职业列表
 
 
  最热文章
 
 
  最多引用文章
 
 
  最新文章
 
 
 
 
网站介绍 | 广告服务 | 招聘信息 | 保护隐私权 | 免责条款 | 法律顾问 | 意见反馈
版权所有 不得转载
沪ICP备 10203777 号 联系电话:021-54428255
  帮助提示    
《我的太学》是一种全新的应用,您在操作中遇到疑问或者问题,请拨打电话13564659895,15921448526。
《我的太学》