MIPS架构上函数调用过程的堆栈和栈帧
转载于CSDN:http://blog.csdn.net/do2jiang/article/details/5404566
在计算机科学中,Call stack是指存放某个程序的正在运行的函数的信息的栈。Call stack和stack frames组成,每个stack frame对应于一个未完成运行的函数。
在当今流行的计算机体系架构中,大部分计算机的参数传递,局部变量的分配和释放都是通过操纵程序栈来实现的。栈用来传递函数参数,存储返回值信息,保存寄存器以供恢复调用前处理机状态。每次调用一个函数,都要为该次调用的函数实例分配栈空间。为单个函数分配的那部分栈空间就叫做stack frame,也就是说,stack frame这个说法主要是为了描述函数调用关系的。
Stack frame组织方式的重要性和作用体现在两个方面:
第一:它使调用者和被调用者达成某种约定。这个约定定义了函数调用时函数参数的传递方式,函数返回值的返回方式,寄存器如何在调用者和被调用者之间进行共享。
第二:它定义了被调用者如何使用它自己的stack frame来完成局部变量的存储和使用。

- 上图描述的是一种典型的(MIPS 32)嵌入式芯片的stack frame组织方式。
- 这张图中,计算机的栈空间采用的是向下增长的方式。
- sp(stack pointer)就是当前函数的栈指针,它指向的是栈底的位置。
- Current Frame所示即为当前函数(被调用者)的frame。
- Caller's Frame是当前函数的调用者的frame。
- 每个frame中所存放的内容和存放顺序,则由目标体系架构的调用约定(calling convention)定义。
- MIPS O32调用约定规定了所占空间不大于4个比特的参数应该放在从$4到$8的寄存器中,剩下的参数应该依次放到调用者stack frame的参数域中,并且在参数域中需要前四个参数保留栈空间。
- 如果被调用者需要使用$16到$23这些保留寄存器(saved register),就必须先将这些保留寄存器的值保存在被调用者stack frame的保留寄存器域中,当被调用者返回时恢复这些寄存器值。
- 当被调用者不是叶子函数时,即被调用者中存在对其它函数的调用,需要将RA(return address)寄存器($31)值保存到被调用者stack frame的返回值域中。
- 被调用者所需要的局部变量,应保存在被调用者stack frame的本地变量域中。
- 在没有BP(base pointer)寄存器的目标架构中,进入一个函数时需要将当前栈指针向下移动n比特,这个大小为n比特的存储空间就是此函数的stack frame的存储区域。此后栈指针便不再移动,智能在函数返回时再将栈指针上这个偏移量恢复栈现场。由于不能随便移动栈指针,所以寄存器压栈和出栈都必须指定偏移量。
- 在RISC计算机中主要参与计算的是寄存器,saved registers就是指在进入一个函数后,如果某个保存原函数信息的寄存器会在当前函数中被使用,就应该将此寄存器保存到堆栈上,当函数返回恢复此寄存器值。而且由于RISC计算机大部分采用定长指令或者定变长指令,一般指令长度不会超过32个位。而现代计算机的内存地址范围已经扩展到32位,这样在一条指令里就不足以包含有效的内存地址,所以RISC计算机一般借助于一个返回地址寄存器RA来实现函数的返回。几乎在每个函数调用中都会使用到这个寄存器,所以在很多情况下RA寄存器会被保存在堆栈上以避免被后面的函数调用修改,当函数需要返回时,从堆栈上取回RA然后跳转。移动SP和保存寄存器的动作一般处在函数的开头,叫做function prologue;恢复这些寄存器状态的动作一般放在函数的最后,叫做fuction epilogue。
MIPS架构上函数调用过程的堆栈和栈帧的更多相关文章
- c函数调用过程原理及函数栈帧分析
转载自地址:http://blog.csdn.net/zsy2020314/article/details/9429707 今天突然想分析一下函数在相互调用过程中栈帧的变化,还是想尽量以比 ...
- C函数调用过程原理及函数栈帧分析(转)
在x86的计算机系统中,内存空间中的栈主要用于保存函数的参数,返回值,返回地址,本地变量等.一切的函数调用都要将不同的数据.地址压入或者弹出栈.因此,为了更好地理解函数的调用,我们需要先来看看栈是怎么 ...
- 在C语言中函数及其调用过程
目录 函数 C语言中的变参函数 函数的本质是什么 内存区域的区分技巧 函数的调用过程 栈帧的概念 调用过程细节 按照约定传参 函数 如果一个函数有声明没实现,那么就会出现链接错误: 以上代码会出现链接 ...
- 第5篇-调用Java方法后弹出栈帧及处理返回结果
在前一篇 第4篇-JVM终于开始调用Java主类的main()方法啦 介绍了通过callq调用entry point,不过我们并没有看完generate_call_stub()函数的实现.接下来在ge ...
- Dubbo学习(六) dubbo 架构图 以及调用过程
一.Dubbo结构图 duubo结构图 我们解释以下这个架构图:Consumer服务消费者,Provider服务提供者.Container服务容器.消费当然是invoke提供者了,invoke这条 ...
- 代码 or 指令,浅析ARM架构下的函数的调用过程
摘要:linux程序运行的状态以及如何推导调用栈. 1.背景知识 1.ARM64寄存器介绍: 2.STP指令详解(ARMV8手册): 我们先看一下指令格式(64bit),以及指令对于寄存机执行结果的影 ...
- MIPS指令 MIPS架构
华中科技大学 - 计算机组成原理 华中科技大学 - 计算机硬件系统设计 Microprocessor without Interlocked Pipleline Stages 无内部互锁流水级的微处理 ...
- 如何在linux主机上运行/调试 arm/mips架构的binary
如何在linux主机上运行/调试 arm/mips架构的binary 原文链接M4x@10.0.0.55 本文中用于展示的binary分别来自Jarvis OJ上pwn的add,typo两道题 写这篇 ...
- Hbase的WAL在RegionServer基本调用过程
版权声明:本文由熊训德原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/221 来源:腾云阁 https://www.qclo ...
随机推荐
- Jquery ajax ajaxStart()和ajaxStop()加载前的优雅表现
Jquery中当一个Ajax请求启动时,并且没有其他未完成的Ajax请求时,将调用ajaxStart()方法.同样,ajaxStop()方法则是在所有Ajax请求都完成时调用.这些方法的参数都是一个函 ...
- 无法获得锁 /var/lib/dpkg/lock
sudo rm /var/cache/apt/archives/lock sudo rm /var/lib/dpkg/lock
- python 授权
1.“包装”意思是一个已经存在的对象进行包装,不管他是数据类型还是一段代码,可以是对一个已经存在的对象增加新的,删除不要的或者修改其他已经存在的功能 2.包装 包括定义一个类,他的实例拥有标准类型的核 ...
- RSS & Server-Sent Events & HTML5 Notification API
RSS Rich Site Summary https://en.wikipedia.org/wiki/RSS https://www.lifewire.com/what-is-rss-2483592 ...
- DTD举例二
DTD举例二: <!--hbase语句库约束文件--> <!DOCTYPE hbaseGroup [ <!ELEMENT hbaseGroup (statements*)> ...
- Lodop导出图片,导出单页内容的图片
用如下语句设置图片的格式,设置导出的图片初识的默认名称,Lodop可以把打印内容导出成图片. LODOP.SET_SAVE_MODE("SAVEAS_IMGFILE_EXENAME" ...
- Bootstrap按钮式下拉菜单
前面的话 按钮式下拉菜单仅从外观上看,和下拉菜单效果基本上是一样的.不同的是普通的下拉菜单是block元素,而按钮式下拉菜单是inline-block元素.本文将详细介绍Bootstrap按钮式下拉菜 ...
- C从源码到运行发生了哪些事
一个C/C++程序从源代码到可执行程序主要经历了四个阶段: ①预处理.包括展开宏.处理#include,#if,#ifdef等指令.删除注释.还有一些其他操作.相关命令:gcc -E或cpp ②编译. ...
- [代码]--C#action和func的使用
以前我都是通过定义一个delegate来写委托的,但是最近看一些外国人写的源码都是用action和func方式来写,当时感觉对这很陌生所以看起源码也觉得陌生,所以我就花费时间来学习下这两种方式,然后发 ...
- Django model 中的字段解释
Django 通过 models 实现数据库的创建.修改.删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField:一个自动递增的整型字段,添加记录时它会自动增长.你通常不需 ...