keil编译产生的代码段分析

Keil编译产生的代码段如下:Code (inc. data), RO-data, RW-data, ZI-data这几个段。

Code (inc. data): 网上大多说的是程序代码所占的字节数。

  但是这种说法并不完全,在官方文档中有这么一句话:Shows how many bytes are occupied by code. In this image, there are 3712 bytes of code. 

  This includes 1580 bytes of inline data (inc. data), for example, literal pools, and short strings.  

  (大意如此:显示代码占用了多少字节。 在上面的这个表中,有3712个字节的代码。 这包括1580字节的内联数据,例如文字池和短字符串)   

  所以,Code中不仅仅包含了代码的大小,其中还包括了inline data(内联数据),比如literal pools(文字池)和short strings(短字符串)。

​RO-data:表示程序中的只读常量数据。比如const类型的数据 (除inline data之外的只读数据)。

​RW-data:表示可读写变量的大小,也就是说是程序中已经初始化的变量大小。

​ZI-data:表示程序中未初始化的变量大小。就是程序中已经定义但是初始化值为0,或者是没有初始化赋值的变量(编译器会默认把没有赋值的变量自动赋值为0)。

代码段在存储器中的位置:

ROM:也就是下载到单片机FLASH中的数据为:  Code + RO-data + RW-data 。

  为什么不把ZI-data 也下载进去呢? 其实是没有必要的,这是浪费空间,只要程序一上电运行就会把ZI-data 自动清0。

RAM:程序运行时所加载的代码为: RW-data + ZI-data。

所以一个程序所占存储器空间大小为:ROM(Flash) = Code + RO Data + RW Data;   RAM = RW-data + ZI-data。

编译完工程会生成一个. map 的文件,该文件说明了各个函数占用的尺寸和地址,在文件的最后几行也说明了上面几个字段的关系:

其中,RW Size 包含了 RW-data 及 ZI-data,也是运行时占用的 RAM 的大小;

ROM Size 包含了 Code、RO Data 以及 RW Data,也是烧写程序时所占用的 Flash 空间的大小。

程序运行之前,需要将编译生成的 bin 或者 hex 文件烧录到 STM32 的 Flash 中,该被烧录文件称为可执行映像文件。

如下图所示,左侧是可执行映像文件烧录到 STM32 后的内存(下图中的内存理解为存储器,包括ROM+RAM)分布,

它包含 RO 段和 RW 段两个部分:其中 RO 段中保存了 Code、RO-data 的数据,RW 段保存了 RW-data 的数据,由于 ZI-data 都是 0,所以未包含在映像文件中。

STM32 在上电启动之后默认从 Flash 启动,启动之后会将 RW 段中的 RW-data(初始化的全局变量)搬运到 RAM 中,

但不会搬运 RO 段,即 CPU 的执行代码从 Flash 中读取,另外根据编译器给出的 ZI 地址和大小分配出 ZI 段,并将这块 RAM 区域清零。

其中动态内存堆为未使用的 RAM 空间,应用程序申请和释放的内存块都来自该空间。

举个栗子:

sensor_value 存放在 ZI 段中,系统启动后会自动初始化成零(由用户程序或编译器提供的一些库函数初始化成零),

sensor_inited 变量则存放在 RW 段中,

而 sensor_enable 存放在 RO 段中。

参考文献:https://blog.csdn.net/ylzmm/article/details/79233560

原文地址:https://www.cnblogs.com/covei/p/13915002.html