【问题标题】:C to MIPS assembly while loopC 到 MIPS 汇编 while 循环
【发布时间】:2021-01-27 16:03:52
【问题描述】:

C 语言

while (save[i] == k) 
i += 1;

i→ $s3

k → $s5

base addr of save → $s6
        
          sll $t1, $s3, 2        #$t1 = 4*$s3
          add $t1, $t1, $s6      #$t1 = address of save[i]
          lw $t0, 0($t1)         #t0 = save[i]
          bne $t0, $s5, Exit     #$t0!=$s5 Exit
    Loop: addi $s3, $s3, 1       #i+=1
          addi $t1, $t1, 4       #point to next cell
          lw $t0, 0($t1)         #t0 = save[i]
          beq $t0, $s5, Loop     #$t0==$s5 loop again
    Exit:

我想问的是,addi $s3, $s3, 1这行是否必要?

因为,无论如何 $ t1 增加了 4。

【问题讨论】:

    标签: c assembly while-loop mips


    【解决方案1】:

    C 代码和汇编代码实际上并不匹配。汇编代码已优化为使用指针而不是数组引用,并且循环的退出条件也已在循环外复制一次,从而允许循环结构使用更有效的 do while 循环(在迭代期间更有效,因为它与 while 循环的直接代码相比,在末尾保存一个无条件分支)。

    请注意,这些优化不仅在汇编中可行,在 C 中也可行。

    C 版本的程序集如下:

    int *sp = save + i; // in C this addition is automatically scaled by 4
    if ( *sp == k ) {
        do {
            i++;
            sp++;   // this C +1 is scaled so really is +4
        } while ( *sp == k );
    }
    

    当然,这在逻辑上等价于另一个。

    你的问题是:我们需要i++;吗?

    一个答案是:不,不在循环中。您是正确的,循环不使用 i 并且会访问数组的相同元素,并在与原始的更简单的 C 循环相同的点退出。

    另一个答案是:是的,如果在循环之后使用i! 这个循环做的很少,但会检查一些内存。我们不得不问:循环的目的是什么,如果不是为循环后面的一些代码设置i?这里循环的目的可能是计算重复项,这将导致 i 成为循环的“输出”/期望结果:在结束时包含重复项计数,并且运行下一条语句。

    这就是为什么很难对小sn-ps代码进行推理的原因之一——本质上我们无法判断接下来会发生什么以及是否会使用i。但是如果不使用i,那么循环就没有任何价值了..


    如果我们尝试将其放入编译器中,我们将不得不将 sn-p 更改为完整的函数。编译器不会接受小于函数的代码语句。

    完整的函数定义是您可以提供给编译器的最小代码段(函数定义之外的代码 sn-ps 在 C 语言中不是合法的语句),并且包装使代码 sn-p 的环境清晰:

    • 参数是给定的输入
    • 局部变量是临时的,超出范围
    • 返回值是预期的输出。

    (当然也有副作用,比如排序比函数更持久的东西,或者创建比函数更持久的堆对象。)

    包裹在一个函数中,然后我们可以确定地观察在循环之后是否使用了局部变量i。


    当然,还有另一种方法可以在循环之后计算i 的值,而无需在循环期间递增它。在循环之后,以下语句将恢复 i 应该具有的值:

    i = sp - save;  // NB: C pointer subtraction automatically descales
    

    在汇编中,这将是减法,然后右移 2 以从字节差值到整数索引值。

    (请注意,这些优化和转换很容易被淘汰,因此请检查工作。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-27
      • 1970-01-01
      • 2015-07-08
      • 2011-08-26
      相关资源
      最近更新 更多