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的地方都已经补足了。

原文地址:https://www.cnblogs.com/fozu/p/3614068.html