ASM - 优化的 `for` 循环
ASM - Optimized `for` loop
作业中接到任务,将一段C代码改成简化版的ASM DLX:
a = 0;
for (i = 1; i < 14; i++)
a = a + c;
A[0] = a;
我的解决方案:
假设:
a
的值在寄存器 R1 中
c
的值在寄存器 R2 中
i
的值在寄存器 R3 中
A
的地址值(表示&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
的地址值(表示&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
循环算法:
- 初始化一个变量
- 检查条件是否为
True
。
If True
: 在循环内应用命令,
否则:退出循环。
- 增量变量
- 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 级优化的结果。
作业中接到任务,将一段C代码改成简化版的ASM DLX:
a = 0;
for (i = 1; i < 14; i++)
a = a + c;
A[0] = a;
我的解决方案:
假设:
a
的值在寄存器 R1 中c
的值在寄存器 R2 中i
的值在寄存器 R3 中A
的地址值(表示&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
的地址值(表示&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
循环算法:
- 初始化一个变量
- 检查条件是否为
True
。
IfTrue
: 在循环内应用命令,
否则:退出循环。 - 增量变量
- 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 级优化的结果。