ARM内核架构(四)——RO、RW、ZI和.text .bss .data

本文详细介绍了ARM架构中RO、RW及ZI段的作用与区别。RO段包含只读代码和常量;RW段存放初始化为非0值的变量;ZI段则用于未初始化或初始化为0的变量。

ARM内核架构(四)——RO、RW、ZI和.text .bss .data

小狼@http://blog.csdn.net/xiaolangyangyang


RO段包括只读代码段(code段/.text段)和常量段(RO Data段/.constdata段)

  1. RW段(.data段)指已被初始化成非0值的变量段
  2. ZI段(.bss段)指未被初始化或初始化为0的变量段
<think>嗯,用户问的是嵌入式系统中的段(section)与内存数据类型的对应关系,还要求具体示例。这个问题涉及编译链接内存管理的底层知识,用户可能是嵌入式开发工程师或相关专业学习者。 从用户引用的资料来看,ta已经对.bss.data等基础概念有所了解,但需要更系统的梳理。特别注意到用户提到“hex文件中的信息”,说明ta关注的是实际烧录文件与运行时内存的关系。 需要重点解释几个关键点: 1)编译阶段生成的段(.text/.data/.bss)如何映射到最终的内存区域 2)Code/RO-data等内存数据类型的具体含义 3)ZI-data的特殊性——它不占用烧录文件空间但需要运行时初始化 用户给出的参考材料[1]提到启动代码对.bss段的初始化操作,这点很重要,应该在示例中体现。参考材料[2]展示的汇编数据段定义正好可以作为.data段的实例。 考虑到嵌入式开发的实际需求,准备用STM32的示例最合适,因为: - 主流MCU平台 - 有清晰的链接脚本(.ld文件) - 启动代码(startup_stm32.s)能展示初始化过程 在解释关系时要注意层次: 先说明源文件编译后生成三种段 再说明链接时这些段被归类到种内存数据类型 最后说明烧录文件(hex/bin)实际只包含前三类数据 用户可能隐含的问题是:为什么ZI-data不存储在flash里?这涉及到嵌入式系统节省存储空间的设计思想,需要强调“用时间换空间”的策略——牺牲少量启动时间初始化RAM,换取flash空间的节约。 关于stack/heap的疑问:虽然问题没直接问,但引用[1]提到了,应该简要说明它们属于ZI-data但不由编译器预初始化,而是由启动代码配置。 最后设计示例时,要确保: - C代码包含所有数据类型(const/全局变量/静态变量等) - 映射表展示准确的大小关系 - 特别标注.bss初始化的实际动作</think>好的,我们来详细解释嵌入式系统中常见的段(`.text`, `.data`, `.bss`)与内存数据类型(`Code`, `RO-data`, `RW-data`, `ZI-data`)之间的关系,并提供具体示例。 **核心关系总结:** * **`.text`段** 主要对应 **`Code` (可执行代码)** **`RO-data` (只读数据)**。 * **`.data`段** 对应 **`RW-data` (已初始化的读写数据)**。 * **`.bss`段** 对应 **`ZI-data` (未初始化或初始化为0的读写数据)**。 **详细解释与示例:** 1. **`.text` 段 (代码段):** * **内容:** 主要包含程序的**可执行机器指令**。通常还包括**字符串常量**标记为 `const` 的**全局/静态变量**(如果它们被编译器优化放置在此段)。 * **内存属性:** `Read-Only (RO)`。程序运行时不能修改此段内容。 * **映射关系:** * **`Code`:** `.text` 段中的可执行指令部分就是 `Code`。 * **`RO-data`:** `.text` 段中包含的字符串常量、`const` 全局/静态变量(如果放在这里)属于 `RO-data`。 * **存储位置:** 存储在**Flash**(或ROM)中。程序运行时直接从Flash执行(或加载到RAM执行,取决于架构配置)。 * **烧录文件:** 该段内容**直接包含**在最终的烧录文件(如`.hex`, `.bin`)中。 2. **`.data` 段 (数据段):** * **内容:** 包含**已初始化**且**初始值非零**的**全局变量****静态变量**。 * **内存属性:** `Read-Write (RW)`。程序运行时可以读写这些变量。 * **映射关系:** 直接对应 **`RW-data`**。 * **存储位置:** 存储在**Flash**中,但在**程序启动时**会被**复制**到**RAM**中对应的地址空间。程序运行时访问的是RAM中的副本。 * **烧录文件:** 该段内容(变量的初始值)**直接包含**在最终的烧录文件中(存储在Flash部分)。启动代码负责将这些初始值从Flash复制到RAM中。 3. **`.bss` 段 (Block Started by Symbol):** * **内容:** 包含**未初始化**或**显式初始化为0**的**全局变量****静态变量**。 * **内存属性:** `Read-Write (RW)`。程序运行时可以读写这些变量。 * **映射关系:** 直接对应 **`ZI-data` (Zero-Initialized Data)**。 * **存储位置:** **不占用Flash存储空间存储初始值**。链接器只在烧录文件中记录其在RAM中的**起始地址****总大小**。 * **运行时初始化:** **在程序启动时(由启动代码负责)**,在RAM中为`.bss`段分配空间,并将该段包含的所有内存区域**初始化为0**。这就是为什么`.bss`段需要初始化的原因[^1]。 * **烧录文件:** **不包含**`.bss`段变量的初始值(因为它们都是0或未定义)。烧录文件只包含其**在RAM中的位置大小信息**,供启动代码使用。 **`Stack` `Heap`:** * 它们不属于编译器预定义的`.text`, `.data`, `.bss`段,而是**运行时动态管理**的内存区域。 * **`Stack` ():** 用于存储函数调用时的局部变量、参数、返回地址等。由编译器/启动代码预先分配一块RAM空间,通过栈指针管理。通常属于ZI区域(启动时只需分配空间,内容由程序运行填充)。 * **`Heap` ():** 用于程序运行时动态申请内存(如C中的`malloc`, C++中的`new`)。由启动代码初始化堆管理器(如`__heap_base`),程序通过特定函数申请释放。堆空间也属于ZI区域。 * 在内存类型统计中,栈堆占用的空间通常被归类到**`ZI-data`** 的总量中,因为它们也是启动时在RAM中分配但无需初始值(或初始值无意义)的读写区域。 **具体示例 (基于STM32等典型ARM Cortex-M MCU):** 假设我们有如下C代码片段 (`main.c`): ```c #include <stdint.h> // RO-data (可能位于 .text 段或专用的 .rodata) const uint32_t const_array[3] = {0xDEADBEEF, 0xCAFEBABE, 0x0BADF00D}; // 初始化的常量数组 (RO) const char welcome_message[] = "Hello, Embedded World!"; // 字符串常量 (RO) // RW-data (.data) uint32_t global_counter = 42; // 已初始化的全局变量 (RW) static float sensor_calibration = 3.14f; // 已初始化的静态变量 (RW) // ZI-data (.bss) uint8_t rx_buffer[1024]; // 未初始化的全局数组 (ZI) static uint32_t internal_state; // 未初始化的静态变量 (ZI, 隐含初始化为0) int main(void) { // Stack (ZI) - 局部变量 int local_var = 10; char local_str[] = "Stack String"; // Heap (ZI) - 动态分配 uint32_t *dynamic_array = (uint32_t*)malloc(50 * sizeof(uint32_t)); // ... 程序逻辑 ... global_counter++; rx_buffer[0] = 0xAA; free(dynamic_array); return 0; } ``` **编译链接后内存区域的映射关系:** | 源文件中的对象/区域 | 编译器生成的段 (Section) | 最终内存数据类型 | 存储位置 (初始) | 运行时位置 | 烧录文件包含初始值? | 启动时动作 | | :------------------------ | :----------------------- | :--------------- | :-------------- | :--------- | :------------------- | :--------- | | `const_array[3]` | `.rodata` (或 `.text`) | RO-data | Flash | Flash/RAM* | Yes | () | | `welcome_message[]` | `.rodata` (或 `.text`) | RO-data | Flash | Flash/RAM* | Yes | () | | `main()` 函数代码 | `.text` | Code | Flash | Flash/RAM* | Yes | () | | `global_counter` | `.data` | RW-data | Flash | RAM | Yes (初始值42) | 复制到RAM | | `sensor_calibration` | `.data` | RW-data | Flash | RAM | Yes (初始值3.14) | 复制到RAM | | `rx_buffer[1024]` | `.bss` | ZI-data | () | RAM | **No** | 分配RAM并清零 | | `internal_state` | `.bss` | ZI-data | () | RAM | **No** | 分配RAM并清零 | | 函数调用中的 `local_var` | (无,运行时在栈上分配) | ZI-data (栈部分) | () | RAM (栈区) | **No** | 栈指针初始化 | | `local_str[]` | (无,运行时在栈上分配) | ZI-data (栈部分) | () | RAM (栈区) | **No** | 栈指针初始化 | | `dynamic_array` 指向的空间| (无,运行时在堆上分配) | ZI-data (堆部分) | () | RAM (堆区) | **No** | 堆管理器初始化 | **查看结果 (ARM GCC/ld为例):** 链接器(ld)在生成最终的可执行文件(如`.elf`)后,通常会生成一个内存映射摘要(`Memory region Used Size`),例如: ``` Memory region Used Size Region Size %age Used FLASH: 1676 B 512 KB 0.32% // 包含 Code, RO-data, RW-data的初始值 RAM: 1140 B 128 KB 0.87% // 包含 RW-data运行时副本 + ZI-data (包括.bss, stack, heap预留) ``` * **FLASH Used:** 等于 `Code` + `RO-data` + `RW-data`的初始值大小。 * **RAM Used:** 等于 `RW-data`(运行时大小) + `ZI-data`(包括`.bss`、栈预留空间、堆预留空间)的大小。 **引用说明:** [^1]: 如引用所述,`.bss`段在烧录文件(hex)中只有位置大小信息,没有实际数据。MCU启动时,启动代码会读取这些信息,在RAM中分配对应大小的区域并将其初始化为0。这是`.bss`段的关键特性,也是它不占用Flash存储空间的原因。 [^2]: 引用[2]展示了汇编语言中已初始化数据段(类似`.data`段)的定义方式 (`DD`指令定义双字数据),说明了变量在内存中的实际布局。 **总结:** * **`.text` -> `Code` + `RO-data`**: 程序核心(指令+常量),存储在Flash,运行时通常只读。 * **`.data` -> `RW-data`**: 有非零初始值的全局/静态变量。初始值在Flash,运行时副本在RAM。 * **`.bss` -> `ZI-data`**: 未初始化或零初始化的全局/静态变量。**不占用Flash存储初始值**,启动时在RAM分配空间并清零。 * **`Stack`/`Heap`**: 动态内存区域,通常归类到运行时`ZI-data`总量中,由启动代码预留空间。 * **启动代码**: 是连接烧录文件(Flash内容)运行时内存(RAM)的关键桥梁,负责`.data`段的复制`.bss`段(及栈/堆预留空间)的初始化[^1]。 理解这些段内存数据类型的关系,对于分析嵌入式程序的存储空间占用(Flash大小)、内存占用(RAM大小)、启动过程以及优化内存使用至关重要。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值