【问题标题】:How much is 32 kB of compiled code32kB的编译代码是多少
【发布时间】:2010-08-22 21:23:30
【问题描述】:

我打算使用Arduino programmable board。它们的闪存非常有限,在 16 到 128 kB 之间,无法存储编译后的 C 或 C++ 代码。

有没有办法估计它会代表多少(标准)代码?

我想这很模糊,但我只是在寻找一个数量级。

【问题讨论】:

  • 64k 对任何人来说都足够了!
  • 16kB 表示从“自动链接运行时所需大小的十分之一”到“大约一千条语句”,后者假定编译语句的平均大小为 16 字节。
  • 确保不要静态分配任何大缓冲区。
  • 32kb的编译代码有多少? 10 美元。

标签: c++ c size arduino


【解决方案1】:

size 命令的输出是一个很好的起点,但它并未提供您需要的所有信息。

$ avr-size program.elf
text            data    bss     dec     hex filename

图片的大小通常略大于文本和数据部分的总和。 bss 部分本质上是压缩的,因为它全为 0。可能还有其他相关部分未按大小列出。

如果您的构建系统的设置与我之前用于 AVR 微控制器的系统一样,那么您最终会得到一个 *.elf 文件和一个 *.bin 文件,可能还有一个 *.hex 文件。 *.bin 文件是存储在处理器程序闪存中的实际映像,因此您可以检查其大小以确定程序在编辑时的增长方式。 *.bin 文件是使用 objdump 命令和一些我现在不记得的标志从 *.elf 文件中提取的。

如果您想知道如何猜测您的 C 或 C++ 代码在编译时会产生多少,这要困难得多。当我尝试使用 uint64_t 而不是 uint32_t 时,我观察到函数发生了 10 倍的爆炸,而我所做的只是增加它(这比我想象的要多 5 倍的代码)。这主要是因为 gcc 的 avr 优化不是最好的,但是代码大小的较小变化可能会从看似无害的代码中蔓延出来。

这可能会随着 C++ 的使用而被放大,与 C 相比,C++ 往往会隐藏更多转化为代码的内容。 C++ 隐藏的主要内容是析构函数调用和大量指针解引用,这与对象中的 this 指针以及许多对象对其虚函数表和类静态变量的秘密指针有关。

在 AVR 上,所有这些指针的东西很可能真的加起来,因为指针是寄存器的两倍,并且需要多条指令来加载。此外,AVR 只有少数可用作指针的寄存器对,这会导致大量内容移入和移出这些寄存器。

AVR上小程序的一些小技巧:

  • 尽可能使用uint8_tint8_t 而不是int。如果您希望代码可移植,也可以使用uint_fast8_tint_fast8_t。这可能导致许多操作只占用一半的代码,因为int 是两个字节。

  • 非常了解字符串和结构常量和文字等内容以及它们的存储方式/存储位置。

  • 如果您不害怕,请阅读 AVR 组装手册。您可以了解指令的类型,以及可以轻松映射到这些指令的 C 代码类型。使用那种 C 代码。

【讨论】:

  • 感谢您的回答,尤其是所有实用的建议。
  • 这都是非常理论化的。我搜索的内容以及我想很多人对 micros 搜索不熟悉的内容是简单的示例和判断库大小的方法,在 C 与 C++ 中完成的一些简单 LED PWM 有多大,是否有常见大小的列表Arduino 上使用的库,诸如此类。
【解决方案2】:

你不能在那里说。未编译代码的长度与已编译代码的长度关系不大。例如:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

int main()
{
  std::vector<std::string> strings;
  strings.push_back("Hello");
  strings.push_back("World");
  std::sort(strings.begin(), strings.end());
  std::copy(strings.begin(), strings.end(), std::ostream_iterator<std::string>(std::cout, ""));
}

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

int main()
{
  std::vector<std::string> strings;
  strings.push_back("Hello");
  strings.push_back("World");
  for ( int idx = 0; idx < strings.size(); idx++ )
    std::cout << strings[idx];
}

两者的行数完全相同,并产生相同的输出,但第一个示例涉及 std::sort 的实例化,这可能比此处的其余代码多一个数量级。

如果您绝对需要计算程序中使用的字节数,请使用汇编程序。

