目录
2 ZI-data RW-data RO-data和Code数据段
2.2 bss data和txt数据段和ZI-data RW-data RO-data和Code数据段的关系
? ? ? ? 我们经常听人提起bss数据段,txt数据段,data数据段,但是我们不知道是什么意思,有些读者和博主一样,经常使用keil这个软件,所以只知道ZI-data数据段,RW-data数据段,RO-data数据段,Code数据段,那么他们存在什么样的关系呢,本小节带大家粗略的了解一下他们的关系,如果有错,请大家指出。
? ? ? ? 要搞懂本节,我们需要了解数据在内存中的存储方式,我们最长听见的词语就是堆栈了,下面我们就从堆栈进行进行讲解。
? ? ? ? 我们常说的堆栈,其实单指堆区,但是严格来说,堆区和栈区是分开的,堆区是需要malloc开辟空间的,然而栈区是存放局部变量的数据区,是由系统自动分配(大小由用户定义)。
? ? ? ? 我们使用最多的就是栈区,栈区的生长方式是向上生长,后面的小节为大家详细的讲解何为向上生长。
注意:堆区和栈区是存放在RAM空间的
? ? ? ? 全局变量又分为初始化为非零的全局变量、没有初始化或初始化为0的全局变量和const修饰的全局变量,他们在内存中的方式也是不同的。
? ? ? ? 初始化为非零的全局变量存储在ROM空间,当程序运行的时候,会自动的加载到RAM空间。
? ? ? ? 此类变量因为没有赋值(默认全局变量初始值为0),所以不必存放在ROM空间,所以此类变量存放在RAM空间。
? ? ? ? const修饰的全局变量为只读变量,也叫常量,它存放在ROM空间。
注意:char *p = "1234"定义的字符串常量也存在ROM空间
? ? ? ? 局部变量的初始值不固定,编译器不同初始值也存在一定的差异,所以使用局部变量的时候,需要给它赋值,它存放在栈区,也就是RAM空间。
? ? ? ? static修饰的变量分为全局变量和局部变量。
? ? ? ? mallco修饰的变量存放在堆区,也就是RAM空间。
? ? ? ? 代码,就是可执行的程序,它根据需求的不同存放的位置也有所不同,但是一般是存放在ROM空间的。
? ? ? ? 我们在使用keil第一次编译或者重新编译程序的时候,《Build Output》窗口会显示《Program Size: Code=8180 RO-data=880 RW-data=296 ZI-data=2176 ?》等信息,由于现在的单片机的ROM(FLASH)和RAM都比较大(相较于传统单片机),一般的程序不必考虑内存的问题,即使存在内存问题,编译器也会给你报错,所以这个就会导致很多现代的工程师很少关注这个问题,但是如果你对内存很敏感,比如你需要规定你的程序大小不能超过1Kbyte,或者不能使用超过250byte的RAM空间,查看这里的信息就显得十分的有用了。
Code:代码域,指的是编译器生成的及其指令,这些内容被存储在ROM区。
RO-data(Read Only Data):只读数据域,指的是程序中用到的只读数据,这些数据被存储在ROM区,并且程序不能修改其内容。例如C语言中的关键词const定义的变量就是典型的RO-data。
RW-data(Read Write Data):可读可写数据域,指的是初始值为“非零”的可读写数据,程序运行之前这些数据被存储在ROM区,这些数据具有非零的初始值,程序运行的时候被加载到RAM区,并且常驻于RAM区。应用程序能够修改其内容。例如C语言中定义的赋值不为0的全局变量就是典型的RW-data。
注意:关键词static定义的变量虽然默认值为0,但是也存在RW-data中。
ZI-data(Zero Initialize Data):初始值为0的数据域,指的是初始化为0值的可读可写数据域。它与RW-data的区别是这些数据一直存在RAM区,并且是在程序运行的时候才被加载到RAM区,且被赋予初始值0,而后续运行过程与RW-data的性质一致。例如C语言中定义的未赋值的全局变量或者赋值为0的全局变量(没有赋值的全局变量初始值默认为0)。
ZI-data的堆空间和栈空间:在C语言中,函数内部定义的局部变量属于栈空间,进入函数的时候向栈空间申请内存给局部变量,退出时释放局部变量,归返内存空间。而使用malloc动态分配的变量属于堆空间。在程序中的堆和栈空间都属于ZI-data区域,这些空间都会被初始化为0,编译器给出的ZI-data占用的空间值中包含了堆栈的大小(若程序没有使用malloc动态申请内存,编译器会优化堆空间,不会把堆空间计算在内)。
注意:局部变量的初始值为0是因为在程序运行的时候局部变量被赋予0值,但是当程序运行的时候,堆栈不停的交换数据,所以当程序运行到某个局部变量的时候,此局部变量的值就为留在堆栈的随机值,因此上学的时候所说的局部变量的值是随机值由此而来。
程序组件 | 所属类别 |
机器代码指令 | Code(txt) |
常量 | RO-data(data) |
初始非0的全局变量 | RW-data(data) |
Static定义的变量 | RW-data(data) |
初始为0的全部变量 | ZI-data(bss) |
局部变量 | ZI-data栈空间(bss) |
使用malloc动态分配的空间 | ZI-data堆空间(bss) |
????????RAM和ROM区域存储的数据如下:
? ? ? ? 下图表示RAM区存储的数据结构。栈区向上生长是压栈的时候SP指针减寄存器的大小,出栈的时候SP指针加上寄存器的大小,这就是所谓的向上生长。
? ? ? ? 下图是压栈时SP指针值的变化。
? ? ? ? 下图是出栈时SP指针值的变化。
? ? ? ? 整个流程称为SP的压栈和出栈,可以看出它压栈的时候,是从高地址往低地址进行压栈的,这种方式称为向上生长。
? ? ? ?当我们编译下载程序到ARM-M系列单片机中的时候,我们的程序存放在ROM空间的位置如左图所示,依次为DATA(R0)(此处为中断向量表),Code,Data(RO),Data(RW),程序复位的时候,PC默认指向0x08000004位置(0x08000000存放的是栈顶值),在复位的同时,程序会把存放在ROM空间的Data(RW)值加载到RAM空间(为了提高执行效率)。
????????BSS(ZI)数据段也就是Data(ZI)数据段,它根据编译器不同存放的位置有所差异,常见是不存放在ROM空间的。