基于STM32F103的重定位
一、段的概念及重定位的引入
1.1 问题引入
在串口程序中添加全局变量,把它打印出来,看看会发生什么事。
char g_Char = 'A';
const char g_Char2 = 'B'; //const修饰的常量
//main()
putchar(g_Char);
putchar(g_Char2);
打印结果:
可以看到const修饰的常量和全局变量的地址空间并不一样,且变量 g_char
的值并不能打印出来,这是为什么呢?
我们先引入STM32F103的内存资源
可以看到g_char
被保存到RAM中,而g_char2
则被保存到ROM中
这是为什么呢?
RAM被称为随机存取存储器,而ROM则被成为只读存储器
因为RAM是可读可写的
ROM只可读,const修饰的是常量,只读就行,所以可以放在ROM里
所以在程序烧录的时候,.bin程序被烧写到ROM里面,变量g_char2
的值就存储在ROM中,此时我们使用地址就可以访问到变量B;
而变量g_char
存储在RAM里面,没人对他进行初始化操作,所以它的值就是一个随机值,打印出来就会变成乱码
为什么变量g_char
的值会保存在RAM中呢,此时就需要我们引入重定位的概念。
什么是重定位呢?
烧写完程序,ROM上会有代码,变量的值等,所以在调用main函数之前,应该把数据复制到内存上去,这就是重定位(重新确定位置)
重定位为数据段重定位,代码重定位
- 代码重定位
保存在ROM上的全局变量的值,在使用前要复制到内存,这就是数据段重定位。
代码直接放在ROM上运行即可,对于数据,可读可写的数据,我们需要把它从ROM上复制到RAM上去
- 数据段重定位
想把代码移动到其他位置,这就是代码重定位。
接下来引入下一个问题:
访问可读可写的全局变量前,应该给它初始化一个值,谁来初始化?
在 start.s 启动文件里进行初始化
- 段的详细解释
1.初始值放在ROM上,但是我们要去内存里访问它,所以在使用它前,我们需要把它的值从ROM上复制到内存里,像这类变量我们要把它们放在一块,这一段空间就称为可读可写的数据段.
2.像程序中的多个常量,我们也把它们放在一块,这一块空间就被成为只读数据段
3.指令本身,他们是属于代码段
4.对于初始值为0的变量,或者没有初始值的变量,假设有很多,我们需要把他们都保存到ROM上吗?
答案肯定是不用,对于这些变量,我们会把他们放在一块,这块空间就被称为BSS段,或者叫ZI段,使用前,只需把这段空间全部清零即可,相应的变量的值也就清零了
1.2 段的概念
代码段、只读数据段、可读可写的数据段、BSS段。
char g_Char = 'A'; // 可读可写,不能放在ROM上,应该放在RAM里
const char g_Char2 = 'B'; // 只读变量,可以放在ROM上
int g_A = 0; // 初始值为0,干嘛浪费空间保存在ROM上?没必要
int g_B; // 没有初始化,干嘛浪费空间保存在ROM上?没必要 放在BSS段上或者ZI段上
所以,程序分为这几个段:
- 代码段(RO-CODE):就是程序本身,不会被修改
- 可读可写的数据段(RW-DATA):有初始值的全局变量、静态变量,需要从ROM