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 之后的指令也会执行),然后 b
在 beq
的 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
重新加入另一条路径。
我在理解这段代码中指令的顺序时遇到了一些问题。假设 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 之后的指令也会执行),然后 b
在 beq
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
重新加入另一条路径。