【讨论】:

  • 除了最后一句话外一切都好!人们在有限的空间环境中愉快地用 C(和 C++)编写代码。
  • 即使使用汇编程序,您也需要知道每条指令有多少字节,因为(至少在某些平台上)汇编助记符和字节之间没有固定的关系。因此,无论哪种方式,您都将编译/组装代码并查看结果有多大。
  • @Kieth:我从来没有说过你必须在有限的空间环境中使用汇编程序。我说过,如果您需要绝对确定代码大小将如何影响二进制大小,这就是您必须要做的。生成的代码量与输入代码大小不成正比,即使在 C 和 C++ 中也是如此。 @Pete:这是真的——我曾经为使用过的固定宽度指令(PIC 和 MIPS)编写过汇编程序的每个平台。当然,如果您正在编写 x86 之类的东西,那么即使汇编程序也无法帮助您,但至少它与程序大小的关系比 C 或 C++ 源代码更直接。
【解决方案3】:

下载 arduino IDE 并“验证”一些现有代码,或查看示例草图。它会告诉您该代码有多少字节,这将使您了解给定设备可以容纳多少字节。随机挑选几个示例,web server 示例为 5816 字节,LCD hello world 为 2616。两者都使用外部库。

【讨论】:

【解决方案4】:

尝试为您的应用创建一个简化版本,首先关注最有价值的功能,然后开始添加“值得拥有的好(又酷)的东西”。验证代码时,请注意 Arduino IDE 中显示的字节使用情况。

作为粗略的指示,我的第一个应用程序(由按钮控制的 LED 闪光灯)需要 1092 字节。这大约是 32k 中的 1K。 C++ 代码的占用空间非常小!

最让我担心的是有限的 RAM (1 Kb)。如果 CPU 堆栈占用了其中的一部分,那么创建任何数据结构的余地就不多了。

我的 Arduino 只用了 48 小时,所以还有很多东西可以有效地使用它;-) 但是使用起来很有趣:)。

【讨论】:

  • 感谢您的反馈和建议 :) 玩得开心您的 Arduino。
【解决方案5】:

对于一个相当复杂的软件来说,这是相当多的,但如果你希望它有很多不同的功能,你就会开始遇到限制。此外,如果您想存储大量静态字符串和数据,它可以很快吃掉。但是 32 KB 对于嵌入式应用程序来说是一个不错的数量。您首先遇到问题的往往是 RAM!

此外,嵌入式系统的 C++ 编译器通常比 C 编译器差很多。 也就是说,它们远不及通用桌面操作系统的 C++ 编译器(在为目标平台生成高效机器代码方面)。

【讨论】:

  • 感谢您的反馈 :) 我们将看看使用 C++/OOP 是否会损失很多空间/RAM。
【解决方案6】:

在 linux 系统中,您可以使用静态编译的示例程序进行一些实验。例如

$ size `which busybox `
text            data    bss     dec     hex filename
1830468    4448   25650 1860566  1c63d6 /bin/busybox

大小以字节为单位。此输出与可执行文件格式无关,因为文件格式内不同部分的大小。文本部分包含机器代码和 const stufff。数据部分包含变量静态初始化的数据。 bss大小是未初始化数据的大小——当然未初始化数据不需要存放在可执行文件中。)

嗯,busybox 包含很多功能(如所有常见的 shell 命令、shell 等)。

如果您使用 gcc -static 链接自己的示例,请记住,您使用的 libc 可能会显着增加程序大小,并且使用嵌入式 libc 可能会更节省空间。

要测试你可以查看diet-libcuclibc 并链接到它。实际上busybox通常是和uclibc链接的。

请注意,您通过这种方式获得的尺寸只给您一个数量级。例如,您的工作站可能使用了与 arduino 板不同的 CPU 架构,并且不同架构的机器代码的大小可能或多或少有所不同(因为操作数大小、可用指令、操作码编码等等)。

继续粗略的数量级推理,busybox 包含大约309 tools(包括 ftp 守护进程和类似的东西),即,busybox 工具的平均代码大小大约是 5k。 p>

【讨论】:

  • 我看不出这是 linux 特有的。 Windows 有类似的实用程序,即 FileAlyzer。其他 unixen 也完全可以使用 size,而不仅仅是 linux。
  • 这里的文件大小是 183 kB ?我不熟悉size 命令(真丢脸)。
  • 这不具有代表性,您将引入(真实的)巨大的库和 elf 格式本身的开销,与 arduino 上的二进制文件相比,这将是巨大的。
  • @Billy ONeal:我什至没有写这是特定于 linux 的。这是 linux 特有的,因为busybox 是 linux 特有的。当然,size utility 也可以在其他 unices 上使用。但同样,我没有写相反的内容。
  • @nos:我已经提到了不同库的影响。查看文本值是与精灵无关的(它是部分的大小),还是?此外,请不要说海报要求“数量级”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多