在平时写代码的时候,特别是嵌入式相关的代码时,能想到的优化方法一般就是通过设置编译器的优化等级。或者是在定义变量的时候考虑变量的使用范围,然后根据数据范围选择比较适合的数据类型。但是这种优化方式操作起来都比较模糊,没有一个直观的感受。为了让代码的优化有个直观的感受,今天就借助map文件来优化代码。

  首先看一段简单的示例。

  这是一段很简单的测试代码,就是在主程序里面让LED灯闪烁,同时给x变量每次加0.1。这个代码还需要优化吗?别着急,先打开工程中生成的map文件看看。

  map文件在工程目录debug文件夹里面的List文件夹中,使用记事本打开这个文件。

  在文件中间有一部分是各个目标文件所占用的空间大小,依次往下找,找几个占用空间比较大的位置。

  可以发现float.o这个目标文件占用的空间相对于其他文件来说很大了。那么这个float.o文件是哪里来的呢?看到float大概可以猜测到这是浮点相关的文件。在程序中只有一个地方用到了浮点运算。

  难道这一行代码能占用那么多的空间吗?那么把浮点运算改为整形运算试试。


  将x扩大10倍,然后每次加1,编译代码后重新打开map文件查看。

  这时就会发现在long.o前面的float.o文件消失了。由此可见,刚才那个float.o文件就是代码中的那一行浮点运算生成的。通过map文件的观察可以得出一个结论,浮点运算在单片机中占用的空间很大,所以尽量把浮点运算换算成整形运算。否则如果浮点运算的运算量比较大时,单片机的空间很快就会被占满了。

  接下来在通过串口将变量的值打印出来。

  通过串口助手观察打印的值

  串口打印的值也正常,接下来继续查看map文件。

  在map文件中可以看到在long.o文件的前面和后面多了好几个文件。而且占用空间非常大。

  那为什么又出现了一个非常大的 float.o 文件?这是因为printf函数支持浮点数打印,在函数里面有浮点数,所以就会产生一个float.o文件。xprintffull_nomb.o也是在调用printf函数时生成的。

  由此可见,printf函数占用的空间相当大的,在程序中尽可能的避免使用printf函数。那么要打印数据的时候怎么办呢?可以通过单片机串口默认输出功能打印字符,但是又有一个新问题,串口输出都是字符格式,而现在要打印整数,如何将整数转换为字符格式呢?可以通过自定义的函数,先将数字转换为字符串,然后在通过串口输出字符串。

  首先编写一段整数转字符串的函数。

void int2str(int n, char *str)
{char buf[10] = "";int i = 0;int len = 0;int temp = n < 0 ? -n: n;  // temp为n的绝对值if (str == NULL){return;}while(temp){buf[i++] = (temp % 10) + '0';  //把temp的每一位上的数存入buftemp = temp / 10;}len = n < 0 ? ++i: i;  //如果n是负数,则多需要一位来存储负号str[i] = 0;            //末尾是结束符0while(1){i--;if (buf[len-i-1] ==0){break;}str[i] = buf[len-i-1];  //把buf数组里的字符拷到字符串}if (i == 0 ){str[i] = '-';          //如果是负数,添加一个负号}
}

  接下来编写串口相关函数。

//发送单个字符
void SendChar( unsigned char dat )
{while( ( UART1_SR & 0x80 ) == 0x00 );       //发送数据寄存器空UART1_DR = dat;
}
//发送字符串
void SendString( unsigned char* s )
{while( 0 != *s ){SendChar( *s );s++;}
}

  下面修改主函数代码。

void main( void )
{int  x = 10;char str[100] = {0};__asm( "sim" );                             //禁止中断SysClkInit();delay_init( 16 );LED_GPIO_Init();Uart1_IO_Init();Uart1_Init( 9600 );__asm( "rim" );                             //开启中断while( 1 ){LED = ~LED;x += 1;    int2str(x,str);SendString(str);SendString("\r\n");delay_ms( 1000 );}
}

  首先通过int2str函数将变量x转换为字符串,然后在通过SendString函数将字符串打印出来,最后在调用一次SendString打印回车换行字符。打印效果如下:


  接下来再看一下map文件中占用的空间大小。

  通过map文件可以看到,相对于直接使用printf函数来说,自定义函数实现打印功能要节省不少空间。这样通过观察map文件中的目标文件大小,在优化程序的过程中就可以直观的看到优化后的代码与优化前的代码具体差距在哪里。这样在调试代码的过程中就会胸有成竹,不会像无头苍蝇一样到处乱撞。

