MIPS——递归调用
嵌套过程
不调用其他过程的过程称为叶过程(leaf procedure)。如果所有过程都是叶过程,那么情况就很简单。但是某个过程可以调用其他过程,甚至调用的是自身的“克隆”。在调用非叶过程时使用寄存器需要十分小心。
例如,假设主程序将参数3存入寄存器a0,然后使用jal A调用过程A。再假设过程A通过jal B调用过程B,参数为7,同样存入a0。由于A尚未结束任务,所以在寄存器a0的使用上存在冲突。同样,在寄存器ra保存的返回地址也存在冲突,因为它现在保存着B的返回值。
我们必须采取措施阻止这类问题发生:
一个解决方法是将其他所有必须保存的寄存器压栈,就像将保存寄存器压栈一样。调用者将所有调用后还需的参数寄存器(a1~a3)或临时寄存器(t0~t9)压栈。被调用者将返回地址寄存器(ra)和被调用者使用的保存寄存器(a0~a7)都压栈。栈指针 sp 随这栈中的寄存器个数调整。到返回时,寄存器会从存储器中恢复,栈指针也会随着重新调整。
有关指令
jal function #set $ra to Program Counter(PC),then jump to statement at target addres
C语言代码
#include<stdio.h> int factorial(int n); int main()
{
int n;
scanf("%d", &n);
int res = factorial(n);
printf("%d\n",res);
return ;
} int factorial(int n)
{
if (n < ) return ;
else return n * factorial(n - );
}
虽然在C语言中函数定义可以在main函数前,也可以在main函数后,但定义在main函数后似乎更接近MIPS风格(看下面的代码你就知道了)
MIPS代码
.data
prompt1: .asciiz "Enter the number\n"
prompt2: .asciiz "The factorial of n is:\n" .text
# Print prompt1
li $v0,
la $a0, prompt1
syscall # Read integer
li $v0,
syscall # Call factorial
move $a0, $v0
jal factorial
move $a1, $v0 # save return value to a1 # Print prompt2
li $v0,
la $a0, prompt2
syscall # Print result
li $v0,
move $a0, $a1
syscall # Exit
li $v0,
syscall ## Function int factorial(int n)
factorial:
## YOUR CODE HERE
addi $sp,$sp,- #adjust stack for items
sw $ra,($sp) #save return address
sw $a0,($sp) #save the argument n slti $t0,$a0, #if n < 1,then set $t0 as 1
beq $t0,$zero,L1 #if equal,then jump L1
#above all,if n >= ,then jump L1
#if(n < 1)
addi $v0,$zero, #return
addi $sp,$sp, #pop items off stack
jr $ra #return to caller
#else
L1:
add $a0,$a0,- #argument :n -
jal factorial #call factorial with (n-) lw $a0,($sp) #restore argument n
lw $ra,($sp) #restore address
addi $sp,$sp,8 #adjust stack pionter
mul $v0,$a0,$v0 #return n * factorial(n-)
jr $ra return to caller
## END OF YOUR CODE
#jr $ra
手绘调用栈:


