1

在作业中,我收到了一项将 C 代码更改为简化DLX的 ASM 的任务:

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

我的解决方案:

假设:

  • 的值a在寄存器 R1 中
  • 的值c在寄存器 R2 中
  • 的值i在寄存器 R3 中
  • A(means )的地址值&A在寄存器 R4 中

然后:

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

他们的解决方案:

假设:

  • 的值a在寄存器 R1 中
  • 的值i在寄存器 R2 中(注意这里的变化)
  • 的值c在寄存器 R3 中(注意这里的变化)
  • A(means )的地址值&A在寄存器 R4 中

然后:

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. 返回#2

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

4

1 回答 1

2

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

例如,在您的代码中,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 级优化的结果。

于 2015-09-27T13:05:15.910 回答