一、实验准备
实验目的:
重温C语言程序里全局变量、局部变量、堆、栈等概念,在Keil中针对stm32系统进行编程,调试变量,进行验证;通过串口输出信息到上位机,进行验证。 并归纳出stm32的堆、栈、全局变量的分配地址,与ARM教材中的地址分配进行对比。
实验工具:
硬件
软件
keil 5
串口工程:(此次实验是在此工程的基础上进行更改)
二、相关代码
解压工程并打开,找到main.c下的bsp_usart.h文件,添加头文件如下:
#include "stm32f10x.h"
#include "bsp_usart.h" //添加 bsp_usart.h 头文件
int init_global_a = 1;
int uninit_global_a;
static int inits_global_b = 2;
static int uninits_global_b;
void output(int a)
{
printf("hello");
printf("%d",a);
printf("n");
}
int main(void)
{
//定义局部变量
int a=2;
static int inits_local_c=2, uninits_local_c;
int init_local_d = 1;
char *p;
char str[10] = "lyy";
//定义常量字符串
char *var1 = "1234567890";
char *var2 = "qwertyuiop";
//动态分配
int *p1=malloc(4);
int *p2=malloc(4);
USART_Config();//串口初始化
output(a);
//释放
free(p1);
free(p2);
printf("栈区-变量地址n");
printf(" a:%pn", &a);
printf(" init_local_d:%pn", &init_local_d);
printf(" p:%pn", &p);
printf(" str:%pn", str);
printf("n堆区-动态申请地址n");
printf(" %pn", p1);
printf(" %pn", p2);
printf("n全局区-全局变量和静态变量n");
printf("n.bss段n");
printf("全局外部无初值 uninit_global_a:%pn", &uninit_global_a);
printf("静态外部无初值 uninits_global_b:%pn", &uninits_global_b);
printf("静态内部无初值 uninits_local_c:%pn", &uninits_local_c);
printf("n.data段n");
printf("全局外部有初值 init_global_a:%pn", &init_global_a);
printf("静态外部有初值 inits_global_b:%pn", &inits_global_b);
printf("静态内部有初值 inits_local_c:%pn", &inits_local_c);
printf("n文字常量区n");
printf("文字常量地址 :%pn",var1);
printf("文字常量地址 :%pn",var2);
printf("n代码区n");
printf("程序区地址 :%pn",&main);
printf("函数地址 :%pn",&output);
return 0;
}
三、编译运行
将程序进行编译
烧录进开发板中
打开串口调试助手,按一下板子上的复位键RESET
四、归纳
在一个STM32程序代码中,从内存高地址到内存低地址,依次分布着栈区、堆区、全局区(静态区)、常量区、代码区,其中全局区中高地址分布着.bss段,低地址分布着.data段。分布方式如下图:
1)栈区(stack)
- 临时创建的局部变量存放在栈区。
- 函数调用时,其入口参数存放在栈区。
- 函数返回时,其返回值存放在栈区。
- const定义的局部变量存放在栈区。
2)堆区(heap)
- 堆区用于存放程序运行中被动态分布的内存段,可增可减。
- 可以有malloc等函数实现动态分布内存。
- 有malloc函数分布的内存,必须用free进行内存释放,否则会造成内存泄漏。
3)全局区(静态区)
4).bss段
- 未初始化的全局变量存放在.bss段。
- 初始化为0的全局变量和初始化为0的静态变量存放在.bss段。
- .bss段不占用可执行文件空间,其内容有操作系统初始化。
5).data段
- 已经初始化的全局变量存放在.data段。
- 静态变量存放在.data段。
- .data段占用可执行文件空间,其内容有程序初始化。
- const定义的全局变量存放在.rodata段。
6)常量区
7)代码区
- 程序执行代码存放在代码区。
- 字符串常量也有可能存放在代码区。