使用 MIPS 的双重递归

2023-12-04

我正在尝试为该函数实现双重递归f(n) = 2f(n-1) + 3f(n-2) + 1。我能够找出奇异递归并实现2f(n-1) + 1它的一部分,但我不知道如何实现第二部分。这是我的奇异递归的工作代码:

.data
prompt1: .asciiz "Enter the value for the recursive function f(n) = 2f(n-1)+3f(n-2)+1:  "
prompt2: .asciiz "Result: "
numberEntered: .word 0
answer: .word 0

.text

main:
#Ask for the value
li $v0 4
la $a0, prompt1
syscall

#enter value
li $v0, 5
syscall

sw $v0, numberEntered  #stores the number

# call the function
lw $a0, numberEntered
jal function
sw $v0, answer

#Print out the result
li $v0 4
la $a0, prompt2
syscall

lw $a0, answer
li $v0, 1
syscall

li $v0, 10
syscall

.globl function
function:
subu $sp, $sp, 8
sw $ra, ($sp)
sw $s0, 4($sp)

#base case
li $v0, 1
beq $a0, $zero, done

#calling f(n-1)
move $s0, $a0
sub $a0, $a0, 1
jal function

#calculations occur here
mul $v0, $v0, 2
addi $v0, $v0, 1

done:

lw $ra, ($sp)
lw $s0, 4($sp)
addi $sp, $sp, 8

jr $ra  #returns

我尝试在其计算部分中将下一部分的地址加载到堆栈中,但我无法弄清楚使其工作的实现。我必须“结束”堆栈两次吗?目前和计算部分的情况如何?我无法弄清楚,任何帮助将不胜感激!


相当不错的努力。

回答你的问题:你可以简单地在以下位置建立一个堆栈帧function进入并最后从中恢复。

我确实必须重新调整用途$s0稍微存储一个中间值并将其添加到堆栈帧中存储的值(即堆栈帧现在是 3 个字而不是 2 个)。

无论如何,这是更正后的代码。我尝试对其进行一些注释(IMO,在 asm 中,不存在“太多评论”这样的事情) [请原谅无偿的清理方式]:

    .data
prompt1:    .asciiz     "Enter the value for the recursive function f(n) = 2f(n-1)+3f(n-2)+1:  "
prompt2:    .asciiz     "Result: "
numberEntered:  .word   0
answer:     .word       0

    .text

main:
    # Ask for the value
    li      $v0,4
    la      $a0,prompt1
    syscall

    # enter value
    li      $v0,5
    syscall

    sw      $v0,numberEntered       # stores the number

    # call the function
    lw      $a0,numberEntered
    jal     function
    sw      $v0,answer

    # Print out the result
    li      $v0,4
    la      $a0,prompt2
    syscall

    lw      $a0,answer
    li      $v0,1
    syscall

    li      $v0,10
    syscall

    .globl  function

# function -- calculation
# v0 -- return value
# a0 -- current n value
# s0 -- intermediate result
function:
    subi    $sp,$sp,12              # establish our stack frame

    sw      $ra,8($sp)              # save return address
    sw      $a0,4($sp)              # save n
    sw      $s0,0($sp)              # save intermediate result

    # base case
    # NOTE: with the addition of n-2, the "beq" was insufficient
    li      $v0,1
    ble     $a0,$zero,done

    # calling f(n-1)
    sub     $a0,$a0,1               # get n-1
    jal     function

    # NOTE: these could be combined into a single instruction
    mul     $v0,$v0,2               # get 2f(n-1)
    move    $s0,$v0                 # save it

    # calling f(n-2)
    sub     $a0,$a0,1               # get n-2
    jal     function

    mul     $v0,$v0,3               # get 3f(n-2)

    # get 2f(n-1) + 3f(n-2) + 1
    add     $v0,$s0,$v0
    add     $v0,$v0,1

done:
    lw      $ra,8($sp)              # restore return address
    lw      $a0,4($sp)              # restore n
    lw      $s0,0($sp)              # restore intermediate result

    addi    $sp,$sp,12              # pop stack frame

    jr      $ra                     # returns

UPDATE:

这个解决方案比我想象的要简单得多。

这可能是因为堆栈帧在 asm [或 C] 中完成的方式所致。

考虑一个现代 C 程序:

int
whatever(int n)
{
    int x;

    // point A
    x = other(1);

    // do lots more stuff ...

    {
        // point B
        int y = other(2);

        // do lots more stuff ...

        // point C
        n *= (x + y);
    }

    // do lots more stuff ...

    n += ...;

    return n;
}

C编译器将在进入时建立一个堆栈帧whatever将会保留space for x and y虽然y只是set很久以后。大多数 C 程序员没有意识到这一点。

在解释语言中(例如java, python等)空间y没有被保留until代码位于point B is executed。而且,他们[通常]会在以下情况下取消分配它:y“超出范围”[之后point C].

大多数 C 程序员think具有作用域声明 [例如y] 节省堆栈空间。 (即)在作用域块中,编译器将增加堆栈帧大小以适应y并再次缩小它y不再需要。

这简直就是not正确的。 C编译器将设置堆栈帧并为以下内容保留空间all函数作用域变量,即使它们是在函数后期或内部作用域内声明的 [例如y].

这正是我们在您的项目中所做的function。即使我们不需要/利用堆栈空间 [在偏移量 0 处] 也是如此$s0直到函数的中间。

所以,我猜你使用其他语言的经历do动态地[有效地]保留空间,或者关于 C 的常识可能会引导您建立一个您认为需要的更复杂的模型。因此你原来的问题是:我必须“结束”堆栈两次吗?


我还应该提到的是function is not符合 ABI。这是完美如果它是自包含的(即不调用其他任何东西)就很好。也就是说,在asm中,对于“叶子”函数,我们可以定义任何我们想要的。

原因是$a0调用被修改/删除callee。我们从堆栈中保存/恢复它,但调用另一个函数可能会把事情搞砸。补救措施就是使用另一个寄存器来保存该值[或保存/恢复到堆栈帧中的额外位置],因此如果function最终调用了其他东西。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 MIPS 的双重递归 的相关文章

  • 如何在 Twig 中渲染树

    我想渲染一棵深度不确定的树 孩子的孩子的孩子等 我需要递归地循环遍历数组 我怎样才能在 Twig 中做到这一点 我玩过domi27的想法 https stackoverflow com questions 8326482 how to re
  • 最有效地将编译时大小的数组的所有元素相加

    我正在尝试使用最少量的指令 有效地将所有内容添加到编译时大小的数组中 当然 我正在使用模板 我创造了这个 template
  • 变量的多个值介于 0 和数字序言之间

    所以我一直在尝试自学序言 我认为我进展顺利 然而 我有点坚持我正在尝试的这一种方法 toN N A A 等于 0 到 N 1 之间的整数值 按升序生成 所以 toN 5 A 将是 A 0 A 1 A 2 A 3 A 4 我对序言还很陌生 所
  • 将正数放在负数之前

    所以我有在互联网上找到的这段代码 它采用负数和正数数组并重新排列数组 以便所有负数都在正数之前 但每个数字出现的位置必须保持相同 例如 如果我有 2 5 9 在有组织的数组中 2仍然必须是first的数量negative那些和 9必须是se
  • 递归与迭代算法

    我正在实现欧几里德算法来查找两个整数的 GCD 最大公约数 给出了两个示例实现 递归和迭代 http en wikipedia org wiki Euclidean algorithm Implementations http en wik
  • 如何从邻接列表构建嵌套树结构?

    考虑到我有 名为的相邻键 子级 父级 列表A 一个名为Tree存储自己的节点键 整数 和子节点 类 A 61 66 50 61 68 61 33 61 57 66 72 66 37 68 71 33 6 50 11 37 5 37 clas
  • 为什么 array_merge_recursive 不是递归的?

    我最近在我的应用程序中发现了一个由意外行为引起的错误array merge recursive 让我们看一下这个简单的例子 array1 1 gt 1 gt 100 2 gt 200 2 gt 3 gt 1000 3 gt 1 gt 500
  • 使用线性递归计算第 n 个斐波那契数 [重复]

    这个问题在这里已经有答案了 我努力了二元递归找到第 n 个斐波那契数 或通过使用整个斐波那契数列 for循环进入main 但根据Java 中的数据结构和算法 第六版 迈克尔 T 古德里奇 这是一种效率极低的方法 因为它需要对该方法进行指数级
  • F# 中的递归对象?

    这段 F 代码 let rec reformat new EventHandler fun gt b TextChanged RemoveHandler reformat b gt ScrollParser rewrite contents
  • 可以通过Data.Function.fix来表达变形吗?

    我有这个可爱的fixana这里的函数执行速度比她的姐妹快 5 倍左右ana 我有一个criterion报告支持我这一点 ana alg Fix fmap ana alg alg fixana alg fix f gt Fix fmap f
  • Java-使用递归压平数组

    我一直在练习算法 递归一直是我的弱项 该问题要求将嵌套数组展平为单个数组 如果使用给出 O n 3 给定相同大小的 3d 数组 解决方案的循环 这将很简单 然而 通过递归 我已经挣扎了几个小时 这就是我所拥有的 请注意 我已经尝试过使用我的
  • C语言中的递归是如何工作的?

    我试图了解 C 中递归的工作原理 任何人都可以给我解释控制流吗 include
  • 递归中的收益回报

    我正在尝试创建一个 IEnumrable
  • 递归例程获取PropertyInfo

    我正在尝试创建一个递归例程 它将检索指定对象 在 NET 3 5 中 下的所有成员的 PropertyInfos 直接成员的一切都正常 但它还需要解析嵌套类 及其嵌套类等 我不明白如何处理解析嵌套类的部分 这部分代码你会怎么写呢 publi
  • 打字稿中的递归未定义

    我在组件内使用画布对象来生成图表 为了使其动画化 我递归地调用该方法 我不断收到错误消息 指出该方法未定义 不确定我需要如何构建它 任何帮助表示赞赏 Animate function protected animate draw to Cl
  • 更好地相当于这个疯狂的嵌套 python for 循环

    for a in map for b in map a for c in map b for d in map c for e in map d print a b c d e 上面的代码用于创建图中一定长度的所有路径 map a 表示从
  • 如何通过map[string]interface{}递归迭代

    我遇到了一个问题 如何在附加条件下递归地迭代 map string interface 1 如果一个值是一个映射 递归调用该方法 2 如果一个值是一个数组 调用数组的方法 3 如果一个值不是一个映射 处理它 现在当方法尝试执行时doc th
  • 递归指数法

    public static int exponent int baseNum int temp baseNum baseNum return temp exponent baseNum 现在 如果我调试它 上面的方法会 n n 变成无穷大
  • SQL Server:如何从递归函数内执行更新?

    我有一个递归标量函数 需要根据它返回的值更新另一个表中的记录 但是函数中不允许使用 UPDATE 语句 如何从函数内更新表 不允许使用 UPDATE 语句 功能 这就是规则 函数不允许有任何数据更改的副作用 您必须使用存储过程来UPDATE
  • 我的递归条件是否正确计算二叉树高度?

    我想在你的帮助下知道我的代码是对还是错 因为遗憾的是我无法运行它来检查 没有编译错误 我想做的是找到二叉树的高度 当然 树不必是平衡的 二叉树中的每个节点可以有两个节点作为子节点 http en wikipedia org wiki Bin