MIPS——递归调用的更多相关文章
- Python-函数的递归调用
递归调用顾名思义即在函数内部调用函数(自己调用自己),通常用它来计算阶乘,累加等 注意: - 必须有最后的默认结果 if n ==0,(不能一直调用自己,如果没有可能会造成死循环) - 递归参数必 ...
- 关于C++的递归调用(n的阶乘为例)
C++,是入门编程界的一门初期的语言.今天我们浅谈一下有关C++的递归调用. 在没有继承,多态,封装之前,C++几乎看成是C语言,除了一些简单的输出和头文件. 具体代码实现如下: #include&l ...
- java中父类与子类, 不同的两个类中的因为构造函数由于递归调用导致栈溢出问题
/* 对于类中对成员变量的初始化和代码块中的代码全部都挪到了构造函数中, 并且是按照java源文件的初始化顺序依次对成员变量进行初始化的,而原构造函数中的代码则移到了构造函数的最后执行 */ impo ...
- 玩坏JVM很简单--toString的递归调用
在JVM的内存管理机制下很少发生内存溢出的情况.至少我碰见的少,好像在SSH我多次发布项目时候出现过一次.今天看见一个特简单的方法让内存溢出(好吧,我似乎作死了--!): public class I ...
- 关于static 的研究 与递归调用的输出
static的作用 :1.保存上次执行的结果 2.static int m; 这里默认m的初始值为0,即默认 值是0 #include "stdio.h" int fun(int ...
- C#函数式编程之递归调用
关于递归相信大家已经熟悉的不能再熟悉了,所以笔者在这里就不多费口舌,不懂的读者们可以在博客园中找到很多与之相关的博客.下面我们直接切入正题,开始介绍尾递归. 尾递归 普通递归和尾递归如果仅仅只是从代码 ...
- c++11 lambda递归调用写法
偶然想到要在函数内部使用lambda递归调用,以下是可行的写法,可参考 std::function<void(Node * container,const BlendFunc &blen ...
- 使用Map辅助拼装树状结构,消除递归调用
目前菜单或其他树状结构在数据库中的存储,多数是以一个parentid作为关联字段,以一维形式存储.使用时全部查询出来,然后在内存中拼装成树状结构.现在主要涉及的是拼装方法的问题. 一般可以进行 递归调 ...
- php之递归调用,递归创建目录
/* 递归自身调用自身,每次调用把问题简化,直到问题解决 即:把大的任务拆成相同性质的多个小任务完成 */ /* function recsum($n){ if($n>1){ return $n ...
随机推荐
- art-template在项目中的应用
art-template 是一个简约.超快的模板引擎.它采用作用域预声明的技术来优化模板渲染速度,从而获得接近 JavaScript 极限的运行性能,并且同时支持 NodeJS 和浏览器. 下面介绍在 ...
- lightoj刷题日记
提高自己的实力, 也为了证明, 开始板刷lightoj,每天题量>=1: 题目的类型会在这边说明,具体见分页博客: SUM=54; 1000 Greetings from LightOJ [简单 ...
- MarketServer 日志
2014.04.29 1. 发现有时候会跳出 Exception Infomations: 用户异常信息:Socket未连接 跟踪后发现的一次情况是: 服务器根据客户端请求从后台读取数据后,写数据 ...
- 上传到git
https://blog.csdn.net/Lucky_LXG/article/details/77849212
- MyBatis源码解析(一)
<!-- mybatis文件配置,扫描所有mapper文件 --><!--SqlSessionFactoryBean的初始化参数--> <bean id="sq ...
- C 语言实例 - 二进制与十进制相互转换
C 语言实例 - 二进制与十进制相互转换 C 语言实例 C 语言实例 二进制转与十进制相互转换. 实例 - 二进制转换为十进制 #include <stdio.h> #include &l ...
- 「开源」SpringCloud+vue搭建的商城项目
最近在研究SpringCloud,看到一个基于SpringCloud+vue搭建的模拟商城项目.用来辅助学习SpringCloud企业级开发还是很有帮助的.强烈推荐!! 源码地址在最后. spring ...
- 测试 | Mock object
实例: 一个简单的图书管理系统包括三个类: Book提供了书籍的定义 BookService提供了有关书籍借阅和归还的服务 BookMananger查找书籍并把对书籍状态的更改更新到数据库中 目前,B ...
- python异常之EOFError: Ran out of input
出现该问题一般是由于你在以写模式打开文件后未关闭的情况下又去以读模式操作该文件时报的错误 # coding = utf-8 import pickle #定义一个boy类 class boy(): d ...
- [题解]数学期望_luogu_P1850_换教室
数学期望dp,题面第一次见很吓人,然而从CCF语翻译成人话就简单多了, 开始一般会想到用 f [ i ] [ j ]表示前 i 个课程申请 j 次的期望,然而其实会发现转移的时候还和上一次的情况有关( ...