keil生成的map文件全面分析

一 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

  • 15
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值