随机推荐

  • 类型错误:“datetime.date”对象没有属性“__getitem__”

    我在我的 models py 中使用 class Pedido models Model data pedido models DateField Data do pedido cliente models ForeignKey Clien
  • 谷歌地理编码不适用于数据库中带有特殊字符的地址

    我的谷歌地理编码数据库中的地址特殊字符有问题 但如果我对它们进行硬编码则不会 简单的地理编码代码 url http maps googleapis com maps api geocode json address address sens
  • TabControl 处理非活动选项卡上的控件

    我正在为我的应用程序使用 MVVM 模式 主窗口包括一个TabControl与DataContext映射到 ViewModel
  • 如何将 Lua 模块作为字符串而不是文件加载?

    我正在使用 LuaJava 和 Lua 的 C 代码 我想做的是读取在Android应用程序中存储为资源字符串的Lua源代码 以便可以执行读入的Lua源代码 我需要知道如何使用 LuaJava 或 C 语言来做到这一点 我想知道如何使用字符
  • Compact Framework 中的 MAC 地址

    如何仅使用紧凑框架获取 MAC 地址 1 4 的 OpenNETCF 代码从以下 P Invoke 调用中获取信息 DllImport iphlpapi dll SetLastError true public static extern
  • NgAnimate 页面加载 hack

    在更新 1 4 1 中 AngularJs Animate 不再像以前那样在页面加载时触发 我的旧解决方案类似对此 笨蛋 found here并一直工作到 v1 3 9
  • CSS 字体 Unicode 范围

    font face font family Nanum Barun Gothic src url NanumBarunGothic ttf unicode range U AC00 D7A3 U 1100 11FF U 3130 318F
  • 将新的拟合阶段添加到现有 PipelineModel 中,无需再次拟合

    我想将几个经过训练的管道连接到一个 这类似于 Spark 将新的拟合阶段添加到现有 PipelineModel 中 无需再次拟合 但是下面的解决方案适用于 PySpark gt pipe model new PipelineModel st
  • 火花笛卡尔积

    我必须比较坐标才能获得距离 因此 我使用 sc textFile 加载数据并制作笛卡尔积 文本文件中大约有 2 000 000 行 因此需要比较 2 000 000 x 2 000 000 坐标 我用大约 2000 个坐标测试了代码 几秒钟
  • fetchone() 正在将 int 变量设置为元组

    我有一个使用 Python 2 7 和 SQLite3 的项目 我正在尝试将整数变量存储在 SQLite3 数据库列中 然后能够将变量设置为 SQLite 列的值 连接正常 列存在 并且类型为 int 我正在使用此代码来提取数据 Trail
  • 有没有办法从以前的 apk 发布文件中获取私有签名的密钥库文件?

    我已经使用 eclipse 创建了私有签名的密钥库文件 并且我已经在 android market 网站上发布了 apk 文件 几天后 我们从用户那里收到了一些问题 我们已经解决了这些问题 但我没有私人签名的密钥库文件 在制作 apk 文件
  • 使用 VSTO 创建 UDF,而不使用 VBA

    与此类似question 但在我的情况下不是 VSTO SE 但是 我只是想确认不可能在 Visual Studio 2005 和 Excel 2003 中使用纯 VSTO 创建 UDF 所以 为了绝对清楚 我的问题是 是否可以使用 Vis
  • 从sql查询中的所有可用列中仅删除一列值的重复值

    我有一个包含三列的sql查询 我想删除beam current列中的任何重复值退出 如何做到这一点 我在sql server2012中工作 我使用了 Distinct 但我也得到了 beam current 的重复值 我的 sql 查询是
  • 如何将旧版构建系统与 Xcode 10 的“xcodebuild”一起使用?

    我想使用 Xcode 10 的新构建系统进行开发 但是我们在持续集成系统中的构建失败了 因为xcarchive制作有一个问题 Info plist in the xcarchive缺少ApplicationProperties密钥及其中的信
  • Select2-rails 无法与 ActiveAdmin 一起使用

    我在将 select2 rails 与 ActiveAdmin 集成时遇到困难 我按照设置步骤操作 Select2 rails Github 页面 https github com argerim select2 rails我添加了一行 r
  • c#编译的应用程序可以在未安装.net的机器上运行吗?

    我想为 Windows 开发一个小型实用程序 我更喜欢用 C 来做 因为它更容易 我是一名 Java 开发人员 该实用程序可供许多人下载 我假设其中一些人没有安装 net 框架 这个假设是否正确 假设我的目标是 win xp 及以上版本 我
  • 在Matlab中保存全局变量

    在 Matlab 中 当将变量声明为全局变量并使用 save 命令保存它时 在新会话中加载 mat 文件后 该变量也是全局变量 以下代码显示了此行为 一开始 我没有变量 gt gt who gt gt who global 然后 我创建全局
  • 更新间隔时间时警报管理器不工作

    阅读所有质量检查后 我没有得到任何正确的解决方案 我有 2 个问题1 即使我仅在清单中注册接收器 警报也会触发两次 不是通过代码 2 当我更新闹钟的间隔时间时 它会随机触发 这是我设置闹钟的方法 public void AlarmCall
  • 如何在java中扫描屏幕上的特定颜色/图像?

    我需要扫描屏幕上的特定图像 颜色 并返回该颜色出现位置的 x 和 y 坐标 我知道这可能包括使用 Robot 类截取屏幕截图 但不知道如何正确扫描该图像 如果您使用 Robot 类进行屏幕截图 您将获得 BuffereImage 类的对象
  • 使用 MIPS 的双重递归

    我正在尝试为该函数实现双重递归f n 2f n 1 3f n 2 1 我能够找出奇异递归并实现2f n 1 1它的一部分 但我不知道如何实现第二部分 这是我的奇异递归的工作代码 data prompt1 asciiz Enter the v