繁体   English   中英

C 到 MIPS 汇编 while 循环

[英]C to MIPS assembly while loop

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 代码和汇编代码实际上不匹配。 汇编代码已被优化为使用指针而不是数组引用,并且循环的退出条件也已在循环外复制一次,从而允许循环结构使用更有效的 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 这个循环做的很少,但会检查一些 memory。 我们不得不问:循环的目的是什么,如果不是为循环后面的一些代码设置i 在这里,循环的目的可能是计算重复项,这将导致i成为循环的“输出”/所需结果:在结束时包含重复项的计数,然后运行下一条语句。

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


如果我们尝试将其放入编译器中,我们将被迫将代码片段更改为完整的 function。 编译器不会接受小于 function 的代码语句。

整个 function 定义是您可以提供给编译器的最小代码段(function 定义之外的代码片段不是 C 语言中的合法声明,并且环境为代码片段提供了清晰的包装)

  • 参数是给定的输入
  • 局部变量是临时变量和 scope 之外的 go
  • 返回值是预期的输出。

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

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


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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM