RISC-V基础之函数调用(二)栈与寄存器(包含实例)

堆栈是一种后进先出(LIFO)的队列,用于存储函数调用时的临时数据和现场数据。堆栈指针sp(寄存器2)是一个普通的RISC-V寄存器,按照惯例,指向堆栈的顶部。堆栈从高地址向低地址增长,即当需要更多的临时空间时,堆栈指针sp减小。

函数调用时,如果函数参数和局部变量很多,寄存器放不下,需要开辟堆栈空间存储。中断发生时,堆栈空间用于存放当前执行程序的现场数据(下一条指令地址、各种缓存数据),以便中断结束后恢复现场。开辟和释放堆栈空间的方法是调整堆栈指针sp的值。

函数调用时,为了避免函数修改除了a0之外的其他寄存器的值,造成主程序的寄存器内容被破坏,需要在函数执行前将需要修改的寄存器的值保存到堆栈上,然后在函数返回前将它们从堆栈上恢复。具体的步骤是:

  • 在堆栈上分配空间来存储一个或多个寄存器的值
  • 将寄存器的值存储到堆栈上
  • 执行函数使用寄存器
  • 从堆栈上恢复寄存器的原始值
  • 释放堆栈空间

堆栈通常颠倒存储在存储器中,使得堆栈顶部实际上是最低地址,并且堆栈向下朝向较低存储器地址增长。 这称为降序堆栈。 一些架构还允许向上的堆栈向更高的内存地址增长。 堆栈指针(sp)通常指向堆栈上的最顶层元素; 这称为全栈。 某些体系结构(例如 ARM)还允许空堆栈,其中 sp 指向堆栈顶部之外的一个字。 RISC-V架构定义了函数传递变量和使用堆栈的标准方式,以便不同编译器开发的库可以互操作。 它指定了一个完整的降序堆栈。

 RISC-V指定的降序堆栈如下图所示: 

 

 

 

上图代码示例展示了一个改进的diffofsums函数,它在修改t0,t1和s3寄存器之前将它们保存到堆栈上,并在返回前将它们从堆栈上恢复。这样可以避免破坏调用者的寄存器内容。

下图展示了在调用代码示例中的diffofsums函数之前,期间和之后的堆栈情况。堆栈一开始在0xBEF0F0FC。diffofsums通过将堆栈指针sp减少12来为三个字分配堆栈空间。然后它将t0,t1和s3寄存器中的当前值存储在新分配的空间中。它执行函数的其余部分,改变这三个寄存器的值。在函数结束时,diffofsums从堆栈上恢复这些寄存器的值,释放它的堆栈空间,并返回。当函数返回时,a0保存了结果,但没有其他副作用:t0,t1,s3和sp与函数调用前具有相同的值。

 

一个函数为自己分配的堆栈空间称为它的堆栈帧(stack frame)。diffofsums的堆栈帧有三个字深。模块化原则告诉我们,每个函数只应访问自己的堆栈帧,而不是属于其他函数的帧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/56710.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文字转语音

键盘获取文字,转化为语音后保存本地 from win32com.client import Dispatch from comtypes.client import CreateObject from comtypes.gen import SpeechLib speakerDispatch(SAPI.SpVoice) speaker.Speak(请输入你想转化的文字) datainput(请输入:)#s…

3.01 用户在确认订单页收货地址操作

用户在确认订单页面,可以针对收货地址做如下操作: 1. 查询用户的所有收货地址列表 2. 新增收货地址 3. 删除收货地址 4. 修改收货地址 5. 设置默认地址步骤1:创建对应用户地址BO public class AddressBO {private String addressId;private…

Unity CanvasGroup组件

文章目录 1. 简介2. 组件属性2.1 Alpha(透明度)2.2 Interactable(是否为可交互)2.3 Blocks Raycasts(是否接受射线监测)2.4 Ignore Parent Groups(忽视上层的画布组带来的影响) 1. 简介 CanvasGroup(画布组) 组件,可集中控制整组 UI 元素(自身和所有子物体)的某些属…

设计模式行为型——迭代器模式

什么是迭代器模式 迭代器模式(Iterator Pattern)属于行为型模式,其提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示,即不需要知道集合对象的底层表示。编程环境中非常常用的设计模式。 迭代…

链表——LinkedList类的概述和实现

LinkedList类 1.1LinkedList类概述 LinkedList类底层是基于双向链表结构实现的,不同于ArrayList类和Vector类是基于数组实现的;LinkedList类是非线程安全的;LinkedList类元素允许为null,允许重复元素;LinkedList类插…

《孙子兵法》是世界上最著名的中国著作,不服来看,趣讲《孙子兵法》第1讲

《孙子兵法》是世界上最著名的中国著作,不服来看!趣讲《孙子兵法》【第1讲】 世界上最有名的中国著作肯定是《孙子兵法》。在著名的美国西点军校是必修课。 在企业管理领域,听一些讲座,经常会引用到《孙子兵法》的一些名句&#…

Java-认识String

目录 一、String概念及创建 1.1 String概念 1.2 String的创建 二、String常用方法 2.1 String对象的比较 2.2 字符串查找 2.3 转化 2.4 字符串替换 2.5 字符串拆分 2.6字符串的截取 2.7 其他操作方法 2.8 字符串修改 三、面试题 一、String概念及创建 1.1 String概念 Java中…

Qt能跨多少个平台?Qt能支持多少个平台?

2023年8月5日,周日下午 目录 Qt所支持的平台更多关于Qt支持的信息 Qt所支持的平台 图中显示的平台都支持。 想要更详细的平台支持信息可以查看:Supported Platforms | Qt 5.15 更多关于Qt支持的信息 Qt - 支持的平台及语言

sentinel组件

目录 定义 4.加SentinelResource,blockHander是超过阈值之后执行的函数 5.设置阈值 6.springboot集成sentinel 定义 1.sentinel知道当前流量大小,在浏览器和后端之间加sentinel控制流量,避免大批量的瞬时请求都达到服务上,将服务压垮 2.…

第一天 什么是CSRF ?

✅作者简介:大家好,我是Cisyam,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Cisyam-Shark的博客 💞当前专栏: 每天一个知识点 ✨特色专…

VSCode如何在行内显示变量值

背景 在调试时,我们希望能够直接在代码行显示变量的值,而不是总是去侧边栏查看,如下这种,y12直接显示在代码行。那么VSCode中如何做呢 设置 VSCode提供了“inline values”设置,但为了速度,默认并没有开…

在 React 中渲染大型数据集的 3 种方法

随着 Web 应用程序变得越来越复杂,我们需要找到有效的方法来优化性能和渲染大型数据集。在 React 应用程序中处理大型数据集时,一次呈现所有数据可能会导致性能不佳和加载时间变慢。 虚拟化是一种通过一次仅呈现数据集的一部分来解决此问题的技术&#…