第6章子程序设计.ppt

上传人:豆**** 文档编号:60592781 上传时间:2022-11-17 格式:PPT 页数:45 大小:154.50KB
返回 下载 相关 举报
第6章子程序设计.ppt_第1页
第1页 / 共45页
第6章子程序设计.ppt_第2页
第2页 / 共45页
点击查看更多>>
资源描述

《第6章子程序设计.ppt》由会员分享,可在线阅读,更多相关《第6章子程序设计.ppt(45页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、第6章子程序设计 Still waters run deep.流静水深流静水深,人静心深人静心深 Where there is life,there is hope。有生命必有希望。有生命必有希望6.1 堆栈n供程序使用的一块连续的内存空间;n用于保存和读取一些临时的数据 n堆栈中的数据有以下几个特点:n临时性n快速性n动态扩展性 6.1.1 堆栈空间 n相关的3个寄存器:SS,ESP和EBP n在Windows用户模式下 nSS段寄存器通常和DS,ES段寄存器相等 nESP寄存器中的内容作为堆栈的当前指针。nEBP寄存器中的内容作为堆栈的“基准”指针。6.1.2 进栈和出栈指令 1进栈指令P

2、USH 格式:PUSH SRC功能:堆栈指针ESP减4,SRC保存在ESP指向的堆栈单元中。nSRC可以是32位寄存器、内存操作数、立即数或16位段寄存器。2出栈指令POP 格式:POP DST功能:从ESP指向的堆栈单元中取出数据送到DST中,堆栈指针ESP加4。nDST是32位寄存器、内存操作数或16位段寄存器。n立即数不能作为DST。3PUSH、POP指令要点注意进栈和出栈的顺序入栈:PUSH EAXPUSH EBXPUSH ECXPUSH EDX出栈(与入栈相反)POP EDXPOP ECXPOP EBXPOP EAX 4PUSHFD指令格式:PUSHFD功能:堆栈指针ESP减4,EF

3、LAGS标志寄存器保存在ESP指向的堆栈单元中。举例:将EFLAGS标志寄存器复制到EAX中 PUSHFD POP EAX 5POPFD指令 格式:POPFD功能:从ESP指向的堆栈单元中取出数据送到EFLAGS中,堆栈指针ESP加4。举例:PUSHFD和POPFD可以配对使用,用来保存和恢复程序某一时刻的标志。PUSHFD ;保存状态寄存器 ;执行其他的指令POPFD ;恢复状态寄存器6ENTER指令 格式:ENTER SRC1,SRC2功能:SRC1和SRC2是两个立即数。SRC20时,该指令相当于下面的3条指令 PUSH EBPMOV EBP,ESPSUB ESP,SRC17LEAVE指

4、令格式:LEAVE功能:令ESP等于EBP,再从堆栈弹出EBP。相当于:MOV ESP,EBPPOP EBP常用于子程序返回之前 6.1.3 堆栈的用途1临时保存寄存器的值 PUSH EAXPUSH EBXPUSH ECXPUSH EDXPOP EDXPOP ECXPOP EBXPOP EAX堆栈的用途(续)2临时保存变量的值 PUSH CountPOP Count堆栈的用途(续)3用于变量之间的数据传递将变量Var1的内容传递给Var2:PUSH Var1POP Var2堆栈的用途(续)4交换两个变量Var1和Var2的值PUSH Var1PUSH Var2POP Var2 POP Var1

5、 堆栈的用途(续)5用做临时的数据区6子程序的调用和返回n在调用子程序时,CALL指令自动在堆栈中保存其返回地址 n从子程序返回时,RET指令从堆栈中取出返回地址 6.2 子程序 在编写较复杂的程序时,可以把整个功能分解为若干小的易于实现的子功能。每一个子功能由子程序段来完成。汇编语言中的子程序就是C语言中的函数。6.2.1 子程序的定义和调用伪指令PROC和ENDP用来定义子程序 子程序名 PROC ;表示子程序定义开始 RET子程序名 ENDP ;表示子程序定义结束 n子程序名的命名规则和变量相同 n子程序结束时,用RET指令返回主程序 n在主程序中,使用CALL指令来调用子程序n PRO

6、C后面可跟其他参数 6.2.2 调用和返回指令 1CALL指令格式:CALL SRC功能:调用子程序,入口地址为SRC。SRC可以是:n程序名(标号)n32位寄存器n内存操作数n带段寄存器的远地址 常见的CALL指令的用法nCALL 子程序名nCALL指令后面跟的是寄存器或内存操作数,则将寄存器或内存单元中的值取出来作为入口地址,再调用子程序。nCALL指令后面跟的是带段寄存器的远地址,则由段寄存器来决定CALL指令的操作,可能是n(1)段间调用 n(2)提升特权级 n(3)任务切换 2RET指令格式:RET SRC功能:从子程序返回到主程序RET指令用法:(1)段间返回 n子程序是由另外一个

7、段的CALL指令调用的(2)降低特权级 n从级别较低的特权级调用高特权级的程序 3CALL,RET指令对堆栈的使用 在程序中我们设计了两个子程序:n第1个子程序AddProc1使用ESI和EDI作为 加数,做完加法后把和放在EAX中;n第2个子程序AddProc2使用A和B作为加 数,做完加法后把和放在R中。程序如右:callret.asm 结果:10+20=30 50+60=110 nCALL指令执行时,它首先把返回地址作为一个双字压栈,再进入子程序执行。n子程序最后执行的RET指令从堆栈中取出返回地址,返回到主程序。nCALL指令和RET指令执行是必须依赖于堆栈的。高级语言的函数就是汇编语

8、言的子程序。汇编语言传递参数有3种常用方法:(1)通过寄存器传递;(2)通过数据区内的变量来传递;(3)通过堆栈传递。6.2.3 C语言函数的参数传递方式1cdecl方式cdecl方式是C语言函数的默认方式 调用规则:(1)使用堆栈传递参数。(2)主程序按从右向左的顺序将参数逐个压栈,(3)在子程序中,使用EBP+X的方式来访问参数。(4)子程序用RET指令返回。(5)由主程序执行“ADD ESP,n”指令调整ESP,达到堆栈平衡。(6)子程序的返回值放在EAX中。2stdcall方式 Windows API采用的调用规则是stdcall方式 调用规则:1.使用堆栈传递参数,使用从右向左的顺序

9、将参数入栈。2.堆栈的平衡是由子程序来完成的。n子程序使用“RET n”指令 n子程序的返回值放在EAX中 3fastcall方式调用方式和stdcall类似 调用规则:(1)它使用ECX传递第1个参数,EDX传递第2个参数。(2)其余参数采用从右至左的顺序入栈。(3)由子程序在返回时平衡堆栈。4this方式在C+类的成员函数中使用。它使用ECX传递this指针,即指向对象。调用方式和stdcall类似。5naked方式 想由编程者自行编写函数内的所有代码,就使用naked调用规则。6.2.4 子程序的参数传递方式 汇编语言中,向子程序传递参数可以按照C程序的方式来处理。例如,下面的子程序Ad

10、dProc3采用cdecl方式,AddProc4采用stdcall方式。程序示例:callrule.asm 6.2.5 带参数子程序的调用 注意的两个方面(1)参数转换。子程序中用ebp+8表示第1个参数,用ebp+12表示第2个参数,用ebp+16表示第3个参数,依次类推。(2)平衡堆栈。一种方式是在子程序中用“RET n”平衡堆栈;另一种方式是在主程序中用“ADD ESP,n”平衡堆栈。invoke伪指令1使用invoke伪指令对主程序和子程序的简化 在调用子程序时,使用invoke伪指令,后面跟子程序名和各个参数的取值即可。使用invoke伪指令对前面的callrule.asm进行简化,

11、有以下几点:invoke伪指令(1)子程序的调用规则(2)子程序的参数(3)子程序的进入/退出代码(4)子程序的返回指令(5)主程序中采用invoke语句程序示例:invoke.asm 机器指令列表:invoke2对照invoke.asm和机器指令列表,可以观察到以下几点:(1)自动加入的指令AddProc5,AddProc6中的一些语句是MASM自动加入的(2)参数的替换参数a用EBP+8替换,参数b用EBP+12替换。(3)返回指令AddProc5采用C规则,用“RET”返回;AddProc6采用stdcall规则,用“RET 8”返回(4)invoke语句转换为CALL指令 invoke

12、后面跟的参数被逐一压入堆栈,再跟上一条CALL指令。(5)堆栈平衡n对AddProc5的调用,在CALL指令后面用“ADD ESP,8”来平衡堆栈。n对AddProc6的调用,由于在返回时使用了“RET 8”n在CALL指令后面不需要“ADD ESP,8”invoke伪指令(续)2使用invoke调用子程序的一些限制 invoke伪指令后面跟的参数必须直接能够作为PUSH指令的源操作数。错误的写法:invoke addproc,r*2,30正确的写法:MOV EBX,r SHL EBX,1 invoke addproc,EBX,30 6.2.6 子程序中的局部变量定义:仅在子程序内部使用的变量

13、,可提高程序的模块化程度也被 称为自动变量。局部变量的作用域是子程序1局部变量的实现原理(1)在进入子程序的时候,通过修改堆栈指针ESP来预留出需要的空间。用SUB ESP,x指令预留空间,x为该子程序中所有局部变量使用的空间。(2)返回主程序之前,通过恢复ESP释放空间,在堆栈中不再为子程序的局部变量保留空间。2堆栈帧 包括以下几个部分:n子程序的参数n返回地址n主程序的EBPn子程序的局部变量在子程序中:n由EBP可确定堆栈帧的位置 n由EBP+0可以得到主程序的堆栈帧 3在子程序中使用局部变量local伪指令可以在子程序中定义局部变量格式:local 变量名1重复数量:类型,变量名2重

14、复数量:类型程序示例:local.asm 结果:r=20 s=10 4直接使用局部空间 如果不使用local伪指令,可以直接在堆栈中为子程序分配局部变量空间,但不如用local伪指令方便。5ADDR伪操作符 ADDR伪操作符可以取出局部变量的地址格式:ADDR 局部变量ADDR只能在invoke语句中使用 程序示例:addr.asm结果:r=50 s=406.2.7 子程序的嵌套程序中同样可以调用其他子程序,构成子程序的嵌套。n嵌套深度没有一个具体的限制,主要取决于堆栈的容量。n子程序调用时,返回地址要保存在堆栈中n子程序中的局部变量也要在堆栈中分配。6.2.8 子程序的递归 子程序自己调用自己的情况称做递归。以计算xn为例来说明递归子程序的写法:C语言程序:recurse.c 汇编程序:recurse.asm 结果:x=3 n=5 x(n)=2436.3 Windows API API在实质上也是一个子程序,主要有:1printf2scanf3MessageBox4确定函数的声明语句和库文件5MASM32工具包

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 小学资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