Mips 到 C 的翻译,两个 for 循环

Mips to C translation, two for-cycles

我最近开始研究 MIPS,但我不确定我是否理解这段代码。

  addi s4, [=10=], 0    // s4 = 0; 
  addi s1, [=10=], 7    // s1 = 7;
  addi t2, [=10=], 7    // t2 = 7;
  addi s0, [=10=], 1    // s0 = 1;
  addi t1, [=10=], 21   // t1 = 21;
L1: addi s1, [=10=], 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, [=10=], 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, [=10=], 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, [=12=], 0

在我看来我重写了 s1 = 7; s1 = 0;。这种情况是在 L1 的每次迭代中发生还是只发生一次?我问的原因是因为行 L2: addi s4, s4, 7 发生在 L2 循环的每次迭代中。

由于我的假设,我不确定我对 C 的翻译是否正确。预先感谢您澄清这段代码中发生的事情。

正如 Jester 在评论中回答的那样,s1 = 0; 每次迭代都会发生。

C 翻译有点正确,但更准确的 C 版本应该是:

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

这应该会在您的情况下产生相同的结果,但不同之处在于 fordo ... while 循环的原理,其中 for 在执行之前进行第一次检查第一次迭代,而 do ... while 确实至少执行一次 body 语句,即使条件是 false 从一开始也是如此。

汇编中的 for 通常在循环代码的开头有比较 + 条件分支,并以无条件分支结束回到那个开始(至少在考虑到可读性的人写的时候, C/C++ 编译器可能会为了性能稍微展开它,甚至在编译时计算稳定时预先计算一些部分,就像这个 - 一个好的 C 编译器会把它编译成 return 980;).

MIPS gcc 5.4 (-O3) 至少 godbolt.org 会产生:

    j       
    li      ,980                  # 0x3d4