背景:
我正在研究 ARM 目标,更具体地说是 ST 的 Cortex-M4F 微控制器。在这样的平台(通常是微控制器)上工作时,显然没有操作系统;为了获得一个有效的 C/C++“环境”(此外,在变量初始化方面符合标准),必须有某种启动代码在重置时运行,在显式调用main
. 正如我所暗示的,此类启动代码必须初始化已初始化的全局和静态变量(例如int foo = 42;
在全局范围内)并将其他全局变量(例如在全局范围内)清零int bar;
。然后,如有必要,将调用全局“ctors”。
在微控制器上,这仅仅意味着启动代码必须为每个初始化的全局(全部在“.data”部分中)将数据从闪存复制到 ram,并清除其他(全部在“.bss”中)。因为我使用 GCC,所以我必须提供这样的启动代码,我很高兴地分析了几个启动代码(及其相关的链接器脚本!)捆绑了我在 Internet 上找到的大量示例,所有示例都使用我正在开发的同一个演示板.
问题:
如前所述,我见过许多启动代码,它们以不同的方式初始化全局变量,其中一些在空间和时间方面比其他的更有效。但它们都有一些奇怪的共同点:它们没有使用memset
nor memcpy
,而是使用手写循环来完成这项工作。由于在可能的情况下使用标准函数对我来说似乎很自然(简单的“DRY 原则”),我尝试了以下方法来代替最初的手写循环:
/* Initialize .data section */
ldr r0, DATA_LOAD
ldr r1, DATA_START
ldr r2, DATA_SIZE
bl memcpy /* memcpy(DATA_LOAD, DATA_START, DATA_SIZE); */
/* Initialize .bss section */
ldr r0, BSS_START
mov r1, #0
ldr r2, BSS_SIZE
bl memset /* memset(BSS_START, 0, BSS_SIZE); */
...而且效果很好。节省的空间可以忽略不计,但现在显然很简单。
所以,我想了想,在这种情况下我认为没有理由做手写循环:
memcpy
并且memset
很可能无论如何都链接到可执行文件中,因为程序员会直接使用它,或者通过另一个库间接使用它;- 它更小;
- 速度不是启动代码的一个非常重要的因素,但它可能更快;
- 几乎不可能弄错。
知道为什么不依赖memcpy
和memset
启动代码吗?