基于体积和成本的考虑,ram会设计的尽可能小,随着功能越来越完善,协议越来越规范,代码空间不足的问题日渐凸显,即使编译器打开优化Os,也还是会遇到代码溢出的问题。
本节针对代码层面去考虑,即 怎么编码更节省代码空间。以下举例代码无特殊说明,均打开了编译优化,优化等级Os。
1 i++与i+1
结论1:没有返回值时,数组偏移使用+1或者++方式,不影响代码内存大小。有返回值时,数组偏移使用+1的方式比++方式少占用2byte字节。
在MIPS指令集中,所有的指令都是32位(4字节)长。然而,在实际编程中,某些指令可能涉及到的操作数较少,因此为了减小程序的大小,可以将这些指令编码为16位长,即2个字节。这类指令称为“半字长指令”(Halfword Instructions)。SLLI333指令就是一种半字长指令,它用于将一个寄存器中的值左移固定的位数,并将结果存入另一个寄存器中。具体来说,在这条指令中,第一个操作数$r3表示目标寄存器,第二个操作数$r1表示源寄存器,#0x1表示要左移的位数。由于这是一条半字长指令,因此它的机器码只有16位长,可以用两个字节来存储。其中,前6位表示操作码和寄存器编号,接下来5位表示移动的位数,最后5位保留。所以这条指令大小为2字节。
结论2:有返回值时,数组偏移使用+1的方式比++方式少占用2byte字节。原因就在于SLLI333指令就是一种半字长指令,只占2字节,sh指令占4字节。
结论3:某种情况下,有返回值时,数组偏移使用+1的方式比++方式占用内存是一样的,可能原因是这两段代码中的数组访问和位运算操作会被编译器优化为相同的 MIPS 指令序列,因此生成的指令是一样的。
CQ偏移使用i++ | CQ偏移使用数字 | |
NF_SetRNDSeedCQ | 0x20 Bytes | 0x20 Bytes |
调用NF_SetRNDSeedCQ的RR_SetDma2CQ | 0x1CE Bytes | 0x1CE Bytes |
不加编译优化NF_SetRNDSeedCQ | 0x84 Bytes | 0x4C Bytes |
调用不加编译优化NF_SetRNDSeedCQ的RR_SetDma2CQ | 0x1CE Bytes | 0x1CE Bytes |
结论4:如果不加编译优化,CQ偏移直接使用数字比i++的方式要将近少占用一半的空间。
2 数组传参
结论5:CQ_SetColAddr里,CQ传参使用CQ地址跟使用基址+偏移的函数大小是一样的,但对调用此函数的函数,会多0xA bytes。
3 volatile变量
结论6:使用temp变量进行运算比直接用volatile变量进行计算能节省4 bytes,尽管看起来代码量是增加的。这是因为使用volatile运算时,每次都要去其地址获取变量最新值,会多几行汇编代码。