【问题标题】:Mips to C translation, two for-cyclesMips 到 C 的翻译,两个 for 循环
【发布时间】:2017-08-03 06:21:47
【问题描述】:

我最近开始探索 MIPS,我不确定我是否很好地理解了这段代码。

  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 循环的每次迭代中发生。

由于我的假设,我不确定我对 C 的翻译是否正确。提前感谢您澄清此代码中发生的情况。

【问题讨论】:

  • 当然j = 0 发生在外循环的每次迭代中。
  • 将其放入 SPIM/MARS/... MIPS asm+emulator 中应该有点容易(尤其是如果您以后必须在以后的任务中使用其中之一,那么尽早熟悉它们不要浪费时间),并尝试在调试器中逐条指令运行它。 value 的覆盖可能感觉很奇怪,因为原始的 s1 = 7 没有在任何地方使用,但就是这样。一旦你用 CPU 跳转到“L1:”,就无法避免该指令,所以当然每次在滴答开始时pc 等于L1 时都会执行它。 C 版本看起来正确,但运行它以确保安全。

标签: c mips


【解决方案1】:

正如 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 进行即使条件是false,也至少执行一次body语句。

汇编中的for 通常在循环代码的开头有比较+条件分支,并以无条件分支结束返回到那个开始(至少在考虑到可读性的情况下由人类编写时,C/C++ 编译器可能会展开当计算在编译时稳定时,它有点性能甚至预先计算某些部分,比如这个 - 一个好的 C 编译器会将它编译成 return 980;)。

至少 Godbolt.org for MIPS gcc 5.4 (-O3) 确实产生:

    j       $31
    li      $2,980                  # 0x3d4

【讨论】:

  • 感谢您的解释 Ped7g。现在我明白了。
猜你喜欢
  • 1970-01-01
  • 2013-09-23
  • 1970-01-01
  • 1970-01-01
  • 2011-12-08
  • 2019-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多