编译器生成称为段 的可重定位代码块和数据块,这些代码块以多种方式分配到内存中,以符合各种系统配置。有关各段及其分配的更多信息,请参阅 TMS320C28x 汇编语言工具用户指南 中介绍的目标文件信息。。
段有两种基本的类型:
- 未初始化的段会在存储器中保留空间(通常为 RAM)。程序可以在运行时使用此空间来创建和存储变量。编译器会创建以下未初始化的段:
- .bss 段为未初始化的全局变量和静态变量保留空间。未初始化且也未使用的变量通常创建为通用符号,而不是放置在 .bss 中,以便将该变量从生成的应用中排除。(EABI 仅用于编译器;EABI 和 COFF 用于汇编器)
- .ebss 段为所有静态变量(已初始化或未初始化;全局或局部)保留空间。在程序启动时,C/C++ 引导例程从 .cinit 段(可能在 ROM 中)复制数据,并将其用于初始化 .ebss 段中的变量。(仅限 COFF)
- .stack 段为保留空间。C/C++ 软件栈。此存储器用于将参数传递给函数,并为局部变量分配空间。
- .esysmem 段为动态存储器分配保留空间。此空间由动态存储器分配例程使用,如 malloc、calloc、realloc 或 new。如果 C/C++ 程序不使用这些函数,编译器则不会创建 .esysmem 段。(仅限 COFF)
- .sysmem 段为动态存储器分配保留空间。保留的空间由动态存储器分配例程使用,如 malloc()、calloc()、realloc() 或 new()。如果 C/C++ 程序不使用这些函数,编译器则不会创建 .sysmem 段。(仅限 EABI)
- 初始化段包含数据或可执行代码。初始化段通常是只读的;例外情况如下所示。C/C++ 编译器会创建以下初始化段:
- .args 段包含用于命令行参数的空间。请参阅 --arg_size 选项。
- .binit 段包含引导时复制表。有关 BINIT 的详细信息,请参阅 TMS320C28x 汇编语言工具用户指南。
- .cinit 段包含用于初始化变量和常量的表。C28x .cinit 记录限制为 16 位。这将初始化对象限制为 64K。(对于 EABI,链接器会创建 .cinit 段。对于 COFF,编译器会创建 .cinit 段。)
- .ovly 段包含联合的复制表,其中的不同段具有相同的运行地址。
- .init_array 段包含全局构造函数表。(仅限 EABI)
- .pinit 段包含全局构造函数表。(仅限 COFF)
- .c28xabi.exidx 段包含用于异常处理的索引表。.c28xabi.extab 段包含用于异常处理的堆栈展开指令。有关详细信息,请参阅 --exceptions 选项。(仅限 EABI)
- .ppdata 段包含用于基于编译器的分析的数据表。有关详细信息,请参阅 --gen_profile_info 选项。此段是可写的。
- .ppinfo 段包含用于基于编译器的分析的相关性表。有关详细信息,请参阅 --gen_profile_info 选项。
- .const 段包含字符串文字和使用 C/C++ 限定符 const 定义的变量(即使该常量未定义为 volatile 也是如此,但如果该常量为节 6.5.1 中描述的异常之一,则不是)。字符串文字放置在 .const:.string 子段中,以更大力度地控制链接时放置位置。(仅限 EABI)
- .econst 段包含字符串文字和使用 C/C++ 限定符 const 定义的全局变量(即使该常量未定义为 volatile 也是如此,但如果该常量为节 6.5.1 中描述的异常之一,则不是)。字符串文字放置在 .econst:.string 子段中,以更大力度地控制链接时放置位置。(仅限 COFF)
- .data 段为初始化的非常量静态变量保留空间,无论它们是全局变量还是局部变量。(对于 EABI,编译器会生成此段,用于初始化全局变量和静态变量。对于 COFF,此段可由汇编代码使用,但不能在其他情况下使用。)此段是可写的。
- .switch 段包含用于 switch 语句的表。默认情况下,此段放置在数据存储器中。如果使用 --unified_memory 选项,此段将放置在程序存储器中。
- .text 段包含所有可执行代码和由编译器生成的常量。此段通常是只读的。
- .TI.crctab 段包含 CRC 检查表。
- .TI.bound 段用于将符号与特定存储器地址关联。当使用 LOCATION pragma(请参阅节 6.9.16)或“location”或“preserve”变量属性(请参阅节 6.15.4)将符号与特定存储器地址关联时,将为符号创建一个 .TI.bound 段。如果是“preserve”符号,当 .TI.bound 段在存储器中是连续的之时,链接器可以将其合并成一个输出段,从而减少初始化所需的 CINIT 记录数。此段可以是可写的,也可以是只读的。
- .TI.update 段包含在热启动时需要重新初始化的符号。重新初始化由 __TI_auto_init_warm() RTS 函数执行。建议您在链接器命令文件中添加一个条目,将 .TI.update 段置于适当的存储器区域。此段是可写的。
下表展示了各种类型的初始化变量的放置:
|
EABI |
COFF |
|
全局 |
局部 |
全局 |
局部 |
const |
.const |
* |
.econst |
* |
静态 |
.data |
.data |
.ebss |
.ebss |
字符串常量、文字 |
.const:.string |
.const:.string |
.econst:.string |
.econst:.string |
* 初始化的 const(非静态)局部变量不放置在输出段中;它们根据需要在运行时在存储器(通常是 RAM)中进行初始化。
汇编器会创建默认段 .text、.ebss 或 .bss(取决于 ABI)和 .data。您可以指示编译器使用 CODE_SECTION 和 DATA_SECTION pragma 创建其他段(请参阅节 6.9.4和节 6.9.6)。
链接器从不同的目标文件中获取各个段,并合并具有相同名称的段。表 7-1中列出了生成的输出段,以及每个段在存储器中的适当位置。您可以根据需要将这些输出段放置在地址空间中的任何位置,以满足系统要求。
链接器还会创建一些编译器未引用的其他段。例如,.common 段包含链接器分配的通用块符号。
对于 EABI,建议您使用统一的存储器方案,将所有段放置在第 0 页上。但是,默认链接器命令文件为段指定了第 0 页或第 1 页,如下表所示。通常,未初始化的常量值段由链接器命令文件放置在第 1 页上;所有其他段通常放置在第 0 页上。
表 7-1 段和存储器位置摘要
段 |
存储器类型 |
默认页面 |
.binit |
预计在闪存/ROM 中 |
1 |
.bss(仅 EABI) |
必须在 RAM 中 |
1 |
.ebss(仅 COFF) |
必须在 RAM 中 |
1 |
.c28xabi.exidx(仅 EABI) |
预计在闪存/ROM 中 |
1 |
.c28xabi.extab(仅 EABI) |
预计在闪存/ROM 中 |
1 |
.cinit (1) |
预计在闪存/ROM 中 |
0 |
.const(仅 EABI) |
预计在闪存/ROM 中 |
1 |
.econst(仅 COFF) |
预计在闪存/ROM 中 |
1 |
.data(主要由 EABI 使用) |
必须在 RAM 中 |
0 |
.init_array(仅 EABI) |
预计在闪存/ROM 中 |
0 |
.pinit(仅 COFF) |
预计在闪存/ROM 中 |
0 |
.ppdata |
必须在 RAM 中 |
1 |
.stack |
必须在 RAM 中 |
1 |
.switch |
取决于 --unified_memory 选项设置 |
0,1 |
.sysmem(仅 EABI) |
必须在 RAM 中 |
1 |
.esysmem(仅 COFF) |
必须在 RAM 中 |
1 |
.text |
预计在闪存/ROM 中 |
0 |
(1) .cinit 段由 COFF 的编译器和 EABI 的链接器创建。
可以使用链接器命令文件中的 SECTIONS 指令来自定义段分配过程。有关将段分配到存储器中的更多信息,请参阅 TMS320C28x 汇编语言工具用户指南 中的链接器说明一章。