汇编第5章-子程序设计

上传人:tian****1990 文档编号:72584104 上传时间:2019-01-23 格式:PPT 页数:184 大小:2.05MB
返回 下载 相关 举报
汇编第5章-子程序设计_第1页
第1页 / 共184页
汇编第5章-子程序设计_第2页
第2页 / 共184页
汇编第5章-子程序设计_第3页
第3页 / 共184页
汇编第5章-子程序设计_第4页
第4页 / 共184页
汇编第5章-子程序设计_第5页
第5页 / 共184页
点击查看更多>>
资源描述

《汇编第5章-子程序设计》由会员分享,可在线阅读,更多相关《汇编第5章-子程序设计(184页珍藏版)》请在金锄头文库上搜索。

1、子程序设计,第五章,在汇编语言中,子程序又称为过程,是程序设计中的一种重要方法。在实际的程序中,常常会遇到在同一程序或多个程序中多次遇到同一任务的处理过程。如果每一次处理都编写一次程序,不仅加大了编程人员的工作量,也浪费存储空间。,为了避免重复编程,人们将经常遇到的处理任务编写成一些独立的程序段,以供其他程序调用,这就是子程序设计。为了能更好地把握子程序的编写和使用方法,必须先掌握堆栈的有关概念。,5.1 堆栈,5.2 子程序的调用与返回,5.3 子程序设计,5.4 子程序设计案例,习 题 5,5.1 堆栈,在汇编语言和机器语言中,堆栈在物理结构上是一段存放数据的连续的内存区域,以及一个称为栈

2、顶指针的专用存储单元。,堆栈中只能存入16位的字型数据,存入数据的操作称为“进栈”或“压栈”,已存入的数据也可以取出,称为“出栈”或“弹出”,数据的存取操作由专用指令完成。 从逻辑上说,堆栈是一种按“先进后出”或“后进先出”原则进行操作的数据结构,栈顶指针用于指出入栈操作和出栈操作的位置。,5.1.1 建立堆栈,图5-1是堆栈的物理结构示意图. 图中标出的SS和SP是与堆栈密切相关的寄存器,SS存放堆栈所占用内存区域的段地址,SP所指向的位置称为栈顶。,图5-1 堆栈的逻辑结构图,一个程序如果要使用堆栈,首先要建立堆栈。建立堆栈实际上就是在程序中定义一个堆栈段,并给SS和SP赋值即可。 定义堆

3、栈段的格式如下: 段名 SEGMENT STACK DW n DUP(?) 段名 ENDS,【说明】 (1)保留字STACK是堆栈段的专用符号,SEGMENT后面的保留字STACK表明这个段专供堆栈使用。 (2)段定义中用“DW n DUP(?)”说明堆栈所用内存区的大小为2n字节,其中n是一个常量。可根据程序需要,调节堆栈段的大小。因为堆栈只能存放字型数据,所以习惯上都是用DW伪指令来定义栈的大小。这不并是说用其它伪指令不行。,(3)按基本格式定义的栈是一个空栈,栈中没有存放有效数据。 (4)为了使SS和SP在程序执行时取得正确的值,必须在源程序中写一条伪指令: ASSUME SS:堆栈段段

4、名,但不需要像DS和ES一样在程序中用指令进行赋值。对SS和SP的赋值是由操作系统在把执行程序调入内存时由DOS本身完成的,DOS将把SS赋值为堆栈段的段地址,把SP赋值为2n,这时用户使用的就是系统堆栈。 当然,用户也可以根据程序的需要按自己的要求定义自己的堆栈,这时,用户不仅要定义堆栈段,而且还要用指令给SS和SP赋值。,5.1.2 堆栈操作指令,栈操作指令以它特有的方式存取数据,属于数据传送类指令,但又与MOV等指令有很大的区别。 1.进栈指令 【指令格式】PUSH S 【功能】先把SP的值减去2,然后把操作数S指明的字型数据放入以SS为段地址、SP为偏移地址所对应的字内存单元中。,【说

5、明】 (1)这是单操作数指令,操作数S可以是包括段寄存器在内的任何字型寄存器,或者内存型寻址方式,但不能是立即寻址。 (2)PUSH指令的功能包括移动栈顶和存入数据两部分,两部分连续完成,密不可分。,(3)操作数S进栈是以减2以后的SP的值作为偏移地址,但程序中不允许出现SP的写法。不要与基地址寄存器或变址寄存器用作偏移地址时的写法相混淆,也就是说,把PUSH指令理解成下面两条指令的组合是不正确的: SUB SP, 2 MOV SP, S 因为指令“MOV SP, S”存在语法错误。,(4)PUSH指令会导致栈顶指针的移动,如果用PUSH指令把很多数据进栈,使SP不断减2,就有可能超出栈的有效

