MIPS 分支执行顺序 (beqz)

MIPS branch execution order (beqz)

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

add $t0,$t1,$t2

beqz $t0, next

b next2

addi $t0,$t0,2

next: 
   addi $t2,$t0,3

next2: 
    addi $t1,$t1,2

程序将继续进行 next2。我假设您想在分支为真时跳过 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 ...

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

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


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

但是如果你在真正的 MIPS 上有 b运行ch 延迟槽(即使 b运行ch 被占用,b运行ch 之后的指令也会执行),然后 bbeq 的 b运行ch 延迟槽中。即 b 将 运行 无论 b运行ch 是否被占用,使其毫无意义。所以你的代码无论如何都没有意义。


你让你的 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 上使用 b运行ch-delay slots,假设 addi $t0,$t0,2 应该 运行 只有 [=23] =] 是非零的。

我正在用 fall-through 路径中的 addi $t1,$t1,2 填充 b运行ch-delay 槽,因为它总是在您的原始源中 运行。我认为这是有意的。

    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 return 之后),这样你就不会必须跳过它。因此,一条路径有一个未采用的路径 b运行ch;另一方已采取 beq 和无条件 b 重新加入另一条路径。