当前位置: 首页 > news >正文

官方网站入口辽宁阜新建设学校官方网站

官方网站入口,辽宁阜新建设学校官方网站,韩国有哪些专业做汽车的网站?,图片设计素材首先先解释一下栈在函数调用中的作用#xff0c;更详细的部分请参照考研复习之数据结构笔记#xff08;五#xff09;栈和队列#xff08;上#xff09;#xff08;包含栈的相关内容#xff09;_管二狗赶快去工作#xff01;的博客-CSDN博客 函数嵌套调用栈的作用是用…首先先解释一下栈在函数调用中的作用更详细的部分请参照考研复习之数据结构笔记五栈和队列上包含栈的相关内容_管二狗赶快去工作的博客-CSDN博客 函数嵌套调用栈的作用是用来保存和恢复函数调用过程中的相关信息如参数、局部变量、返回地址、上下文等。这些信息可以帮助函数在执行完毕后返回到正确的位置以及在发生异常时恢复到合理的状态。函数嵌套调用栈的具体结构和操作取决于编译器、操作系统和体系结构的设计但一般来说它遵循以下原则 当一个函数被调用时它会在栈顶分配一段空间称为栈帧stack frame。栈帧中存放了该函数的参数、局部变量、返回地址、上下文等信息。当一个函数调用另一个函数时它会将新的栈帧压入栈顶形成一个嵌套的结构。这样每个函数都可以访问自己的栈帧中的信息而不会影响其他函数的信息。当一个函数执行完毕后它会将自己的栈帧弹出栈顶释放空间。然后它会根据返回地址跳转回调用者并将返回值传递给调用者。当一个函数发生异常时它会将异常信息保存在栈中并跳转到异常处理程序。异常处理程序可以根据栈中的信息进行恢复或终止操作。 为了更好地理解函数嵌套调用栈的作用我们可以看一个简单的例子。假设我们有以下三个函数 int f1(int a, int b) {int c a b;int d f2(c);return d; }int f2(int x) {int y x * x;int z f3(y);return z; }int f3(int r) {int s r - 1;return s; }现在我们假设主程序调用了 f1(2, 3)。那么函数嵌套调用栈的变化如下 主程序在调用 f1(2, 3) 之前会将参数 a 2 和 b 3 压入栈中并将返回地址主程序中 f1(2, 3) 的下一条指令压入栈中。然后跳转到 f1 的起始地址。f1 在执行时会在栈顶分配一段空间存放自己的局部变量 c 和 d。然后计算 c a b 5 并保存在栈中。f1 在调用 f2(c) 之前会将参数 x c 5 压入栈中并将返回地址f1 中 f2(c) 的下一条指令压入栈中。然后跳转到 f2 的起始地址。f2 在执行时会在栈顶分配一段空间存放自己的局部变量 y 和 z。然后计算 y x * x 25 并保存在栈中。f2 在调用 f3(y) 之前会将参数 r y 25 压入栈中并将返回地址f2 中 f3(y) 的下一条指令压入栈中。然后跳转到 f3 的起始地址。f3 在执行时会在栈顶分配一段空间存放自己的局部变量 s。然后计算 s r - 1 24 并保存在栈中。f3 在执行完毕后会将自己的返回值 s 24 放在 a0 寄存器中并将自己的栈帧弹出栈顶释放空间。然后它会根据返回地址跳转回 f2。f2 在接收到 f3 的返回值后会将其保存在栈中的 z 中。然后它会将自己的返回值 z 24 放在 a0 寄存器中并将自己的栈帧弹出栈顶释放空间。然后它会根据返回地址跳转回 f1。f1 在接收到 f2 的返回值后会将其保存在栈中的 d 中。然后它会将自己的返回值 d 24 放在 a0 寄存器中并将自己的栈帧弹出栈顶释放空间。然后它会根据返回地址跳转回主程序。主程序在接收到 f1 的返回值后会将其保存在某个变量中。然后它会将栈中的参数 a 2 和 b 3 弹出栈顶释放空间。然后它会继续执行下一条指令。 递归函数是一种非叶函数它调用自身。递归函数既是调用者又是被调用者所以它必须保存和恢复保留和非保留寄存器。 例如阶乘函数可以写成一个递归函数。回忆一下阶乘(n) n × (n – 1) × (n – 2) × ⋯ × 2 × 1。阶乘函数可以递归地写成阶乘(n) n × 阶乘(n – 1)如下图所示。1 的阶乘就是 1。 假设程序从地址 0x8500 开始。根据被调用者保存规则阶乘是一个非叶函数必须保存 ra。根据调用者保存规则阶乘在调用自身后仍然需要 n所以它必须保存 a0。因此它在开始时将这两个寄存器压入栈中。然后它检查 n 是否小于等于 1。如果是的话它将返回值 1 放在 a0 中恢复栈指针并返回到调用者。在这种情况下它不需要恢复 ra因为它从未被修改过。如果 n 大于 1函数递归地调用阶乘(n−1)。然后它从栈中恢复 n 和返回地址寄存器 (ra)进行乘法并返回这个结果。注意函数巧妙地将 n 恢复到 t1 中以免覆盖返回值。乘法指令 (mul a0,t1,a0) 将 n (t1) 和返回值 (a0) 相乘并将结果放在 a0 中即返回寄存器。 为了清楚起见我们在函数调用开始时保存寄存器。一个优化的编译器可能会观察到当 n 小于等于 1 时没有必要保存 a0 和 ra并且只在函数的 else 部分将寄存器保存到栈上。下图显示了执行阶乘(3) 时的栈情况。 为了说明我们假设 sp 最初指向 0xFF0高地址位为 0如上图(a) 所示。函数创建了一个两字的栈帧来保存 n (a0) 和 ra。在第一次调用时阶乘将 a0保存 n 3保存在 0xFEC 和 ra 在 0xFE8 中如图 (b) 所示。函数然后将 n 改变为 2 并递归地调用阶乘(2)使 ra 持有 0x8528。在第二次调用时它将 a0保存 n 2保存在 0xFE4 和 ra 在 0xFE0 中。这次我们知道 ra 包含 0x8528。函数然后将 n 改变为 1 并递归地调用阶乘(1)。 在第三次调用时它将 a0保存 n 1保存在 0xFDC 和 ra 在 0xFD8 中。这次 ra 再次包含 0x8528。第三次调用阶乘返回值为 1 的 a0并在返回到第二次调用之前释放栈帧。第二次调用恢复 n到 t1为 2恢复 ra 到 0x8528它恰好已经有了这个值释放栈帧并返回 a0 2 × 1 2 给第一次调用。第一次调用恢复 n到 t1为 3恢复 ra调用者的返回地址释放栈帧并返回 a0 3 × 2 6。图© 显示了递归调用的函数返回时的栈情况。当阶乘返回到调用者时栈指针在它的原始位置0xFF0栈指针以上的栈内容没有改变并且所有的保留寄存器保持它们的原始值。a0 持有返回值6。 另外在函数调用过程中如果一个RISC-V函数需要的参数超过了八个寄存器即a0到a7那么它应该按照标准调用约定的规则将多余的参数通过堆栈stack传递。具体来说调用者caller在进行函数调用前需要将多余的参数按照顺序压入堆栈中并且在调用后将它们从堆栈中弹出。被调用者callee在接收到参数后需要从堆栈中按照相反的顺序取出多余的参数并且在返回前将它们放回堆栈中。这样可以保证函数调用前后堆栈的内容和指针不变以及参数的正确传递。 例如如果一个函数需要10个整数参数那么它可以将前八个参数放在寄存器a0到a7中将后两个参数压入堆栈中。被调用者可以从寄存器a0到a7中直接读取前八个参数从堆栈中读取后两个参数。在返回前被调用者需要将后两个参数放回堆栈中。调用者在函数返回后需要将后两个参数从堆栈中弹出。 图(b) 显示了被调用者堆栈帧的组织。 堆栈帧保存临时、参数和返回地址寄存器如果由于后续函数调用而需要保存它们以及函数将修改的任何已保存寄存器。 它还保存局部数组和任何多余的局部变量。 如果被调用者有超过八个参数它会在调用者的堆栈帧中找到它们。
http://www.hkea.cn/news/14277151/