6、范围。在一些高级语言中这种现象会导致堆栈溢出错误,但8086对此并不做任何检测和警告。因此要求编程人员自己注意控制堆栈的大小,估计可能进栈的数据量,以免由于栈溢出导致一些不可预测的后果。,假设:SS=3000H,SP=0200H, AX=1234H, 则CPU执行PUSH AX指令后: SS的内容不变,SP=01FEH,栈顶字单元(301FEH)= 1234H,AX的内容不变。,2出栈指令 【指令格式】POP D 【功能】从SS为段地址、SP为偏移地址的栈顶单元中取出一个字型数据,送到操作数D指定的位置,然后把SP的值加2。对操作数D的寻址方式要求与PUSH指令相同。,堆栈通常用于临时保存数据

7、。一般做法是先用PUSH指令把需要保存的数据入栈,然后完成一定的指令序列,再用POP指令把原先保存的数据出栈。 用堆栈保存数据的特点是不用定义变量,不必关心被保存的数据到底在栈的什么位置,只要保证出栈和进栈的对应关系即可。当CPU中的寄存器不够使用时经常用堆栈临时保存数据。,假设:SS=3000H,SP=0200H,栈顶单元的数据为1234H,即(30200H)=1234H,则CPU执行POP AX指令后,SS的内容不变,SP=0202H,AX=1234H。 栈顶所指位置以上的部分是堆栈的空闲区,以下部分是已入栈的数据存放区(见图5-1),例5-1用来说明PUSH指令和POP指令对堆栈的影响。

8、,【例5-1】设AX1234H,BX56578H,SP1000H,分别逐条执行下列指令,用内存图的形式画出堆栈的变化情况,并分析程序段执行完后AX和BX寄存器的值。 PUSH AX PUSH BX POP AX POP BX,【解】堆栈变化见图5-2,程序段执行完后AX5678H,BX1234H。,(a)执行前,(b)执行PUSH AX 后,(c)执行 PUSH BX 后,(d)执行 POP AX 后,(e)执行 POP BX 后,图5-2 执行PUSH 和POP 指令前后堆栈的变化情况,3.标志寄存器入出栈指令 (1)标志寄存器入栈指令 【指令格式】PUSHF 【功能】把SP的值减2,并把1

9、6位的标志寄存器的内容送入SS:SP所指向的内存字单元,即把标志寄存器的值入栈。,(2)标志寄存器出栈指令 【指令格式】POPF 【功能】把栈顶的一个16位的字型数据从堆栈中弹出,然后送入标志寄存器,并把SP的值加2。,这两条指令相互配合可以设置标志寄存器中的任意一个标志位,一般的做法是: PUSHF POP AX ;按标志位的分布情况和实际需要,修改AX中的值 PUSH AX POPF,5.2 子程序的调用与返回,把可以多次调用、能够完成特定处理任务的程序段编写成独立的程序模块,称为子程序。 子程序可以被其他程序调用,调用这些子程序的程序称为主程序。,在主程序中,如果调用子程序,就把控制转移

10、到子程序,这个过程称为转子;子程序执行完后,再把控制返回到主程序,这个过程称为返主。 主程序与子程序之间的转换关系如图5-3所示。,图5-3 主程序和子程序间的转换关系,为了实现主程序调用子程序以及子程序执行完后能返回主程序,在8086/8088指令系统中提供了一组调用指令CALL和返回指令RET,5.2.1 子程序调用指令CALL,主程序调用子程序需要通过调用指令来实现。 调用指令的基本功能是将返回地址,即调用指令的下一条指令的偏移地址或下一条指令的段地址和偏移地址(简称为断点)压入堆栈,并按照某种寻址方式转向子程序的入口。,主程序和子程序可以在同一个代码段中,也可以在不同的代码段中。前者称

