我正在为飞思卡尔Coldfire处理器开发嵌入式C固件。在编写了一些代码之后,我开始研究减少构建大小的方法。我们的空间有限,所以这对我来说很重要。
我意识到我的代码中有几个int32,但我只需要int16。为了节省空间,我尝试用int16替换相关变量。当我构建它时,构建的大小增加了大约60个字节。
我认为这可能是我的结构包装的方式,所以我定义了我希望它包装的方式,但它没有改变。
#pragma pack(push, 1)
// Struct here
#pragma pack(pop)
我可以看到它保持不变,但我无法确定会导致它上升的原因。这有什么想法?可能导致这种情况的原因是什么?
修改
是的,看起来它只是生成额外的指令来说明32位是处理器的优化大小。我应该先检查数据表。
这是生成的额外装配:
0x00000028 0x3210 move.w (a0),d1
0x0000002A 0x48C1 ext.l d1
; Other instructions between
0x0000002E 0x3028000E move.w 14(a0),d0
0x00000032 0x48C0 ext.l d0**
答案 0 :(得分:3)
你的编译器可能会发出int32的代码就好了;它可能是你的架构的自然int大小(这是真的吗?sizeof(int)== 4?)。 我猜测尺寸的增加来自三个地方:
进行对齐工作
32位整数可能在堆栈和其他地方自然对齐, 所以通常不必发出代码以确保" the 堆栈是4字节对齐"。如果你撒上一堆16位的整数 你的代码,可能需要添加填充(帧指针的额外添加 作为修复?)通常一个添加指令覆盖帧/堆栈 维护,但可能会发出额外的指示以保证 对准。
在16位和32位整数之间进行转换
使用32位整数,大多数指令自然起作用。对于较小的整数,有时编译器必须发出切换/切片位的代码 它保留了较小的语义。 (也许做一个额外的AND指令来掩盖 关闭一些高位或OR指令来设置一些位。)
来回追寻记忆
标准LOADS和STORES适用于32位整数(可能是您机器的自然尺寸)。有可能,当它必须存储只有2个字节而不是4时,架构必须发出额外的指令来存储非标准的int(通过切断int,使用编码较长的奇怪指令,或使用位指令来删除指令。
这些都是猜测。最好的方法是查看汇编代码,看看发生了什么!
答案 1 :(得分:0)
为了节省空间,我尝试用int16替换相关变量。 当我构建它时,构建的大小增加了大约60个字节。
这对我来说没什么意义。使用较小的数据类型并不需要转换为较少的指令。它可以在运行软件时减少内存使用,但不一定是构建大小。
因此,例如,在这里使用较小数据类型的原因可能是增加二进制文件的大小可能是因为使用较小类型需要更多指令或更长的指令。例如,对于非字/双字对齐的存储器,编译器可能必须使用更多指令用于未对齐的移动。如果所有通用寄存器都较大,则可能必须使用特殊指令来提取低位/高位字。在这种情况下,除了使用较小类型增加的二进制大小(但代码运行时使用的内存较少)之外,您可能还会获得轻微的性能损失。
可能存在许多场景,它们对您使用的确切编译器和架构都是特定的(汇编代码将揭示确切原因),但简而言之,对变量使用较小类型并不一定意味着更小的构建/更少的指令,并且可能很容易意味着相反。