【问题标题】:MIPS branch execution order (beqz)MIPS 分支执行顺序 (beqz)
【发布时间】:2018-07-08 16:44:05
【问题描述】:

我在理解此代码中的指令顺序时遇到了一些问题。假设 beqz 为真,它分支到下一个标签,程序是在那里结束还是标签 next2 也执行?由于没有系统调用来结束程序。

add $t0,$t1,$t2

beqz $t0, next

b next2

addi $t0,$t0,2

next: 
   addi $t2,$t0,3

next2: 
    addi $t1,$t1,2

【问题讨论】:

  • "程序到此结束了吗?"没有。"或者label next2也执行了?"是的。
  • 您的示例还有另一个问题:如果分支指令紧跟在另一条指令之后(b 跟在 beqz 之后),则 MIPS CPU 的结果未定义。至少 MIPS R4000 CPU 的手册是这么说的。在这种情况下,通常汇编程序会在跳转之间隐式添加nop 指令。
  • @Michael 好的,谢谢,我想我知道了。添加后它返回到 beqz,再次检查,但现在它是错误的,所以它转到 next2,进行加法,然后转到 b next2 下面的加法,然后结束。
  • @MartinRosenau 谢谢指正,这只是课堂上的一个例子,你可以责怪我的教授哈哈
  • @MartinRosenau:根据我的经验,在学术界教授 MIPS 汇编时,他们倾向于使用 SPIM 或 MARS 等模拟器。这些默认情况下禁用了延迟分支,可能是为了让学生的事情变得不那么复杂。

标签: assembly branch mips


【解决方案1】:

标签只是让您从另一条指令中引用地址的一种方式。他们不会阻止执行。无论源代码中的空格或标签如何,执行总是继续到下一条指令。

请记住,asm 源代码只是一种将机器代码写入文件的语言;标签不会出现在机器码中。


你的代码很奇怪。在b 指令之后您有一个addi $t0,$t0,2,因此在禁用分支延迟槽的情况下永远无法到达它。 (默认为 MARS/SPIM)。它上面没有标签,所以它不是你从其他地方跳转到的分支目标。

但是,如果您使用的是带有分支延迟槽的真正 MIPS(即使采用分支,分支后的指令也会执行),那么 b 位于 beq leads to unpredictable behaviour 的分支延迟槽中。即 b 无论分支是否被采用都会运行,这使它毫无意义。因此,无论哪种方式,您的代码都没有意义。


您正在使您的if 变得比它需要的复杂得多(或者它是if/else?)。 不用beq / b 总是跳转到某处,只需使用bne 跳转或跌倒。另外,使用有意义的标签名称。

 ## MIPS without branch-delay slots

    add  $t0, $t1,$t2
    bnez $t0, sum_nonzero

    # addi $t0,$t0,2     # was unreachable, or was that supposed to be a branch-delay slot?

# sumzero:               # not really a branch target, only reached via fallthrough
    addi $t2, $zero, 3   # only reached with t0 = 0, might as well not even read it

    # execution falls through to the next instruction like always
sum_nonzero: 
    addi $t1,$t1,2       # runs whether bnez was taken or not

    ... execution continues

或者在带有分支延迟槽的 MIPS 上,假设 addi $t0,$t0,2 应该仅在 $t0 非零时运行。

我正在使用来自直通路径的addi $t1,$t1,2 填充分支延迟槽,因为它始终在您的原始源中运行。我认为这是故意的。

    add  $t0, $t1,$t2
    bnez $t0, sum_nonzero
    addi $t1,$t1,2       # branch-delay: runs whether bnez was taken or not

# Fall through when sum == zero
    addi  $t2, $zero, 3
    addiu $t0,$zero, -2     # instead of branching to avoid addi  $t0,$t0,2 on this path, do its inverse

sum_nonzero: 
    addi  $t0,$t0,2         # produces $t0 = 0 if $t1+$t2 == 0, otherwise $t0 = $t1+$t2+2

    ... execution continues

如果您正在制作if/else,您可以将一侧的代码放在其他地方(在jr $ra 返回之后),这样您就不必跳过它。因此,一条路径有一个未采用的分支;对方有一个采取beq和一个无条件的b重新加入另一条路径。

【讨论】:

  • 好吧,我迟到了一年多,但感谢您的帮助。代码不是我写的,所以怪我的教授。
  • @user2602540:请随时向您的教授发送此答案的链接:P
【解决方案2】:

程序将继续 next2。我假设您想在分支为 true 时跳过 next2,因此您可以执行以下操作来修复它:

add $t0,$t1,$t2

beqz $t0, next

b next2

addi $t0,$t0,2

next: 
   addi $t2,$t0,3
   b cont

next2: 
    addi $t1,$t1,2

cont:
    # The rest of your program ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-07
    • 2011-07-09
    • 2015-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多