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 ...
随机推荐
- 怎样让DBGrid在按住Shift点鼠标的同时能将连续范围的多行选中?
参见例子:…privateSel : Boolean ;//判断是否处于选择状态BookMark : TBookMark ;//记录先前的位置…procedure TForm1.DBGrid1Mous ...
- BZOJ3996[TJOI2015]线性代数——最小割
题目描述 给出一个N*N的矩阵B和一个1*N的矩阵C.求出一个1*N的01矩阵A.使得 D=(A*B-C)*A^T最大.其中A^T为A的转置.输出D 输入 第一行输入一个整数N,接下来N行输入B矩阵, ...
- java常见面试题及答案
java常见面试题及答案 来源 https://blog.csdn.net/hsk256/article/details/49052293 来源 https://blog.csdn.net/hsk25 ...
- python3网络爬虫(2.1):爬取堆糖美女
额,明明记得昨晚存了草稿箱,一觉醒来没了,那就简写点(其实是具体怎么解释我也不太懂/xk,纯属个人理解,有错误还望指正) 环境: 版本:python3 IDE:pycharm2017.3.3 浏览器: ...
- Leetcode 242.有效的字母异位词 By Python
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词. 示例 1: 输入: s = "anagram", t = "nagaram" ...
- NOIP2018退役记
退役失败*1. md可能只有一次啊.
- 【BZOJ1818】[CQOI2010]内部白点(树状数组,扫描线)
[BZOJ1818][CQOI2010]内部白点(树状数组,扫描线) 题面 BZOJ 题解 不难发现\(-1\)就是在搞笑的. 那么对于每一行,我们显然可以处理出来最左和最右的点,那么等价于我们在横着 ...
- [并查集+LCA USACO18OPEN ] Disruption
https://www.luogu.org/problemnew/show/P4374 一看这道题就是一个妙题,然后题解什么树链剖分...珂朵莉树... 还不如并查集来的实在!我们知道并查集本来就是路 ...
- 学习2__STM32--汉字显示
汉字显示操作流程 第一,进入主函数 int main(void) { u32 fontcnt; u8 i,j; u8 fontx[];//gbk码 u8 key,t; delay_init(); // ...
- install kubernetes cluster k8s集群安装
一,安装docker-ce 17.031,下载rpm包 Wget -P /tmp https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/ ...