相关文章:

  • 网站推广文案网站客户续费
  • 网站优化防范提高工作效率总结心得
  • 网站要怎么备案wordpress语言切换
  • .net开发网站的优点做网站没资源
  • 婚纱网站建设目的企业开源网站系统
  • 国外做电商网站有哪些wordPress登不上数据库
  • 做网站广告收入互联网软件公司排名
  • 双语网站代码如何做一个网站
  • 那个网站做排列五头比较准ps企业网站模板免费下载
  • 潍坊网站建设报价费用2022最新小学生新闻
  • 网站推广的心得网站服务器能更换吗
  • 软件外包网站服务行业网站建设
  • 网站建设步骤完整版四川省四川省住房和城乡建设厅网站
  • 重庆最大的网站制作公司公路机电工程建设网站
  • 单位网站建设制作个人网站制作成品图片
  • 网页网站开发淘宝网站SEO怎么做
  • 广州开发网站建设北京电力交易中心
  • 最专业的做网站公司哪家好网业协同具体指什么
  • 外贸移动端网站模板网站建设sem账户搭建
  • 外贸谷歌网站推广切削工具东莞网站建设
  • 灰色网站网站在线修图编辑器
  • 做网站一天能赚多少钱遵义网站开发
  • 河南平顶山网站建设公司免费发做网站
  • 镇江网站建设包括哪些专业网站建设平台代理商
  • 贵州专业网站建设费用南通市建设局网站6
  • 高端企业网站建设蓦然郑州网站建设wordpress进不到后台
  • 做外账要登什么网站wordpress jekyll 选择
  • 高端网站建设公司有哪些项目局域网建WordPress
  • 建设网站要准备什么新乡网络公司推荐
  • 张家港外贸网站制作江苏省住房和城乡建设局