【问题标题】:How does the .bss section copied to RAM?.bss 部分如何复制到 RAM 中?
【发布时间】:2017-03-11 15:49:57
【问题描述】:

我是嵌入式系统低级编程的新手,我很困惑在链接器生成输出目标文件之后以及在刷新 .bin 文件期间究竟发生了什么。

1- 我在链接描述文件中看到 .bss 部分的 可加载内存地址(LMA) 和 虚拟内存地址(VMA) 在 RAM 中,我的问题是自从我在闪存中闪存我的二进制图像后,它最初是如何进入 RAM 的?

2- 我看到的启动代码仅将 RAM 中的 .bss 部分清零,但是如果启动代码没有像使用 .data 部分那样将其复制到 RAM 中,它是如何到达那里的?

【问题讨论】:

  • 您可以通过检查哪些变量转到.bss 以及它们具有哪个初始值来回答这个问题。不清楚你的问题是什么。
  • @Olaf 我知道 .bss 包含未初始化的变量,但我们是否还需要对具有零值的非局部变量的引用?我的意思是我们实际上是闪存 .bss 部分还是我们只是在运行时创建一个填充零的部分?
  • “我明白 .bss 包含未初始化的变量” - 不,它没有!您可能想了解更多有关此内容的信息。另请注意,标准本身和平台相关的标准中甚至都没有提到这一点。
  • .bss section 不是 gcc 中 .data section* 的一部分,而是一个单独的 NOLOAD 部分!检查您的链接器控制文件,阅读 ld 文档。细分是另一回事。 “不,它没有” - 我引用了错误的假设,不清楚你不明白什么,但也许你听从了我的建议并阅读了标准。提示:进入.bss 以支持它的实现的对象初始化!事实上,你自己已经说过了。善意:有时退后一步看全貌是件好事。如果您离得太近,您只会看到彩色圆点。
  • 我认为您的问题是页面底部附近的answered in the manual under output section LMA。通常,您需要一些汇编程序启动代码来将 init 数据 复制到 RAM、设置堆栈并将 BSS 归零。然后你可以调用一个最小的“C”函数。

标签: c linker gnu ld linker-scripts


【解决方案1】:

看起来评论者在很大程度上回答了您的问题,但将其放在这里以供将来可能遇到该问题的人使用:

您在这里看到的是优化。根据定义*,.bss 部分全为 0。虽然您可以将大量零数组写入闪存,然后在启动时将大量零数组复制到 ram,但为什么还要麻烦呢?您真正需要知道的是“重新定位”的 0 数组需要结束的位置。链接器文件通常会定义命名为_sbss_ebss 的符号(通常也称为_szero_ezero)。现在,整个.bss 部分只占用闪存中的两个内存字(_sbss_ebss 符号)。您的启动例程(在main() 之前运行的代码,与复制其他数据的相同)可以执行memset(_sbss, 0, _ebss-_sbss) 之类的操作,并且.bss 部分已设置好并准备就绪。

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

【讨论】:

    猜你喜欢
    • 2021-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-10
    • 2013-05-09
    • 1970-01-01
    • 2013-09-03
    • 2018-07-03
    相关资源
    最近更新 更多