前言

在开发mcu代码的时候经常会有些疑惑,变量是怎么在编译之后进入单片机的ram区的呢,特别是在使用keil开发的时候。后来在接触gcc编译器和自研的mcu后,终于明白了这个问题。实际上变量编译后被放在了bin文件中代码的后面。程序运行时会主动将该区域的数据依次搬运到ram区域中。

原理

写完代码编译后,会把code中的所有变量放在代码的后面,当然这个规则也是由链接文件来决定的。示例图如下



在程序运行后正式进入C环境下,code中会存在一段汇编代码。主要作用就是把data区域内存依次复制到ram中,复制结束后把后面和bss长度一致区域的内存全置为0。

通过这也能够看出为什么bss区域的值会被设置为0,因为内存中是没有类型的说法。如果不全置0,无论其它哪个值都没法确认实际类型的值。

但是在keil中我们没有看到这样的代码。keil的汇编代码如下:

Reset_Handler   PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP

这段代码执行完毕后会跳转到__main函数里执行,主要注意的是这里并不是直接跳转到我们编写的main函数里。在__main有很多的操作,其中就包括将变量复制到ram区域中。执行完毕后才会跳转到我们自己开发的main函数中执行。

示例分析

下面这段代码就是gcc编译器下移动变量内存的代码。其中有几个变量,data区的起始、结束地址,bss区的起始、结束地址都是通过ld文件中获取的。

运行完下面的code后,程序中的所有变量都被移动到了ram区域中。

/*
* The ranges of copy from/to are specified by following symbols
* __etext: LMA of start of the section to copy from. Usually end of text
* __data_start__: VMA of start of the section to copy to
* __data_end__: VMA of end of the section to copy to
*
* All addresses must be aligned to 4 bytes boundary.
*/
lrw r1, __erodata // data在bin文件中的起始地址
lrw r2, __data_start__ // data在ram中的起始地址
lrw r3, __data_end__ // data在ram中的结束地址 subu r3, r2 // r3为data的长度
cmpnei r3, 0 // 判断长度是否为0
bf .L_loop0_done .L_loop0: // 将bin文件中数据依次移到ram中
ldw r0, (r1, 0)
stw r0, (r2, 0)
addi r1, 4
addi r2, 4
subi r3, 4
cmpnei r3, 0
bt .L_loop0 .L_loop0_done: /*
* The BSS section is specified by following symbols
* __bss_start__: start of the BSS section.
* __bss_end__: end of the BSS section.
*
* Both addresses must be aligned to 4 bytes boundary.
*/
lrw r1, __bss_start__
lrw r2, __bss_end__ movi r0, 0 subu r2, r1
cmpnei r2, 0
bf .L_loop1_done .L_loop1: // 将bss里的数据复制为0
stw r0, (r1, 0)
addi r1, 4
subi r2, 4
cmpnei r2, 0
bt .L_loop1
.L_loop1_done:

MCU变量加载过程的更多相关文章

  1. linux内核启动以及文件系统的加载过程

    Linux 内核启动及文件系统加载过程 当u-boot 开始执行 bootcmd 命令,就进入 Linux 内核启动阶段.普通 Linux 内核的启动过程也可以分为两个阶段.本文以项目中使用的 lin ...

  2. JVM——类的加载过程

    附一张图方便理解,一个类的执行过程 类的加载过程,简明的来说 类装饰器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件.在Java中,类装载器把一个类装入JVM中,要经过以下步骤: 装载:查 ...

  3. Java 类的加载过程(阿里面试题)

    问以下程序打印出什么内容: 问题及解析如下: /** * 加载方法不等于执行方法,初始化变量则会赋值 * 类加载顺序应为 加载静态方法-初始化静态变量-执行静态代码块 * 实例化时 先加载非静态方法- ...

  4. (转)JVM类生命周期概述:加载时机与加载过程

    原文地址: http://blog.csdn.net/justloveyou_/article/details/72466105 JVM类加载机制主要包括两个问题:类加载的时机与步骤 和 类加载的方式 ...

  5. java中类的加载过程和对象的创建过程

    1.类加载过程 首先,jvm在执行时,遇到一个新的类,会先去内存的方法区中去寻找该类的.class文件,如果找到了就直接运行,如果没有找到,则会去硬盘中去寻找该类的.class文件,并将该类文件加载到 ...

  6. java程序的加载过程

    昨天笔试阿里有个求java程序加载过程的题目很是复杂,回来研究了好久才有点明白,整理一下.原题代码如下,判断输出: public class StaticTest { public static in ...

  7. asp.netcore 深入了解配置文件加载过程

    前言     配置文件中程序运行中,担当着不可或缺的角色:通常情况下,使用 visual studio 进行创建项目过程中,项目配置文件会自动生成在项目根目录下,如 appsettings.json, ...

  8. spring启动component-scan类扫描加载过程(转)

    文章转自 http://www.it165.net/pro/html/201406/15205.html 有朋友最近问到了 spring 加载类的过程,尤其是基于 annotation 注解的加载过程 ...

  9. ELF文件的加载过程(load_elf_binary函数详解)--Linux进程的管理与调度(十三)

    加载和动态链接 从编译/链接和运行的角度看,应用程序和库程序的连接有两种方式. 一种是固定的.静态的连接,就是把需要用到的库函数的目标代码(二进制)代码从程序库中抽取出来,链接进应用软件的目标映像中: ...

随机推荐

  1. A Child's History of England.41

    When intelligence of this new affront [hit in the face, c-o-n-frontation!] was carried to the King i ...

  2. day08 外键字段的增删查改

    day08 外键字段的增删查改 今日内容概要 外键字段的增删查改 正反向查询的概念 基于对象的跨表查询(子查询) 基于双下划线的跨表查询(连表操作) 聚合查询与分组查询 F查询和Q查询 前提准备 cl ...

  3. flink03-----1.Task的划分 2.共享资源槽 3.flink的容错

    1. Task的划分 在flink中,划分task的依据是发生shuffle(也叫redistrubute),或者是并行度发生变化 1.  wordcount为例 package cn._51doit ...

  4. C++福尔摩斯的约会

    这道题的要求总结如下: 1.DAY 星期 大写字母:A B C D E F G2.HH 时 数字+大写字母 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M ...

  5. 节省内存的循环banner(一)

    循环banner是指scrollview首尾相连,循环播放的效果,使用非常广泛.例如淘宝的广告栏等. 如果是简单的做法可以把所有要显示的图片全部放进一个数组里,创建相同个数的图片视图来显示图片.这样的 ...

  6. vue2 中的 export import

    vue中组件的引用嵌套通过export import语法链接 Nodejs中的 export import P1.js export default { name: 'P1' } index.js i ...

  7. 【Java基础】HashMap原理详解

    哈希表(hash table) 也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,本文会对java集合框架中Has ...

  8. 设计模式学习笔记之看懂UML类图

    什么是UML: UML(统一建模语言)是当今软件设计的标准图标式语言.对于一个软件系统而言,UML语言具有以下的功能:可视化功能.说明功能.建造功能和建文档功能. UML都包括什么类型的图: 使用案例 ...

  9. Jenkins动态选择分支/tag

    目录 一.简介 二.配置 三.配置tag 四.其它方法 五.List Git Branches插件 一.简介 一般选择分支构建,Git Parameter插件即可.这里是应用pipline的同时,可以 ...

  10. CentOS6设置开机自启动

    1.把开机启动脚本(mysqld)copy到文件夹/etc/init.d 或 /etc/rc.d/init.d 中 2.将启动程序的命令添加到 /etc/rc.d/rc.local 文件中,比如: # ...