我是嵌入式系统低级编程的新手,对于链接器生成输出目标文件后,在闪存.bin文件烧录期间会发生什么感到很困惑。
1- 我在链接脚本中看到,.bss段的可加载内存地址(LMA)和虚拟内存地址(VMA)位于RAM中,我的问题是它最初是如何进入RAM的,因为我将二进制映像烧录到FLASH存储器中?
2- 我看到的启动代码只是将RAM中的.bss段清零,但是如果启动代码没有像.data段一样将其复制到RAM中,那么它是如何进入RAM的?
我是嵌入式系统低级编程的新手,对于链接器生成输出目标文件后,在闪存.bin文件烧录期间会发生什么感到很困惑。
1- 我在链接脚本中看到,.bss段的可加载内存地址(LMA)和虚拟内存地址(VMA)位于RAM中,我的问题是它最初是如何进入RAM的,因为我将二进制映像烧录到FLASH存储器中?
2- 我看到的启动代码只是将RAM中的.bss段清零,但是如果启动代码没有像.data段一样将其复制到RAM中,那么它是如何进入RAM的?
看起来评论者们已经回答了你的问题,但我把这个留在这里,以便未来可能会遇到这个问题的人:
你在这里看到的是一种优化。按照定义,.bss
段都是 0。虽然你可以将一个大型零数组写入闪存,然后将其复制到启动时的 RAM 中,但为什么要这样做呢?你真正需要知道的只是“重定位”零数组需要停止的位置。链接器文件通常会定义类似于 _sbss
和 _ebss
(也常见为 _szero
和 _ezero
)的符号。现在,整个 .bss
段在闪存中只占用两个字(即 _sbss
和 _ebss
符号)。你的启动例程(运行在 main()
之前的代码,与复制其他数据的相同操作)可以执行类似于 memset(_sbss, 0, _ebss-_sbss)
的操作,这样 .bss
段就设置好并准备好了。
*在你和大多数现代环境中,.bss
被定义为全零。
.bss
以及它们的初始值来回答这个问题。不清楚你的问题是什么。 - too honest for this site.bss
段 在 gcc 中并不是.data
段 的一部分,而是一个单独的NOLOAD
段!请检查您的链接器控制文件并阅读 ld 文档。一个“segment”是一个不同的概念。“No it does not” - 我引用了错误的假设,不清楚您不理解什么,但也许您可以遵循我的建议并阅读标准。提示:对于支持它的实现,进入.bss
的对象是被初始化的!事实上,您自己已经说明了这一点。善意地提醒:有时候退后一步看整个画面是件好事。如果你离得太近,你只能看到有色的点。 - too honest for this siteint foo;
这样的全局变量,然而这与int foo = 0;
完全相同。 - nos