Keil开发的ARM程序main函数之前的汇编分析
Keil开发的ARM程序main函数之前的汇编分析
——BIN文件中RW段的数据移动
系统平台:
STM32系列STM32F103ZE,512KB内部FLASH,64KB片内存储;
FLASH地址范围0x0800 0000 ~ 0x0808 0000,用于存放代码;
片内存储地址范围0x2000 0000 ~ 0x2001 0000,用于存放数据;
Cortex-M3上电后来到复位中断(已将前4个字节的值存入MSP堆栈指针),转到__main标号,完成RW段的移动、ZI段的初始化,建立堆栈,初始化库函数,然后跳转到main函数,开启C程序之旅,执行流程如图1所示。

图1 main函数之前的汇编程序执行流程图
本文主要讨论RW段的移动,RW段就是程序中赋了初值的变量,它的搬移我看到过两种方式。在BIN文件中,RO段和RW段之间有8个双字的Region$$Table,4个双字一组,分别用于完成RW段的搬移和ZI段的初始化。
(1) __scatterload_copy来完成
此时RW段的内容保存到内存开始的地方,本文中是0x20000000,用这一方式完成后,内存中存放的不是RW数据的内容,而是一个地址。这个地址是在FLASH中,即指向了其在RO段的地址,实际的内容是在RO段中。
(2) 通过__uncompressed1实现
RW是程序中初始化的变量,但是这些变量有可能初值是0,因此为了节省空间,实际在BIN文件中RW段是压缩过的。调用__uncompressed1解压缩RW段的数据内容,并将其保存到内存开始的地方。

图2 BIN文件中压缩RW段内容
图2是BIN文件中RW段的数据内容,影印部分显示,大小是164字节。其中0x0001 C72C前面8个双字的内容是Region$$Table,将其列出如下。
0x0801 C72C BIN文件中RW段的开始地址
0x2000 0000 RW段要存放到RAM中的地址
0x0000 0334 要存放到RAM中的RW段数据大小
0x0800 0184 执行函数__scatterload_copy或者__uncompressed1的地址
上面4个双字完成RW段的搬移。
0x0801 C7D0 BIN文件的末尾,ZI段的开始
0x2000 0334 ZI段放到RAM中的起始位置
0x0000 F4BC ZI段的大小
0x0800 01E0 执行函数__scatterload_zeroinit的地址
这4个双字完成ZI段的初始化。

