ASM - 优化的 `for` 循环

ASM - Optimized `for` loop

作业中接到任务,将一段C代码改成简化版的ASM DLX:

a = 0;
for (i = 1; i < 14; i++)
    a = a + c;
A[0] = a;

我的解决方案:

假设:

然后:

addi R1 R0 0    // init a = 0
addi R3 R0 1    // init i = 1
slti R5 R3 14   // test (i < 14) ; R5 = 1 if i < 14
beqz R5 3       // branch 3 lines of R5 == 0
add R1 R1 R2    // a = a + c
addi R3 R3 1    // i++
beqz R0 -5      // return up to the condition of the for loop
sw R1 R4 0      // A[0] = 0

他们的解决方案:

假设:

然后:

addi R1 R0 0    // a = 0
addi R2 R0 1    // i = 1
add R1 R1 R3    // a = a+c
addi R2 R2 1    // i++
slti R5 R2 14   // R5=1 iff i<14
bnez R5 -4      // jump 4 lines up from the next line if
                // R5!=0, that is if i<14
sw R1 R4 0      // store the new value of A[0]=a (R1)

区别:

他们的解决方案显然更好,因为少了 1 个命令——我的代码有一个额外的条件分支。他们的代码正是我一开始想做的,但后来我想起了for循环算法:

  1. 初始化一个变量
  2. 检查条件是否为 True
    If True: 在循环内应用命令,
    否则:退出循环。
  3. 增量变量
  4. return 至 #2

所以他们的代码不同于 for 循环算法,因为它在初始化 (#1) 之后不检查条件 (#2)...
我心想——这是优化的结果吗? 这是什么级别的优化? (IIRC有4个级别:O0、O1、O2、O3)
在解释C代码时是否期望默认优化代码?

激活优化后,您的编译器会检查其汇编代码以查看是否有任何需要改进的地方,特别是避免无用的指令或检查。

例如,在您的代码中,for 循环是一个初始化,然后是经典的 while 循环。一个经典的优化是在第一个条目中检查 while 条件是否可以为假,如果不能,则在 do while 循环中对其进行转换。
这正是你的情况。 i < 14 如果你在指令 i = 1 之后检查它,它就不会是假的。所以 运行:

更快
a = 0;
i = 1;
do
{
    a = a + c;
    i++;
} while (i < 14);
A[0] = a;

是的,这是一种优化形式。但是当你直接用汇编语言编码时,通常期望你会做这种技巧,因为汇编编程(主要是学习它)的目标是让你的代码尽可能快,使用任何可能性来减少指令调用。

这是 GCC 上 O1 级优化的结果。