2017-08-01 64 views
0

我最近開始探索MIPS,我不確定是否理解這段代碼。Mips to C翻譯,兩個for-cycles

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的值是什麼。 我想象中的C譯法是:

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

但是我擔心這條線。

L1: addi s1, $0, 0 

在我看來,我重寫了s1 = 7;與s1 = 0 ;.這是否會在L1或每次迭代中發生?我之所以問,是因爲線路L2: addi s4, s4, 7發生在L2週期的每一次迭代中。

我不確定如果由於我的假設,我的翻譯是正確的。在此先感謝您澄清此代碼中發生的事情。

+2

當然'J = 0'發生爲外部循環的每一次迭代。 – Jester

+0

把它放到SPIM/MARS/... MIPS asm +模擬器中應該有點容易(特別是如果你以後需要使用其中的一個用於將來的任務,那麼早期熟悉它們就不會浪費時間),並嘗試在調試器中通過指令運行它的指令。價值的重寫可能會讓人覺得奇怪,因爲原來的's1 = 7'沒有在任何地方使用,但事實就是這樣。一旦你用CPU跳到「'L1:'」,就沒有辦法避免這個指令,所以當每次'pc'在tick的開頭都等於'L1'時,它就會被執行。 C版本*看起來*正確,但運行它是安全的。 – Ped7g

回答

1

隨着Jester在評論中回答,s1 = 0;發生每一次迭代。

的C譯法是那種正確的,但更準確的C版將是:

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

這應該產生在你的情況相同的結果,但不同的是在for VS do ... while循環的原理,其中for在執行第一次迭代之前執行第一次檢查,而do ... while確實在執行主體語句時至少執行一次,即使條件從false開始。

程序集中的for通常在循環代碼的開始處有比較+條件分支,並以無條件分支結束回到那個開始處(至少在人們爲了可讀性而編寫時,C/C++編譯器可以展開它性能有點差,甚至在編譯時計算穩定的時候預先計算一些部分,就像這樣 - 一個好的C編譯器會把它編譯成return 980;)。

至少godbolt.org用於MIPS的gcc 5.4(-O3)確實產生:

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

感謝您對Ped7g的解釋。現在我懂了。 –