2017-08-01 73 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的解释。现在我懂了。 –