如何获取我的代码的结束地址

我正在为一个课程项目从头开始编写一个实时操作系统。 我想在将代码下载到芯片后知道代码的结束地址,因为我打算使用空闲内存来获取堆栈空间,我需要确保不会覆盖现有代码。

我听说GCC提供的__end变量是代码的结尾,但我不知道__end的含义是什么以及如何在我的代码中使用它。 任何人都可以解释一下或提供一些材料的链接,因为我不能google __end?

非常感谢。

正如Adam Rosenfeld指出的那样,您需要使用链接器控制文件为您定义一个或多个符号,这些符号位于精确正确的位置。

对于gcc和binutils,您将使用ld的链接器脚本语法。 有关我在此处遗漏的所有详细信息,请参阅ld的手册。 它有点不透明,但是如果你要在嵌入式世界中花费大量精力,你应该花一些时间。 它会为你带来回报。

在链接描述文件中,您希望在.text段之前定义一个符号,然后在之后定义一个符号。

Adam提到了PROVIDE()语法,它将起作用。 但如果您可以保证您的名字是唯一的,您可能不需要在PROVIDE中包含该定义。 请注意,这是您必须能够制作的保证,否则您将面临很多混乱的风险。

在我的脚本中,我只是使用类似的东西:

 __SDRAM_CS1 = 0x10000000; 

定义具有常量地址的符号(在这种情况下)指向我们认为SDRAM控制器将映射SDRAM存储器的位置,并且在CI中声明它如下:

 extern unsigned char __SDRAM_CS1[]; 

这样它就可以用在需要知道SDRAM实际位置的代码中。

对于定位.text段结尾的符号,您将在链接描述文件中使用以下内容

 SECTIONS { ... .text { _start_text = .; *(.text); ... _end_text = .; } ... } 

并将开始和结束符号声明为

 extern unsigned char _start_text[]; extern unsigned char _end_text[]; 

在C.然后,起始地址只是_start_text ,文本段的字节长度是_end_text - _start_text

请注意,我遗漏了很多细节。 您可能有一些名为.text以外的部分,必须将它们视为文本段中的部分。 一个主要的例子是只读数据,它们通常可以安全地位于文本段中,因为它已知为const而在嵌入式系统中,如果不必要,则不要将其复制到有价值的RAM中。 此外,数据段的初始值设定项和内部生成的全局对象构造函数列表都位于文本段附近。

是否在图像大小中包含此类内容是您在了解其用途后需要做出的设计决策。

您可以使用链接描述文件。 在您的C代码中,声明:

 // call this whatever you want; the linker will fill this in with the address // of the end of code extern uint32_t endOfCode; 

然后,在链接描述文件中,在.text部分的定义之后立即添加以下内容:

 PROVIDE(endOfCode = .); 

我对链接器脚本不是很熟悉,所以我不能提供一个完整的,有效的例子。 您必须使用默认链接描述文件(我不确定如何获取)并按上述方法对其进行修改,然后使用链接器的-T选项指定它。 祝好运!

而不是把它放在最后,你可能只是声明一个大的静态数组并使用它,没有花哨的编译器或链接器技巧?

好吧,我对GCC并不熟悉,但也许你可以这样做:

 long foo() { int anything[0]; return *(&anything - 1); } long endOfProgram() { return stackPointer(); } 

我在这里要做的是:

  1. 调用endOfProgram()
  2. endOfProgram调用foo,因此endOfProgram的地址被压入堆栈。
  3. 将任何[0]推到foo的堆栈上。
  4. 在任何地址之前抓取元素的位置,这应该是endOfProgram的内存位置。

我的一些语法可能有误,但我希望你能得到我想要做的事情的要点。

编辑:

…或者只是获取一个指向endOfProgram的函数指针的值。 我想那也行得通。