1. ホーム
  2. assembly

[解決済み] MIPS分岐実行順序(beqz)

2022-02-08 09:42:51

質問事項

このコードの命令の順序を理解するのに問題があります。例えば ベクズ が真でラベル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

解決方法は?

ラベルは、他の命令からアドレスを参照できるようにするためのものです。 実行をブロックするものではありません。 ソースの空白やラベルに関係なく、常に次の命令へ実行が継続されます。

asmのソースは、機械語コードをファイルに取り込むための言語であり、ラベルは機械語コードに現れないことを忘れないでください。


あなたのコードは変です。 あなたのコードには addi $t0,$t0,2 のすぐ後に b 命令であるため、分岐遅延スロットを無効にしても到達することができない。(MARS/SPIMではデフォルト)。 ラベルがないので、他の場所からジャンプしてくる分岐先ではありません。

しかし、分岐遅延スロット(分岐しても分岐後の命令が実行される)のある本物のMIPSであれば b のブランチディレイスロットで 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 を飛び越える必要がないようにするためです。 つまり、片方のパスには1つの取られていない分岐があり、もう片方には取られている beq と無条件に b を使用して、もう一方のパスに再接続します。