【问题标题】:Confused by the if Jumps in MIPS对 MIPS 中的 if 跳转感到困惑
【发布时间】:2021-09-05 18:05:46
【问题描述】:

我很难理解为什么我的bge 语句中的跳转会跳转到标签然后结束,而其他两个执行标签并返回。我对此有些陌生,希望有一个链接或另一篇帖子,其中包含我找不到的类似问题。我在nop 末尾留下了关于它对我的看法和代码结果的 cmets,我可能是错的,如果我有希望,可以指导我如何工作。

.globl main
.data
.text
main:

    li $t5, 8
    li $t6, 9 
    blt $t6,$t5, L1 // if (9 < 8) goto L1
    addi $t1, $t1, 2 // $t1 = 2
L1: 
    addi $t1, $t1, 1 // $t1 = 3
    nop // $t1 = 3 
    li $t7, 2
    li $t3, 2
    bne $t7,$t3, L2 // if ( 2 == 2) goto L2
    addi $t3, $t3, 2 // $t3 = 9
L2: 
    addi $t3, $t3, 5 // $t3 = 7
    nop // $t3 = 9
    li $t6, 4
    li $t5, 1
    bge $t6,$t5, L3 // if (4 >= 1) goto L3
    add $t6, $t6, $t5
    addi $t6, $t6, 3  
L3: 
    addi $t6, $t6, 5 // $t6 = 9
    nop // $t6 = 9

【问题讨论】:

  • 该代码中没有第三个 bge 语句。你能澄清你在问什么吗?

标签: if-statement mips


【解决方案1】:

首先,术语:

标签不执行。它们在汇编代码中,但不获取/获取机器代码,处理器永远不会看到它们。因此,单独的标签不能改变控制流,只有处理器指令可以做到这一点。

标签存在于汇编代码中,它们用于通知汇编器在机器代码指令中为引用它们的汇编指令(标签)选择哪些偏移量。

这段代码中没有任何东西可以“返回”。通常,我们保留术语 return 来表示通过间接分支返回给调用者的子例程。

就结尾而言,您没有有效的程序指令序列结尾,因此它只是在完成时从结尾运行。

第一个分支blt 不应该触发(应该通过)b/c 9 确实不少于 8。

您对bne 的评论与用汇编编写的操作相反,也许这会澄清一些事情。这个分支也不会触发,因为 2 确实等于 2。

最后一个分支会触发,因为 4 >= 1,所以会跳过前面的几条指令。

您应该在开始时将$t1 初始化为零,而不是依赖模拟器将其清零。

你说得对,$t6 最终会得到 9 = 4+5。

【讨论】:

    【解决方案2】:

    可能让你感到困惑的是MIPS有branch delay slots——这意味着只要你有一个分支(有条件的或无条件的,都没有关系),总是会执行分支指令之后的指令在分支实际分支之前。所以在这段代码中:

        blt $t6,$t5, L1 // if (9 < 8) goto L1
        addi $t1, $t1, 2 // $t1 = 2
    L1: 
    

    即使条件为真,分支似乎也没有任何效果,因为分支之后的指令(它与目标之间的唯一一条指令)无论如何都会被执行。

    在代码中

        li $t6, 4
        li $t5, 1
        bge $t6,$t5, L3 // if (4 >= 1) goto L3
        add $t6, $t6, $t5
        addi $t6, $t6, 3  
    L3: 
        addi $t6, $t6, 5 // $t6 = 9
    

    add $t6, $t6, $t5指令会一直执行,所以当分支条件为真时,只会跳过addi $t6, $t6, 3

    处理这个问题的最简单方法是总是在分支之后放置一个nop 指令。这会起作用,但效率低下(浪费了一个指令槽和周期),所以如果你能弄清楚如何在那里放置一条有用的指令会更好。请注意,分支后的指令直到条件分支计算其测试后才会执行,因此您不能只将分支前的指令移到分支后。

    最近的 MIPS 实施具有没有延迟槽的分支指令的“紧凑”版本。您可以通过在指令中添加c 来使用它们

    bgec $t6,$t5, L3 // if (4 >= 1) goto L3
    

    如果您的模拟器/系统支持它们

    【讨论】:

    • 我想你已经找到了 OP 的答案。然而,2014 年推出的 MIPS32 和 MISP64 架构具有删除/缺少分支延迟槽的功能。流行的模拟器可以选择打开/关闭分支延迟槽。这很令人困惑,因为我们永远不知道用户的设置是什么......
    • mips 第 6 版引入了“紧凑”分支,它们具有不同的编码并且没有分支延迟槽,但它们也有不同的助记符,末尾带有 C
    • 课程作业中使用的两个流行模拟器,MARS 和 QtSpim,都默认为所有分支都没有分支延迟槽,所以我认为大多数学生学习(当然没有统计数据和进一步证据)这些天通过 MIPS 进行组装并不期望或被教导分支延迟槽。
    猜你喜欢
    • 2011-01-24
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    • 1970-01-01
    相关资源
    最近更新 更多