图3 RW段内容解压缩后在RAM中排布
将BIN文件中RW解压缩以后(这个解压缩从反汇编可以看到,但是没有看明白),实际内容如图3所示,大小变为820个字节,该补0的地方都已经补足了。
Keil开发的ARM程序main函数之前的汇编分析的更多相关文章
- 转:iOS程序main函数之前发生了什么
原文地址:http://blog.sunnyxx.com/2014/08/30/objc-pre-main/ 我是前言 一个iOS app的main()函数位于main.m中,这是我们熟知的程序入口. ...
- iOS程序main函数之前发生了什么
我是前言 一个iOS app的main()函数位于main.m中,这是我们熟知的程序入口.但对objc了解更多之后发现,程序在进入我们的main函数前已经执行了很多代码,比如熟知的+ load方法等. ...
- 问题:C#控制台程序参数;结果:设置与读取C#控制台应用程序Main函数中的参数args
设置与读取C#控制台应用程序Main函数中的参数args 在项目属性面版->调试->命令行参数设置.空格分隔.读取:string[] str = Environment.GetComman ...
- linux中应用程序main函数中没有开辟进程的,它应该在那个进程中运行呢?
1.main函数是一个进程还是一个线程? 不知道你是用c创建的,还是用java创建的. 因为它们都是以main()做为入口开始运行的. 是一个线程,同时还是一个进程. 在现在的操作系统中,都是多线程的 ...
- C 语言main 函数终极探秘(&& 的含义是:如果 && 前面的程序正常退出,则继续执行 && 后面的程序,否则不执行)
所有的C程序必须定义一个称之为main的外部函数,这个函数是程序的入口,也就是当程序启动时所执行的第一个函数,当这个函数返回时,程序也将终止,并且这个函数的返回值被看成是程序成功或失败的 ...
- .NET中Main函数使用小技巧
摘要:任何语言开发出来的程序,都会有一个程序入口函数,可能每个语言所使用的程序入口函数名称不一样,但是它们的作用都是一样的,都是被操作系统去调用.那么本文主要总结.NET中的程序入口函数Main使用的 ...
- keil c51中C程序的启动过程
汇编是从org 0000h开始启动,那么keil c51是如何启动main()函数的?keil c51有一个启动程序startup.a51,它总是和c程序一起编译和链接.下面看看它和main()函数是 ...
- 【逆向工具】IDA使用1-VS2015版本debug查找Main函数,加载符号文件
IDA 常见操作 空格,切换反汇编视图 选择CALL或是跳转 进入函数内部或是跳转处 返回键 ESC daq.exe 分析32位程序 ,生成的IDA数据库文件是 .idb Idap64.exe 分析6 ...
- WPF点滴(1) Main 函数
应用程序的入口函数是main函数,在Console程序和Winform程序main函数都有清晰的定义,可以很容易找到,但是WPF的工程文件中却找不到main函数的定义,是WPF不需要main函数吗?N ...
随机推荐
- Hibernate (ORM)
1 框架体系结构 2 hibernate入门 2.1 ORM框架 Hibernate是一个数据持久化层的ORM框架. Object:对象,java对象,此处特指JavaBean Relational: ...
- MongoDB 创建集合
createCollection() 方法 MongoDB db.createCollection(name, options) 是用来创建集合. 语法: 基本的 createCollection() ...
- mysql 更新sql报错:You can't specify target table 'wms_cabinet_form' for update in FROM clause
数据库里面有两个字段的位置不对,要把他们对调换下.因为没有数据库写的权限,需要用sql语句来实现.原来以为简单的 update table a set a.字段a=(select b字段 from t ...
- Java基础之多线程详细分析
在了解多线程之前,先来了解一下进程与线程之间的关系. 进程和线程: 进程是指在系统中正在执行的一个程序,每个进程之间是独立的. 线程是进程的一个基本执行单元.一个进程要想执行任务,必须得有线程(每1个 ...
- atom 常用配置
基本配置 setting 位于 File -> setting 显示HTML标签闭合的竖线 Setting -> Editor Setting -> 勾选 Show Indent G ...
- angular2 应用 不同的environment 进行 build/serve
文件目录如下: 命令行使用:ng serve --e=dev/offline/prod build 不同,像上面那样写没用.必须后面再加--prod 如: ng build --e=offline - ...
- [使用经验]cocostudio UI编辑器的裁剪
日志-2015/03/16 描述:在程序使用UI编辑器导出文件的时候,该panel中大于panel的部分都没有显示出来,例如人物,一些特效等 原因:UI编辑器panel都勾上了裁剪 解决:在编辑器中把 ...
- nginx的开机自启、server命令启动、nginx.conf配置
1.将Nginx设置为开机自动启动 a.当上面6步完成之后,说明安装已经完全成功了,但是每次开机我们面临的一个问题,就是每次都要执行命令(1: cd /usr/local/nginx/sbin/ ...
- $.on()方法和addEventListener改变this指向
jQuery $.on()方法和addEventListener改变this指向 标签(空格分隔): jQuery JavaScript jQuery $.on() jq的绑定事件使用$([selec ...
- eclipse通过maven进行打包并且对hdfs上的文件进行wordcount
在eclipse中配置自己的maven仓库 1.安装maven(用于管理仓库,jar包的管理) -1.解压maven安装包 -2.把maven添加到环境变量/etc/profile -3.添加mave ...