STM32启动代码主要是分配堆栈及设置向量表,然后跳转到__main函数。

跳转具体到代码段部分如下:

[cpp] view plain copy
  1. Reset_Handler   PROC
  2. EXPORT  Reset_Handler             [WEAK]
  3. IMPORT  __main
  4. LDR     R0, = __main
  5. BX      R0
  6. ENDP

当您看到__main函数时,估计应该有不少人认为这个是main函数的别名或是编译之后的名字,否则在启动代码中再也无法找到和main相关的字眼了。可事实是,__main和main是完全两个不同的函数,并且你无法找到__main代码,因为这个是编译器自动创建的。

查看MDK的文档,会发现有这么一句说明:It is automatically created by the linker when it sees a definition of main()。简单点来说,当编译器发现定义了main函数,那么就会自动创建__main。

程序经过汇编启动代码,执行到__main()后,可以看出有两个大的函数:

__scatterload():负责把RW/RO输出段从装载域地址复制到运行域地址,并完成了ZI运行域的初始化工作。

__rt_entry():负责初始化堆栈,完成库函数的初始化,最后自动跳转向main()函数。

分析__scatterload()函数

执行到__main(),先跳转到_scatterload下图红框框中代码所示,执行完后,R10和R11就被赋给成了下面两个值。

Map文件中的symbol

然后执行_scatterload_null代码,将R10对应地址存放的的4个字copy到R0~R3中,可以看出

R0:0x1000表示的是keyled.o加载域起始地址

R1:0x30000100为keyled.o运行域地址

R2:0X160为copy的大小,keyled.o的大小从map文件中得知就是0x160 Byte

R3:0X1E4 是_scatterload_copy 代码的起始地址,实用BXR3 就能跳转到_scatterload_copy来复制代码。

跳到_scatterload_copy,开始copy,循环0x16次,每次搬移4个字(16Byte),共搬移0x16*0x10=0x160

复制完keyled.o代码后,进一步循环到_scatterload_null准备好,ZI段需要清零的地址和范围

执行完这个循环后

R1:0x30050000 为ZI段的起始地址

R2:0x618为ZI段大小,换成十进制是1560.从map文件得知ZI大小就是1560Byte

R3:0x20c 为_scatterload_zeroinit 的地址

执行下面红框框中循环体,共清零0x610Byte范围,然后再执行蓝框框中代码,清零8Byte,总共0x618

ZI段清零(0x30050000~0x30050618)

然后使用BX R14跳转到0x000001BC处,顺序执行到BL  __rt_enty 指令

成功跳转到__rt_enty函数

分析__rt_entry()函数

先调用__user_setup_stackheap()函数来建立堆栈

可以看出在这个函数中,会执行到BL__user_initial_stackheap()函数,这样也就明白了,为什么使用分散加载文件,需要设置__user_initial_stackheap这个函数来设置堆栈空间。

__main代码分析相关推荐

  1. arm9 c语言函数库,s3c2410(ARM9)启动代码分析(转载)

    ADS下C语言的入口方式和ROM镜像文件的生成 这部分介绍下ADS下如何生成可以运行的ROM镜像文件,我们知道当程序下载到flash中运行的时候,对于RW.ZI数据就存在着两个环境,一个load环境, ...

  2. Cortex-M启动代码分析(以STM32F4为例)

    ARM Cortex-M系列MCU的启动代码(使用汇编语言编程则不需要)主要做3件事情: 1.初始化并正确放置异常/中断向量表: 2.分散加载: 3.初始化C语言运行环境(初始化堆栈以及C Libra ...

  3. 20145236《网络攻防》Exp4 恶意代码分析

    20145236<网络攻防>Exp4 恶意代码分析 一.基础问题回答 如果在工作中怀疑一台主机上有恶意代码,但只是猜想,所有想监控下系统一天天的到底在干些什么.请设计下你想监控的操作有哪些 ...

  4. C#中类的继承 override virtual new的作用以及代码分析

    继承中override virtual new的作用 virtual 父类中需要注明允许重写的方法: override 子类中必须显示声明该方法是重写的父类中的方法: new 子类中忽略父类的已存在的 ...

  5. 2017.4.18 静态代码分析工具sonarqube+sonar-runner的安装配置及使用

    配置成功后的代码分析页面: 可以看到对复杂度.语法使用.重复度等等都做了分析,具体到了每一个方法和每一句代码. 四种使用方式: sonarqube + sonar-runner sonarqube + ...

  6. lighttpd1.4.18代码分析

    lighttpd1.4.18代码分析(八)--状态机(2)CON_STATE_READ状态 posted @ 2008-09-24 10:50 那谁 阅读(2225) | 评论 (1)  编辑 lig ...

  7. Device Tree(三):代码分析

    2019独角兽企业重金招聘Python工程师标准>>> 一.前言 Device Tree总共有三篇,分别是: 1.为何要引入Device Tree,这个机制是用来解决什么问题的?(请 ...

  8. 使用Hadoop和ELK进行业务代码分析!分分钟捉到Bug!

    大数据是计算领域的新高地,它有望提供一种方法来应对二十一世纪不断增长的数据生成.越来越多的大数据爱好者正在涌现,越来越多的公司正在采用各种大数据平台,并希望提出以客户为中心的解决方案,帮助他们在竞争激 ...

  9. 20145328 《网络对抗技术》恶意代码分析

    20145328 <网络对抗技术>恶意代码分析 ------看到这句话说明还没写完-------- 实践内容: 使用schtasks指令监控系统运行 使用sysmon工具监控系统运行 使用 ...

最新文章

  1. Express应用配置端口
  2. TensorFlow人工智能引擎入门教程之二 CNN卷积神经网络的基本定义理解。
  3. 自动化测试之iframe窗口的切换
  4. 20种小技巧,玩转Google Colab
  5. java ascii码从小到大排序_待签名参数按照字段名的ascii码从小到大排序 怎么理解...
  6. 团队作业4——第一次项目冲刺(Alpha版本)4.25
  7. java生成数据库设计说明书(excel)
  8. 窗口操作-关闭,最小化
  9. 第三天 LINUX安全
  10. Linux 镜像文件ISO下载地址:
  11. http://wang-min-zhao-sina-com.iteye.com/blog/1467204
  12. [iOS]申请苹果开发账号
  13. 华为服务器_RH2288H V3介绍
  14. 大数据破获网售假耐克案
  15. java秒换算成时分秒的形式
  16. 在nginx上部署vue项目(history模式)--demo实列;
  17. 服务器安装内置无线网卡,笔记本怎么安装内置网卡 笔记本内置无线网卡安装步骤【图文】...
  18. nikebot nike机器人 如何做一个nikebot nike监控怎么能不延迟 nike如何过盾 bot 机器人 snkrs
  19. 修改war3 魔兽争霸3分辨率
  20. 实惨!这些互联网公司,年终奖是真发不出来了...

热门文章

  1. Wireshark工作笔记-对TCP连接与断开以及数据传输的实战分析
  2. 专业课程设计之客户与服务器程序的同步与通信机制的设计(一)项目介绍
  3. C/C++文件剪切复制删除
  4. 怎么修改图例位置_学到了学到了,叠加图,原来可以这样处理图例
  5. mysql使用占位费付_美国大学硕士占位费怎么支付?三种支付方式任选!
  6. python创建数据库字数不限制_textarea字数限制方法一例
  7. cdh 差异_“Sahara/CDHPlugin”的版本间的差异
  8. linux df和du常用命令
  9. andriod 自写的view 获得屏幕大小和 获得自写view大小的不同写法
  10. 动态库的链接和链接选项-L,-rpath-link,-rpath