.bss段如何复制到RAM?

3

我是嵌入式系统低级编程的新手,对于链接器生成输出目标文件后,在闪存.bin文件烧录期间会发生什么感到很困惑。

1- 我在链接脚本中看到,.bss段的可加载内存地址(LMA)和虚拟内存地址(VMA)位于RAM中,我的问题是它最初是如何进入RAM的,因为我将二进制映像烧录到FLASH存储器中?

2- 我看到的启动代码只是将RAM中的.bss段清零,但是如果启动代码没有像.data段一样将其复制到RAM中,那么它是如何进入RAM的?


你可以通过检查哪些变量进入了.bss以及它们的初始值来回答这个问题。不清楚你的问题是什么。 - too honest for this site
@olaf ".bss或bss被许多编译器和链接器用于数据段的一部分,其中包含仅由零值位表示的静态分配变量(即在执行开始时)。它通常被称为“bss节”或“bss段”。这是我在网上找到的关于.bss所持有内容的信息。你说的“不是这样”的意思是什么? - Keith Ape
1
.bss 在 gcc 中并不是 .data 的一部分,而是一个单独的 NOLOAD 段!请检查您的链接器控制文件并阅读 ld 文档。一个“segment”是一个不同的概念。“No it does not” - 我引用了错误的假设,不清楚您不理解什么,但也许您可以遵循我的建议并阅读标准。提示:对于支持它的实现,进入 .bss 的对象是被初始化的!事实上,您自己已经说明了这一点。善意地提醒:有时候退后一步看整个画面是件好事。如果你离得太近,你只能看到有色的点。 - too honest for this site
1
我认为你的问题可以在手册的输出部分 LMA 下找到答案, 该页面底部有详细说明。通常你需要一些汇编启动代码来将初始化数据复制到RAM中,设置堆栈并清零BSS段。然后你就可以调用一个最小化的'C'函数了。 - artless noise
@user2628079 大多数平台都包含启动代码,以在运行时将bss部分清零。但是如何以及是否执行此操作完全取决于平台。还要记住,在C语言中,具有静态存储期且未显式初始化的变量保证会获得它们的0值。也许您所说的“未初始化变量”是指像int foo;这样的全局变量,然而这与int foo = 0;完全相同。 - nos
显示剩余2条评论
1个回答

3

看起来评论者们已经回答了你的问题,但我把这个留在这里,以便未来可能会遇到这个问题的人:

你在这里看到的是一种优化。按照定义,.bss 段都是 0。虽然你可以将一个大型零数组写入闪存,然后将其复制到启动时的 RAM 中,但为什么要这样做呢?你真正需要知道的只是“重定位”零数组需要停止的位置。链接器文件通常会定义类似于 _sbss_ebss(也常见为 _szero_ezero)的符号。现在,整个 .bss 段在闪存中只占用两个字(即 _sbss_ebss 符号)。你的启动例程(运行在 main() 之前的代码,与复制其他数据的相同操作)可以执行类似于 memset(_sbss, 0, _ebss-_sbss) 的操作,这样 .bss 段就设置好并准备好了。

*在你和大多数现代环境中,.bss 被定义为全零。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接