一 map文件
map文件是编译器在连接之后生成的一个文件,用来反映各个函数模块之前的调用关系以及在flash和SRAM中的分布情况,了解这个文件对深入理解嵌入式软件开发有很大的帮助。
map文件大致有4个模块:
- Section Cross References(代码段间的相互调用关系)
- Removing Unused input sections from the image.(删除冗余的模块)
- Image Symbol Table(代码、变量映射表)
- Memory Map of the image(存储空间分布情况)
使用keil编程的话可以在下图的位置设置输出哪些信息到map文件
二 代码段间的相互调用关系
Section Cross References
main.c
int main(void)
{
function1();
while(1){
function2();
}
return 0;
}
void test_func(void)
{
function2();
}
func1.c
void function1(void)
{
}
void function2(void)
{
}
- main.o 是main.c文件编译产生的模块
- func1.o 是func1.c文件编译产生的模块
- main.o(i.main) 表示main.o模块中的func1函数
正文第一行的表示:main.o中的main函数调用了func1模块中的function1函数
二 删除冗余的模块
Removing Unused input sections from the image
删除一些冗余代码,比如第一行: Removing main.o(i.test_func), (8 bytes). 因为test_func没有被任何地方引用,因此可以被删除。
三 代码、变量映射表
这部分映射表分为Local Symbols(局部符号),Global Symbols(全局符号)
每一个条目都包含5部分
- Symbol Name(符号名称)
- Value(地址值)
- Ov Type(类型)
- Size(大小)
- Object(Section) (所属模块)
这部分包含:
- 用static声明的全局变量
- C文件中函数
- 用static声明的函数
- 汇编文件中的标号地址(作用于限本文件)
static int var1;//static 修饰的全局变量,放到SRAM中,局部符号
int var2;//全局变量,全局符号
int array[10] = {0};//位于.bss段
int* p_int;//全局变量,全局符号
char* const str_temp = "abcd";//字符串常量,被写到flash
m_object_t mobject;//全局变量
void test_func(void)
{
array[0] = var1;
function2();
var2 = array[5];
array[0] = mobject.a;
array[0] = var2;
mobject.b = *(str_temp + 1);
*p_int = 8;
function1();
}
int main(void)
{
static int var3;//static修饰的局部变量,局部符号
int var4;//普通的局部变量,运行时才被分配空间
function1();
test_func();
while(1){
array[0] = var2;
function2();
}
return 0;
}
- var1, static 修饰的全局变量,放到SRAM中,局部符号
- var2, 全局变量,全局符号
- var3, static修饰的局部变量,局部符号
- var4, 普通的局部变量,运行时才被分配空间
- array[10] , 数组,位于.bss段(bss段由编译器确定其初始值)
- p_int, 全局变量,全局符号
- str_temp, 字符串常量(只读的),位于flash中
- Thumb Code(代码,只读的), 比如main、function1、function2等,位于flash中
该测试工程的.s文件部分截图如下所示:
- Stack_Size, 栈大小
- __initial_sp,栈顶指针,链接之后确定
- Heap_Size, 堆大小
- __heap_base, 堆基地址
- __heap_limit, 堆指针
通过map文件可知
- .data段的起始地址为0x2000 0000大小为24 byte,包括:
- var1 4byte
- var2 4byte
- var3 4byte
- p_int 4byte
- mobject 8byte
- .bss段的起始地址为0x20000018大小为136 byte,包括:
- array 40byte
- __libspace_start 96byte
- 堆起始地址为0x200000a0(0x20000018 + 0x88 == 0x200000a0),大小为512byte
- 栈起始地址为0x200002a0(0x200000a0 + 0x200 == 0x200002a0), 大小为1024byte
- 栈顶指针__initial_sp值为0x200006a0,由于栈是由高地址向低地址增长的,因此0x200006a0 = 0x200002a0 + 0x400
四 内存分布
- Image Entry point : 0x080001cd,入口地址指向硬件复位向量 Reset_Handler
- Load Region LR_1 和 Execution Region ER_RO 反应的是在工程中配置情况,如下图所示
各个字段的含义:
- Base Addr ,基地址
- Size, 大小
- Type,类型,类型有:
- Data:数据类型
- Code:代码类型
- Zero:未初始化变量类型
- PAD:补充字段,为了实现字对起
- Attr,属性,属性有:
- RO,存储与ROM中的段
- RW:存储与RAM中的段
- Section Name:段名
- RESET
- ARM
- text
- i.
- .data
- .bss
- HEAP
- STACK
- Object, 模块
五 程序的构成
一个程序的固件由以下4部分组成:
- Code:指代码的大小;
- Ro-data:常量数据
- RW-data:指可读写(RW),已初始化的变量数据;
- ZI-data:指未初始化(ZI),的变量数据;
编译完程序之后会有如下图的提示:
Code = 820, RO-data = 348,RW-data = 24, ZI-data 1672
Code,Ro-data 位于FLASH中;
RW-data、ZI-data:位于RAM中;
RW-data已初始化的数据会存储在Flash中,程序运行时从FLASH搬移至RAM中。
RO Size = Code + RO Data
RW Size = RW Data + ZI Data
最终程序占用flash的大小为 Code + RO Data + RW Data这个大小也就是bin文件的大小。
SRAM应不小于RW Data + ZI Data