11、为段内调用,只涉及偏移地址,后者称为段间调用,将涉及段地址和偏移地址两部分。,段内调用指令的基本功能是:将断点地址,即当前的IP值压入堆栈,段寄存器CS的内容保持不变。然后将子程序的入口地址(即偏移地址)装入IP中。段间调用指令执行时,其断点地址及子程序的入口地址包括段地址和偏移地址。,子程序入口地址直接出现在调用指令中(用子程序名表示),称为直接调用;子程序入口地址存放在寄存器或存储单元中,而寄存器名或存储单元的地址出现在调用指令中,称为间接调用。,1.段内直接调用 【指令格式】 CALL DST 或:CALL NEAR PTR DST ;DST为子程序名或语句标号,执行操作: (SP)(S

12、P)2; 即修改堆栈指针; (SP+1),(SP) (IP); IP(断点)入栈; (IP) (IP)+16 位偏移量; 转向子程序入口。,说明: 该指令的第一步是把子程序的返回地址(即CALL指令的下一条指令地址)压入堆栈中,第二步是转移到子程序的入口地址,执行该子程序。,指令中的DST为子程序的入口地址,16位偏移量是子程序入口地址与CALL指令的下一条指令地址之间的差值,所以这种调用也称为相对调用。,【例5-2】 指令CALL SUB1 SUB1为子程序名,即过程名或语句标号,且子程序SUB1被定义为段内标号或近过程名,则CALL SUB1就是段内直接调用。,若假设指令CALL SUB1

13、的第一个字节的地址为2000H:1000H,段内直接调用指令为三字节,因此其返回地址是2000H:1003H。再设子程序SUB1的入口地址为2000H:3000H,那么,该指令执行后,堆栈、IP和CS的内容如图5-4所示。,图5-4 段内直接调用示意图,2.段内间接调用 【指令格式】 CALL DST 或:CALL WORD PTR DST ;DST为通用字寄存器或字存储单元,执行操作: 1.(SP)(SP) 2 ;修改堆栈指针 2.(SP+1),(SP) (IP) ;IP入栈 3.(IP) (DST) ;转向子程序,说明: 该指令与段内直接调用类似,区别是将字寄存器或存储单元内容作为子程序入

14、口地址送入IP。,【例5-3】下面三种情况均是段内间接调用。 CALL BX CALL WORD PTR BX CALL ES:WORD PTR SUB2,3.段间直接调用 【指令格式】 CALL FAR PTR DST ;DST为子程序名或语句标号,执行操作: 1.段点入栈: (SP)(SP) 2 (SP+1),(SP) (CS) ;(CS)入栈; (SP) (SP) 2 (SP+1),(SP) (IP) ;(IP)入栈;,2.子程序入口地址送IP和CS,转入子程序: (IP) 偏移地址 ;IP由指令中的偏移地址取代; (CS) 段地址 ;CS由指令中的段地址取代.,说明:该指令的操作与段内

15、直接调用指令基本类似,不同的只是: 其一,调用时不仅要保护偏移地址,而且要保护段地址,它们的顺序是CS先压栈,然后再把IP压栈; 其二,CS和IP的值,是直接将子程序入口的段地址和偏移地址送入CS和IP中。,【例5-4】指令CALL FAR PTR SUB2 SUB2是子程序名,且过程SUB2与调用指令不在同一个代码段,即段间直接调用 若设该指令的第一个字节的地址为2000H:0200H,段间直接调用指令为五字节,因此,其返回地址为2000H:0205H。再设子程序SUB2的入口地址为4000H:0100H,那么,该指令执行后,堆栈、IP和CS的内容如图5-5所示。,图5-5 段间直接调用示意

16、图,4.段间间接调用 【指令格式】 CALL DWORD PTR DST ;DST为双字存储器单元操作数,执行操作: 1.段点入栈: (SP)(SP) 2 (SP+1),(SP) (CS);CS入栈 (SP) (SP) 2 (SP+1),(SP) (IP);IP入栈,2.子程序入口地址送IP和CS,转入子程序: (IP) (EA) ;指令中的有效地址所指字内容送入IP; (S) (EA+2) ;指令中的有效地址+2所指字内容送入CS.,说明: 该指令的操作与段间直接调用指令基本类似。不同的是根据寻址方式求出EA后,把指定存储器单元的字内容送到IP寄存器,再把下一个字的内容送到CS寄存器。,【例5-5】 下面指令都是段间间接调用。 CALL DWORD PTR BX CALL DWORD PTR SADR 上面两条指令的操作数均为双字存储器类型。其中第一指令是由BX的内容指定数据段中的一个双

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号