有没有办法在编译时访问 __bss_end 的位置?

问题描述

我想在我的代码中访问 bss 部分末尾的地址,并在编译时对其进行操作。我正在使用 avr-gcc 为 ATmega328p 编译。 (当然:))

目的是将剩余的 RAM(在 Arduino 上)分成偶数段。我已经结束了 RAM,只是不是全局变量未占用的开始。该程序假定没有动态内存分配。

我知道该位置在预处理器时或编译时不可用。但是,它应该在代码上传之前可用。

现在我有

extern uint16_t __bss_end;

然后再

Serial.println((uint16_t) &__bss_end);

哪个有效。它打印 0x0F00 (RAMSTART) + 使用的字节数。但是,这会迫使我在运行时计算分区位置,然后需要我将分区位置存储到变量中,浪费宝贵的 RAM。

所以我想我的观点是:如何在编译时使用 __bss_end 计算这些常量(分区位置)? (或者,真的,任何等价物)。

这只是一个有趣的项目,不是为了实用。

解决方法

__bss_end 由链接器计算为创建可执行文件的最后阶段之一,当它适合所有目标代码时。

由于链接器计算发生在所有编译步骤之后,它显然不能在编译时直接可用,但是,一种选择是从一个构建中获取 __bss_end 的值并将您获得的值应用到另一个作为编译时间常数,然后在启动时断言新版本中的运行时 __bss_end 等于您计算的编译时版本。