c - 浮点数及其对 8 位微控制器内存的影响
问题描述
我目前正在开发一个项目,该项目包括在 stm-8 微控制器上使用 linux 中的 SDCC 编译器进行裸机编程。芯片中的内存非常低,所以我试图保持精简。我已经使用了 8 位和 16 位变量,一切都很顺利。但最近我遇到了一个问题,我真的需要一个浮点变量。因此,我编写了一个函数,该函数将 16 位值转换为浮点数,并执行我需要的数学运算并返回一个 8 位数字。这导致我在 MCU 上的最终编译代码从 1198 字节变为 3462 字节。现在我明白了使用浮点是内存密集型的,并且可能需要调用许多函数来处理浮点数的使用,但是将程序的大小增加这么多似乎很疯狂。
规格:MCU stm8151f2 编译器:带有 --opt_code_size 选项的 SDCC
int roundNo(uint16_t bit_input)
{
float num = (((float)bit_input) - ADC_MIN)/124.0;
return num < 0 ? num - 0.5 : num + 0.5;
}
解决方案
要确定为什么代码在您的特定工具链上如此之大,您需要查看生成的汇编代码,并查看 FP 支持调用它的内容,然后查看映射文件以确定每个函数的大小。
作为使用 GCC 5.4.0 的Godbolt-Os
for AVR 的示例(Godbolt 不支持 STM8 或 SDCC,因此这是作为 8 位架构进行比较),您的代码生成 6364 字节,而空函数生成 4081 字节。所以代码体所需的附加代码是 2283 字节。现在考虑到您同时使用不同的编译器和体系结构这一事实,这些与您的结果并没有什么不同。在生成的代码(下面)中rcall
查看子例程的 s,例如__divsf3
- 这些是大部分代码所在的位置,我怀疑 FP 除法是迄今为止更大的贡献者。
roundNo(unsigned int):
push r12
push r13
push r14
push r15
mov r22,r24
mov r23,r25
ldi r24,0
ldi r25,0
rcall __floatunsisf
ldi r18,0
ldi r19,0
ldi r20,0
ldi r21,lo8(69)
rcall __subsf3
ldi r18,0
ldi r19,0
ldi r20,lo8(-8)
ldi r21,lo8(66)
rcall __divsf3
mov r12,r22
mov r13,r23
mov r14,r24
mov r15,r25
ldi r18,0
ldi r19,0
ldi r20,0
ldi r21,0
rcall __ltsf2
ldi r18,0
ldi r19,0
ldi r20,0
ldi r21,lo8(63)
sbrs r24,7
rjmp .L6
mov r25,r15
mov r24,r14
mov r23,r13
mov r22,r12
rcall __subsf3
rjmp .L7
.L6:
mov r25,r15
mov r24,r14
mov r23,r13
mov r22,r12
rcall __addsf3
.L7:
rcall __fixsfsi
mov r24,r22
mov r25,r23
pop r15
pop r14
pop r13
pop r12
ret
您需要对工具链生成的代码执行相同的分析才能回答您的问题。毫无疑问,SDCC 能够生成汇编列表和映射文件,这将允许您准确确定正在生成和链接的代码和 FP 支持。
最终,尽管在这种情况下您完全没有必要使用 FP:
int roundNo(uint16_t bit_input)
{
int s = (bit_input - ADC_MIN) ;
s += s < 0 ? -62 : 62 ;
return s / 124 ;
}
与空函数相比,Godbolt 2283 字节。仍然有点大,但最有可能的问题是 AVR 缺少DIV
指令所以调用__divmodhi4
. STM8 具有DIV
16 位除数和 8 位除数,因此在您的目标上它可能会明显更小(并且更快)。
推荐阅读
- java - 填充给定形状的选项数
- html - 在鼠标悬停之前隐藏 Blazor HTML 链接
- python - 如何使用 regix (re) 模块从字符串中提取数字
- google-apps-script - 如何将 Google 表格作为电子邮件附件发送?
- c++ - _mm256_load_ps 在调试模式下导致 google/benchmark 出现分段错误
- angular - Angular - 在按钮点击时切换两个类
- c# - 如何通过 OPC 基础 UA-.net 标准库正确使用 OPC UA 中的 TypeDefinition 和 Object 实例
- javascript - 如何使用 setimage discord.js 使图像更大
- c# - 在 GLSL 中复制 GL 中间模式光照模型
- zsh - 杀死特定屏幕