如何通过map文件优化代码相关推荐

  1. webpack打包生成的map文件_从这十几个方面优化你的 Webpack 配置

    目录 开发环境性能优化 生产环境性能优化 开发环境性能优化 优化打包构建速度 HMR 优化代码调试 source-map HMR ❝ 概念:「HMR:」 hot module replacement ...

  2. webpack打包生成的map文件_一站式搞明白webpack中的代码分割

    上次分析到通过devtool的配置项来设置source map,在线上环境可以通过设置成cheap-module-source-map来生成单独的map文件,但是map文件在线上环境会不会每次都加载呢 ...

  3. 问题-[Delphi]通过Map文件查找内存地址出错代码所在行

     一 什么是MAP文件       什么是 MAP 文件?简单地讲, MAP 文件是程序的全局符号.源文件和代码行号信息的唯一的文本表示方法,它可以在任何地方.任何时候使用,不需要有额外的程序进行支持 ...

  4. 使用MAP文件快速定位程序崩溃代码行

    作为程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统 造成巨大的损失.但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事.其实测试中出现 ...

  5. 使用MAP文件快速定位程序崩溃代码行(转)

    作为程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统造成巨大的损失.但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事.其实测试中出现程 ...

  6. ARM 之十 ARMCC(Keil) map 文件(映射文件)详解

    在看这篇文章之前 需要对 ARM ELF 文件有一定的了解.了解什么是域(Region).节(Section,也称为节区).段(Segment).镜像(Image).镜像文件(Image File)等 ...

  7. STM32 MDK编译后生成的 .map文件深入分析

    .map文件是STM32开发中非常重要的一个文件,在该文件中可以详细的查看单个文件.函数及用户定义的全局变量等的占用RAM和ROM(一般为片内FLASH)的空间大小,通过了解这些信息可以很方便的进行代 ...

  8. STM32的map文件学习笔记

    前言 前几个月针对公司自己的芯片写了个程序,这个程序有个硬性要求,就是能用的FLASH空间只有4KB,之前已经写得差不多了,最终占用空间3.6KB. 这不,最近又得加需求,还剩一点点FLASH空间可以 ...

  9. 如何优化代码和RAM大小

    如果供应商为我自己的项目提供了一个起点,那就太好了.工作'blinky'始终是一个伟大的首发.方便总是有代价,而且"blinky"就是夸大"切换GPIO引脚"的 ...

最新文章

  1. windows安装visual studio code并配置latex并编写latex论文
  2. 动态代理:JDK动态代理和CGLIB代理的区别
  3. SQLServer转义问题
  4. 原文翻译:深度学习测试题(L1 W1 测试题)
  5. 深度学习String、StringBuffer、StringBuilder
  6. Android获取最新发送短信的基本信息,没有之一
  7. 计算机网络常见面试真题详解
  8. 几大主流国产浏览器统一屏蔽996.ICU!
  9. pytorch torch.nn.TransformerEncoderLayer
  10. 高德地图定位5.0以下
  11. 1.4.1bat脚本命令COPY 拷贝 复制到
  12. iPhone+wp7并行初体验
  13. python爬取今日头条新闻,js解密
  14. SFB 项目经验-35-分配公网证书 For Exchange Server 2016(图解)
  15. [深度学习]图片的几种读写方式以及相互转换
  16. mock gps android,GitHub - Hilaver/MockGPS: Android application to fake GPS
  17. 浏览器兼容性问题及常见的解决方法
  18. 超详细Redis使用手册
  19. 裸金属服务器是什么?裸金属服务器能用来干啥
  20. 【数据库原理】Transact-SQL

热门文章

  1. iOS 7.1下itms-services在线安装失败的解决方法
  2. 基于Starling的mask实现
  3. DataGridView 禁用自动生成列
  4. 一个老博士的经验顺口溜
  5. SpringBoot启动流程解析
  6. PL/SQL程序设计(七)—— 触发器
  7. github 上 Fork 别人的项目后的常用的操作指南
  8. C/C++ -- Gui编程 -- Qt库的使用 -- 使用.ui文件
  9. 【原】如何实现IE6下块级元素的内容自动收缩
  10. 【原创】一款符合当前主流审美的Swing外观(Look and Feel)_测试版发布