首页 > 解决方案 > MIPS 分支执行顺序 (beqz)

问题描述

我在理解此代码中的指令顺序时遇到了一些问题。假设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

标签: assemblybranchmips

解决方案


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

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


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

但是,如果您使用的是带有分支延迟槽的真正 MIPS(即使采用分支,分支后的指令也会执行),那么b在 a 的分支延迟槽中beq 会导致不可预测的行为。即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重新加入另一条路径。


推荐阅读