文章目录
一、归纳出Ubuntu、stm32下的C程序中堆、栈、全局、局部等变量的分配地址,进行对比分析
在Ubuntu和stm32下的C程序中,变量的分配地址受到编译器和操作系统的影响。下面是对Ubuntu和stm32下变量的分配地址的一般归纳:
Ubuntu中的变量分配地址:
全局变量:在程序的数据段(data segment)或者BSS段(未初始化的全局变量)中分配。
局部变量(自动变量):在函数调用栈中分配。每当函数被调用时,为局部变量分配新的内存空间,当函数返回时,这些内存空间被释放。
stm32中的变量分配地址:
全局变量:在芯片的存储区域(RAM或FLASH)中分配。其地址在编译时即确定。
局部变量(自动变量):通常在函数调用栈中分配。
堆变量:在堆(heap)中分配,使用动态内存分配函数(如malloc、calloc)来分配和释放。
栈变量:在堆栈(stack)中分配。在stm32中,栈的大小是一个非常有限的资源,通常是硬件决定的,因此栈变量的分配空间非常有限。
二、对ARM Cortex-M/stm32F10x的存储器地址映射的理解
ARM Cortex-M系列是一个32位嵌入式处理器架构,stm32F10x是一系列基于Cortex-M系列内核的STM32单片机。存储器地址映射指的是将不同类型的存储器(包括Flash、SRAM、外设寄存器等)映射到处理器地址空间的过程。
在ARM Cortex-M系列中,存储器地址映射通常遵循以下原则:
代码存储器: Flash存储器用于存储程序代码,通常被映射到处理器的地址空间的起始位置。该映射可以是连续的或分段的,取决于具体的处理器和片内存储器的布局。
数据存储器: 数据存储器包括SRAM(随机访问存储器)和外设寄存器,用于存储变量和外设的配置寄存器。SRAM通常映射到处理器地址空间的中间区域,而外设寄存器则映射到一个独立的地址空间,通常称为Peripherals区域。
堆栈: 堆栈用于存储函数调用的局部变量和返回地址等信息。在ARM Cortex-M系列中,堆栈位于SRAM的末尾,使用较高的地址。
特殊寄存器: ARM Cortex-M系列处理器还有一些特殊的寄存器,如NVIC(中断控制器)和SCB(系统控制块)。这些寄存器通常被映射到特定的地址,用于控制中断、系统时钟和处理器状态等。
stm32F10x系列单片机在ARM Cortex-M系列的基础上,还具有自己的存储器布局和外设寄存器映射。具体的映射关系和地址范围可以在芯片的参考手册中找到,手册会指定Flash、SRAM、寄存器和其他外设的起始地址和范围,以及访问这些地址时的读写权限和功能描述。
总结来说,ARM Cortex-M和stm32F10x单片机的存储器地址映射决定了各种存储器和寄存器如何在处理器地址空间中分配和访问。了解这种映射关系对于嵌入式软件开发和硬件编程非常重要,可以直接操作与处理器相连的存储器和外设。
三、Ubuntu(x86)系统编程
1.代码
#include <stdio.h>
#include <stdlib.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( )
{
//定义局部变量
int a=2;//栈
static int inits_local_c=2, uninits_local_c;
int init_local_d = 1;//栈
output(a);
char *p;//栈
char str[10] = "yaoyao";//栈
//定义常量字符串
char *var1 = "1234567890";
char *var2 = "abcdefghij";
//动态分配——堆区
int *p1=malloc(4);
int *p2=malloc(4);
//释放
free(p1);
free(p2);
printf("栈区-变量地址\n");
printf(" a:%p\n", &a);
printf(" init_local_d:%p\n", &init_local_d);
printf(" p:%p\n", &p);
printf(" str:%p\n", str);
printf("\n堆区-动态申请地址\n");
printf(" %p\n", p1);
printf(" %p\n", p2);
printf("\n全局区-全局变量和静态变量\n");
printf("\n.bss段\n");
printf("全局外部无初值 uninit_global_a:%p\n", &uninit_global_a);
printf("静态外部无初值 uninits_global_b:%p\n", &uninits_global_b);
printf("静态内部无初值 uninits_local_c:%p\n", &uninits_local_c);
printf("\n.data段\n");
printf("全局外部有初值 init_global_a:%p\n", &init_global_a);
printf("静态外部有初值 inits_global_b:%p\n", &inits_global_b);
printf("静态内部有初值 inits_local_c:%p\n", &inits_local_c);
printf("\n文字常量区\n");
printf("文字常量地址 :%p\n",var1);
printf("文字常量地址 :%p\n",var2);
printf("\n代码区\n");
printf("程序区地址 :%p\n",&main);
printf("函数地址 :%p\n",&output);
return 0;
}
2.编写结果
四、STM32(Keil)编程
1.代码
总结
在这次的学习中,学习了全局常量、全局变量、局部变量、静态变量、堆、栈等,在Ubuntu(x86)系统和STM32(Keil)中的相同点以及不同点。对ARM Cortex-M/stm32F10x的存储器地址映射的理解。Ubuntu和Keil中堆,栈的差别还是较大的。ARM Cortex-M和stm32F10x单片机的存储器地址映射决定了各种存储器和寄存器如何在处理器地址空间中分配和访问。在地址有关的知识还是较为困难的,需要继续的学习下去。