2017-08-01 7 views
0

最近私はMIPSの探索を開始しました。このコードをよく理解しているかどうかはわかりません。Mips to C変換、2サイクルfor

addi s4, $0, 0 // s4 = 0; 
    addi s1, $0, 7 // s1 = 7; 
    addi t2, $0, 7 // t2 = 7; 
    addi s0, $0, 1 // s0 = 1; 
    addi t1, $0, 21 // t1 = 21; 
L1: addi s1, $0, 0 // s1 has new value s1 = 0;? 
L2: addi s4, s4, 7 // s4 += 7; 
    addi s1, s1, 1 // s1 += 1; 
    slt t3, s1, t2 // t3 = (s1 < t2) ? 1 : 0; 
    bne t3, $0, L2 // if t3 != 0 go to L2 
    nop 
    addi s0, s0, 1 // s0 =+ 1; 
    slt t3, s0, t1 // t3 = (s0 < t1) ? 1 : 0; 
    bne t3, $0, L1 // if t3 != 0 go to L1 
    nop 
L3: nop 

問題は、このアセンブラコードの最後にあるs4の値です。

for(int i = 1; i < 21; i++) 
    for(int j = 0; j < 7; j++) 
     s4 += 7; 

私はこのラインと心配しかし: 私はCの変換は次のようになり想像してみてください。

L1: addi s1, $0, 0 

私はs1 = 7を上書きしているようです。 s1 = 0;である。これはL1の繰り返しごとに1回だけ発生しますか?私が尋ねる理由は、L2: addi s4, s4, 7という行がL2サイクルの繰り返しごとに発生するためです。

私の前提のため、私のCへの翻訳が正しいかどうかわかりません。このコードで何が起こっているのかを明確にしてくれてありがとう。

+2

を 'jは= 0 '外側ループの各反復のために起こります。 – Jester

+0

これをSPIM/MARS/... MIPS asm +エミュレータに入れておくのはやや簡単です(特に、後でタスクに使用する必要がある場合は早めに慣れてから時間を無駄にする必要はありません)。デバッガの命令で命令を実行する。元の 's1 = 7'はどこでも使用されていないので、値のオーバーライドは変わっているかもしれませんが、それはその方法です。 CPUを "L1:' "にジャンプすると、その命令を回避する方法はないので、もちろん、tickの始めに' pc'が 'L1'に等しくなるたびに実行されます。 Cバージョン*は正しいように見えますが、安全に実行します。 – Ped7g

答えて

1

Jesterがコメントで回答したので、s1 = 0;はすべての反復で発生します。

Cの翻訳は一種の正しいですが、より正確なCのバージョンは次のようになります。これはあなたのケースで同じ結果を生成する必要があり、その差はfordo ... while対ループの原則である

s4 = 0; 
s1 = 7; 
s0 = 1; 
do { 
    s1 = 0; 
    do { 
     s4 += 7; 
    } while (++s1 < 7); 
} while (++s0 < 21); 

forは、最初の反復の実行に先立って最初のチェックを行いますが、do ... whileは、最初から条件がfalseであっても、少なくとも1回はbody文を実行します。

アセンブリ内のforは、ループコードの先頭にcompare +条件分岐を持ち、その先頭に無条件分岐で終わることがよくあります(少なくとも、人間が読みやすさを考慮して書くと、C/C++コンパイラはコンパイル時に計算が安定しているときには、パフォーマンスのために少しだけ、あるいはいくつかの部分をあらかじめ計算することさえできます。このように、良いCコンパイラはreturn 980;にコンパイルします。 MIPSのGCC 5.4(-03)のための少なくともgodbolt.org

が生じるんもちろん

j  $31 
    li  $2,980     # 0x3d4 
+0

あなたの説明のおかげでPed7g。今私はそれを得る。 –