嵌套过程

不调用其他过程的过程称为叶过程(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——递归调用的更多相关文章

  1. Python-函数的递归调用

    递归调用顾名思义即在函数内部调用函数(自己调用自己),通常用它来计算阶乘,累加等   注意: - 必须有最后的默认结果 if n ==0,(不能一直调用自己,如果没有可能会造成死循环) - 递归参数必 ...

  2. 关于C++的递归调用(n的阶乘为例)

    C++,是入门编程界的一门初期的语言.今天我们浅谈一下有关C++的递归调用. 在没有继承,多态,封装之前,C++几乎看成是C语言,除了一些简单的输出和头文件. 具体代码实现如下: #include&l ...

  3. java中父类与子类, 不同的两个类中的因为构造函数由于递归调用导致栈溢出问题

    /* 对于类中对成员变量的初始化和代码块中的代码全部都挪到了构造函数中, 并且是按照java源文件的初始化顺序依次对成员变量进行初始化的,而原构造函数中的代码则移到了构造函数的最后执行 */ impo ...

  4. 玩坏JVM很简单--toString的递归调用

    在JVM的内存管理机制下很少发生内存溢出的情况.至少我碰见的少,好像在SSH我多次发布项目时候出现过一次.今天看见一个特简单的方法让内存溢出(好吧,我似乎作死了--!): public class I ...

  5. 关于static 的研究 与递归调用的输出

    static的作用 :1.保存上次执行的结果 2.static int m; 这里默认m的初始值为0,即默认 值是0 #include "stdio.h" int fun(int ...

  6. C#函数式编程之递归调用

    关于递归相信大家已经熟悉的不能再熟悉了,所以笔者在这里就不多费口舌,不懂的读者们可以在博客园中找到很多与之相关的博客.下面我们直接切入正题,开始介绍尾递归. 尾递归 普通递归和尾递归如果仅仅只是从代码 ...

  7. c++11 lambda递归调用写法

    偶然想到要在函数内部使用lambda递归调用,以下是可行的写法,可参考 std::function<void(Node * container,const BlendFunc &blen ...

  8. 使用Map辅助拼装树状结构,消除递归调用

    目前菜单或其他树状结构在数据库中的存储,多数是以一个parentid作为关联字段,以一维形式存储.使用时全部查询出来,然后在内存中拼装成树状结构.现在主要涉及的是拼装方法的问题. 一般可以进行 递归调 ...

  9. php之递归调用,递归创建目录

    /* 递归自身调用自身,每次调用把问题简化,直到问题解决 即:把大的任务拆成相同性质的多个小任务完成 */ /* function recsum($n){ if($n>1){ return $n ...

随机推荐

  1. TP5之上传多张图片

    1.效果图(每点击一次‘添加选项’,就会有一个新的 file 框来添加新的图片) 2.view <!--不要忘了引入jquery文件--> <!-- post传值方式和文件传输协议一 ...

  2. js微信摇一摇功能以及api

    一.摇一摇功能 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  3. DataGridView Index -1 does not have a value 错误

    遇到一个非常奇怪的问题, 一个DataGridView在装载数据后, 无论点击Column还是Cell都会报如下错误: 查bing之后发现StackOverFlow都指向DataSource的问题. ...

  4. java基础第二篇

    3.选择结构 a.if: 格式一: if(表达式1){ 表达式1为真才执行 } 格式二: if(表达式1){ 表达式1为真才执行 }else{ 表达式1位假才执行 } 格式三:判断工龄的范围,判断成绩 ...

  5. get 和 post 请求的区别(转)

    转自 http://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html http://www.nowamagic.net/librarys/ve ...

  6. hdu 2108 Shape of HDU(判定是不是凸多边形)

    #include <iostream> #include <algorithm> #include <cstring> #include <cstdio> ...

  7. IDE工具、文本编辑器的列块编辑模式

    前言 有时候需要对若干列进行一样的操作,比如在前一百行数据的最前边加上一样的字符,这时候可以通过列块编辑模式来快捷地实现这个效果.在列块编辑模式下,被选定的区域内的所有字符会被替换成你之后输入的字符. ...

  8. java操作redis实现和mysql数据库的交互

    连接地址http://blog.csdn.net/kingcat666/article/details/77936970

  9. 清空模拟器中的app

    1.打开模拟器 2.在左上角得下拉菜单选择“还原内容和设置” 3.选择“还原” ,确定 就ok了! 图解如下:

  10. [题解](gcd/lcm)luogu_P1072_Hankson的趣味题(NOIP2009)

    连续三次不开longlong导致wa!!! 不开longlong一时爽,一会提交火葬场!!! OI千万条,longlong第一条 乘法不longlong,提交两行泪 暴力luogu就能过了???打好暴 ...