ARM程序剖析--ARM程序结构,Image文件结构等

ZCShou标签: ARM程序,Image文件

说明:1、今天学习到ARM程序,于是到网上找了不少资料,发现真正有用的并不是很多。而且经过我的实际测试,与网上部分大神说的有不少出入

2、测试环境 WinXp  RVDS2.2的编译器和连接器

3、关于测试使用的工具           

一、ARM程序的组成

此处所说的“ARM程序”是指在ARM系统中正在执行的程序,而非保存在ROM中的映像(image)文件。烧录到ROM中的image文件与实际运行时的ARM程序之间并不是完全一样的。

一个ARM程序包含3部分:RO,RW 和 ZI

  1. RO:是程序中的指令和常量      ,ReadOnly    只读的代码段和常量
  2. RW:是程序中的已初始化变量  , ReadWrite  可读写的全局变量和静态变量
  3. ZI:是程序中的未初始化的变量 , ZeroInit      RW段中要被初始化为零的变量的段(也就是说该段包含在RW内)

由以上3点在C语言中的表现:

1、C 中的指令以及常量被编译后是RO类型数据。
2、C 中的未被初始化或初始化为0的变量编译后是ZI类型数据。(这点注意
3、C 中的已被初始化成非0值的变量编译后是RW类型数据。

关于上面的这些,我将在下面,用实际的例子来说明。

二、ARM映像文件的组成

        所谓ARM映像文件其实就是可执行文件,也成为image文件,又叫ELF文件。包括bin或hex两种格式,可以直接烧到rom里执行。在AXD调试过程中,我们调试的是 .axf 文件,其实这也是一种映像文件,它只是在bin文件中加了一个文件头和一些调试信息

        映像文件一般由组成,域最多由三个输出段组成(RO,RW,ZI)组成,输出段又由输入段组成。所谓域,指的就是整个bin映像文件所处在的区域,它又分为加载域运行域。我们输入的代码,一般有代码部分和数据部分,这就是所谓的输入段,经过编译后就变成了bin文件中RO段和RW段,还有所谓的ZI段,这就是输出段。

        加载域:就是Image被静态存放的区域,一般就是指烧在flash中的整个bin文件;

        运行域:通常是程序都是被搬到SDRAM中运行,该Image被搬在SDRAM里工作所处的地址空间就是运行域。

对于加载域中的输出段,一般来说RO段后面紧跟着RW段,RW段后面紧跟着ZI段。运行域中这些输出段并不连续,但RW和ZI一定是连着的。ZI段和RW段中的数据其实可以是RW属性。

        Image文件一般只包含了RO和RW数据。之所以Image文件不包含ZI数据,是因为ZI数据都是0,没必要包含,只要程序运行之前将ZI数据所在的区域一律清零即可。包含进去反而浪费存储空间。

实际上,ROM中的指令至少应该有这样的功能:
        1、将RW从ROM中搬到RAM中。因为RW是变量,变量不能存在ROM中。
        2、将ZI所在的RAM区域全部清零。因为ZI区域并不在Image中,所以需要程序根据编译器给出的ZI地址及大小来将相应得RAM区域清零。ZI中也是变量,同理:变量不能存在ROM中
在程序运行的最初阶段,RO中的指令完成了这两项工作后C程序才能正常访问变量。否则只能运行不含变量的代码。

三、实例测试

(1) RO段测试

下面两段程序,他们之间差了一条语句,这条语句就是声明一个字符常量。因此按照我们之前说的,他们之间应该只会在RO数据中一条语句的大小。

Pro1:

   1: #include <stdio.h>
   2: void main(void)
   3: {
   4: ;
   5: }

Pro2:

   1: #include <stdio.h>
   2: const char ch = 2;  // 常量
   3: void main(void)
   4: {
   5: ;
   6: }

Pro3:

   1: #include <stdio.h>
   2: const char ch = 2;
   3: int main(void)
   4: {
   5:     return 0;
   6: }

Pro1的编译结果:

      Code   (inc. data)   RO Data    RW Data    ZI Data      Debug  

      932      32            16          0         96          0   Grand Totals

      932      32            16          0         96          0   Image Totals

================================================================================

    Total RO  Size (Code + RO Data)                          948 (   0.93kB)

    Total RW  Size (RW Data + ZI Data)                     96 (   0.09kB)

    Total ROM Size (Code + RO Data + RW Data)        948 (   0.93kB)

================================================================================

Pro2的编译结果:

      Code  (inc. data)   RO Data    RW Data    ZI Data      Debug  

      932      32          20          0         96          0   Grand Totals

      932      32          20          0         96          0   Image Totals

================================================================================

    Total RO  Size (Code + RO Data)                          952 (   0.93kB)

    Total RW  Size (RW Data + ZI Data)                     96 (   0.09kB)

    Total ROM Size (Code + RO Data + RW Data)        952 (   0.93kB)

================================================================================

Pro3的编译结果:

      Code    (inc. data)   RO Data    RW Data    ZI Data      Debug  

       936         32             20              0             96          0   Grand Totals

       936         32             20              0             96          0   Image Totals

================================================================================

    Total RO  Size (Code + RO Data)                          956 (   0.93kB)

    Total RW  Size (RW Data + ZI Data)                     96 (   0.09kB)

    Total ROM Size (Code + RO Data + RW Data)        956 (   0.93kB)

================================================================================

由上面的编译结果(尤其是加红部分)可知:常量被放在了 RO段中,验证第一点。增加一条语句时,Code部分大小增大。

(2) RW段测试

Pro4和Pro1 之间只相差一个“已初始化为非零的变量“,按照之前所讲的,已初始化的变量应该是算在RW中的,所以两个程序之间应该是RW大小有区别。

Pro4:

   1: #include <stdio.h>
   2: char a = 5;
   3: void main(void)
   4: {
   5: ;
   6: }

Pro5:

   1: #include <stdio.h>
   2: char a = 0;
   3: void main(void)
   4: {
   5: ;
   6: }

Pro4 的编译结果:

      Code     (inc. data)   RO Data    RW Data    ZI Data      Debug  

       932         32              16             4             96          0   Grand Totals

       932         32              16             4             96          0   Image Totals

================================================================================

    Total RO  Size (Code + RO Data)                          948 (   0.93kB)

    Total RW  Size (RW Data + ZI Data)                     100 (   0.10kB)

    Total ROM Size (Code + RO Data + RW Data)        952 (   0.93kB)

================================================================================

Pro5 的编译结果:

      Code     (inc. data)   RO Data    RW Data    ZI Data      Debug  

       932         32             16              4             96          0   Grand Totals

       932         32             16              4             96          0   Image Totals

================================================================================

    Total RO  Size (Code + RO Data)                          948 (   0.93kB)

    Total RW  Size (RW Data + ZI Data)                     100 (   0.10kB)

    Total ROM Size (Code + RO Data + RW Data)        952 (   0.93kB)

================================================================================

Pro4与 Pro1 相比,只有 RW Data段 多了4字节。

在Pro5中,对于初始化为0的变量,其仍然放在了RW区。

(3) ZI 段测试

Pro5 和 Pro1 之间的差别是一个未初始化的变量“a”,从之前的了解中,应该可以推测,这两个程序之间应该只有ZI大小有差别。

Pro5:

   1: #include <stdio.h>
   2: char a;
   3: void main(void)
   4: {
   5: ;
   6: }

Pro5的编译结果:

      Code      (inc. data)   RO Data    RW Data    ZI Data      Debug  

       932             32          16              4             96          0   Grand Totals

       932             32          16              4             96          0   Image Totals

================================================================================

    Total RO  Size (Code + RO Data)                          948 (   0.93kB)

    Total RW  Size (RW Data + ZI Data)                     100 (   0.10kB)

    Total ROM Size (Code + RO Data + RW Data)        952 (   0.93kB)

================================================================================

实际情况是,未初始化的变量放在了 RW区,而不是ZI区

四、总结

通过上面的测试发现,ZI根本就没用到。这很费解。以下是Pro5的完整编译文件

ARM Linker, RVCT2.2 [Build 349]

================================================================================

Memory Map of the image

  Image Entry point : 0x00008000

  Load Region LR_1 (Base: 0x00008000, Size: 0x000003b8, Max: 0xffffffff, ABSOLUTE)

    Execution Region ER_RO (Base: 0x00008000, Size: 0x000003b4, Max: 0xffffffff, ABSOLUTE)

    Base Addr    Size         Type   Attr      Idx    E Section Name        Object

    0x00008000   0x00000008   Code   RO            6  * !!!main             __main.o(c_a__un.l)

    0x00008008   0x00000038   Code   RO           26    !!!scatter          __scatter.o(c_a__un.l)

    0x00008040   0x0000002c   Code   RO           27    !!handler_zi        __scatter_zi.o(c_a__un.l)

    0x0000806c   0x00000010   Code   RO           11    .emb_text           lib_init.o(c_a__un.l)

    0x0000807c   0x00000004   Code   RO            1    .text               test.o

    0x00008080   0x00000048   Code   RO            7    .text               kernel.o(c_a__un.l)

    0x000080c8   0x00000018   Code   RO            8    .text               sys_exit.o(c_a__un.l)

    0x000080e0   0x00000018   Code   RO            9    .text               exit.o(c_a__un.l)

    0x000080f8   0x000000fc    Code   RO           10    .text               stkheap1.o(c_a__un.l)

    0x000081f4   0x00000108   Code   RO           12    .text               lib_init.o(c_a__un.l)

    0x000082fc   0x00000004   Code   RO           13    .text               boardinit1.o(c_a__un.l)

    0x00008300   0x0000000c   Code   RO           14    .text               boardinit2.o(c_a__un.l)

    0x0000830c   0x0000000c   Code   RO           15    .text               boardinit3.o(c_a__un.l)

    0x00008318   0x00000004   Code   RO           16    .text               boardshut.o(c_a__un.l)

    0x0000831c   0x0000004c   Code   RO           17    .text               sys_stackheap.o(c_a__un.l)

    0x00008368   0x0000000c   Code   RO           18    .text               libspace.o(c_a__un.l)

    0x00008374   0x00000004   Code   RO           20    .text               use_semi.o(c_a__un.l)

    0x00008378   0x00000004   Code   RO           21    .text               cpuinit.o(c_a__un.l)

    0x0000837c   0x00000010   Code   RO           23    .text               rt_fp_status_addr.o(c_a__un.l)

    0x0000838c   0x00000004   Code   RO            2    i.__ARM_get_argv    test.o

    0x00008390   0x00000014   Code   RO           22    x$fpl$fpinit        fpinit.o(fz_a_p.l)

    0x000083a4   0x00000010   Data   RO           24    Region$$Table       anon$$obj.o

    Execution Region ER_RW (Base: 0x000083b4, Size: 0x00000004, Max: 0xffffffff, ABSOLUTE)

    Base Addr    Size         Type   Attr      Idx    E Section Name        Object

    0x000083b4   0x00000001   Data   RW            3    .data               test.o

    Execution Region ER_ZI (Base: 0x000083b8, Size: 0x00000060, Max: 0xffffffff, ABSOLUTE)

    Base Addr    Size         Type   Attr      Idx    E Section Name        Object

    0x000083b8   0x00000060   Zero   RW           19    .bss                libspace.o(c_a__un.l)

================================================================================

Image component sizes

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name

         8          0          0          1          0          0   test.o

    ------------------------------------------------------------------------

         8          0         16          4          0          0   Object Totals

         0          0         16          0          0          0   (incl. Generated)

         0          0          0          3          0           0   (incl. Padding)

    ------------------------------------------------------------------------

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Member Name

         8          0          0          0          0          0   __main.o

        56          8          0          0          0          0   __scatter.o

        44          0          0          0          0          0   __scatter_zi.o

         4          0          0          0          0          0   boardinit1.o

        12          0          0          0          0          0   boardinit2.o

        12          0          0          0          0          0   boardinit3.o

         4          0          0          0          0          0   boardshut.o

         4          0          0          0          0          0   cpuinit.o

        24          0          0          0          0          0   exit.o

        20          0          0          0          0          0   fpinit.o

        72          0          0          0          0          0   kernel.o

       280          4          0          0          0          0   lib_init.o

        12          4          0          0         96          0   libspace.o

        16          0          0          0          0          0   rt_fp_status_addr.o

       252          0          0          0          0          0   stkheap1.o

        24          8          0          0          0          0   sys_exit.o

        76          8          0          0          0          0   sys_stackheap.o

         4          0          0          0          0          0   use_semi.o

    ------------------------------------------------------------------------

       924         32          0          0         96          0   Library Totals

         0          0          0          0          0          0   (incl. Padding)

    ------------------------------------------------------------------------

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Name

       904         32          0          0         96          0   c_a__un.l

        20          0          0          0          0          0   fz_a_p.l

    ------------------------------------------------------------------------

       924         32          0          0         96          0   Library Totals

    ------------------------------------------------------------------------

================================================================================

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug  

       932         32         16          4         96          0   Grand Totals

       932         32         16          4         96          0   Image Totals

================================================================================

    Total RO  Size (Code + RO Data)                  948 (   0.93kB)

    Total RW  Size (RW Data + ZI Data)               100 (   0.10kB)

    Total ROM Size (Code + RO Data + RW Data)        952 (   0.93kB)

================================================================================

至于原因,还没验证出来,等后面接着验证吧!!

 

 

 

 

 

 

时间: 2024-10-22 15:47:53

ARM程序剖析--ARM程序结构,Image文件结构等的相关文章

Windows-MFC框架程序剖析

MFC框架程序剖析 1.MFC Microsoft Foundation Class,微软基础类库,是微软开发的C++集合,方便我们使用它来编写Windows程序. 下面是4个基本的类,我们的Visual C++程序基本都会有这4个类 2.MFC AppWizard 它是一个辅助我们生成源代码的工具,它可以帮助我们自动生成基于MFC的源代码,使我们可以定制自己的程序. 3.MFC中的WinMain函数 在MFC中找不到WinMain函数,因为MFC为我们封装了WinMain函数的调用,所以我们看

S1/使用Java理解程序逻辑/05-循环结构(一)

Java程序中的循环结构有3种实现方式:while循环结构.do-while循环结构和for循环结构. 如何进行程序调试 (1)分析错误,设置断点. Toggle Breakpoint或在该代码行左侧边栏处双击 (2)启动调试,单步执行. 在调试视图中,按F5键或F6键都是单步执行,它们的区别如下. 按F5键“单步跳入”,会进入本行代码内部执行,如进入方法内部. 按F6键“单步跳过”,仅执行本行代码,执行完则跳到下一行代码. 单步执行过程中,可以在变量视图中观察变量的值,可通过选择“Window

.NET零基础入门之01:开篇及CSharp程序、解决方案的结构

一:为什么选择C# 每个人都有梦想,有些人的梦想就是:成为程序员.最课程(www.zuikc.com)的<零基础c#入门>是试图帮助我们实现这个梦想. 也许你要问:我基础很差怎么办?最课程的<零基础c#入门>假设你基础差到从来没有写过一行程序.当然,我们也相信,本系列学习对于大学本科学的计算机,但是又初入程序员这个行业的同学有很大帮助. 现在,我们言归正传,为什么选择C#? 为什么要选择C#作为你成为程序员的第一门语言,我们这里归结的原因有3个: ? 首先,C#是一门非常优秀的面向

Python封装应用程序的最佳项目结构是什么?

Python封装应用程序的最佳项目结构是什么? 转载来源于stackoverflow:https://stackoverflow.com/questions/193161/what-is-the-best-project-structure-for-a-python-application 和http://www.cnblogs.com/alex3714/articles/5765046.html#3719169 开发一个终端用户桌面应用(非网页),最佳的项目文件夹层次结构是怎样的? 理想的项目

程序通过定义学生结构体变量,存储学生的学号、姓名和3门课的成绩。函数fun的功能是:对形参b所指结构体变量中的数据进行修改,并在主函数中输出修改后的数据。

程序通过定义学生结构体变量,存储学生的学号.姓名和3门课的成绩.函数fun的功能是:对形参b所指结构体变量中的数据进行修改,并在主函数中输出修改后的数据.例如,若b所指变量t中的学号.姓名和三门课的成绩一次是:10002."ZhangQi".93.85.87,修改后输出t中的数据应为:10004."Lijie".93.85.87. #include <stdio.h>#include <string.h>struct student { lo

图解简单C程序的运行时结构

程序在内存中的存储分为三个区域,分别是动态数据区.静态数据区和代码区.函数存储在代码区,全局变量以及静态变量存储在静态数据区,而在程序执行的时候才会在动态数据区产生数据.程序执行的本质就是代码区的指令不断执行,驱使动态数据区和静态数据区产生数据变化. 代码区与动态数据区由三个寄存器控制,分别是eip.ebp和esp.eip指向代码区下一个要执行的指令,ebp与esp分别指向动态数据区的栈底和栈顶.初始情况下eip默认指向main函数的第一条指令,esp.ebp指向的位置由程序加载时内核的设置决定

【嵌入式开发】ARM 芯片简介 (ARM芯片类型 | ARM处理器工作模式 | ARM 寄存器 | ARM 寻址)

作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42375701 相关资源下载 :  -- 三星 ARM Architecture Reference Manual 文档 : http://download.csdn.net/detail/han1202012/8324641 一. ARM 芯片类型 1. ARM 分类 (1) ARM 分类类型(芯片 | 核 | 指令架构) ARM 分类 : -- ARM 芯片类型

程序员突围-程序调试分析(一) 我从菜鸟进化的感悟

程序员突围-程序调试分析(一) 我从菜鸟进化的感悟 在说程序调试分析之前,我们还是了解一些基本的概念性的东西(在下现在从事java,因而都已java为例) 1. bug的分类 根据程序的阶段和MSDN和看过的一些书籍的分析,bug分为编译错误,运行时错误和逻辑的错误 (1)  编译错误 一般初学者犯错比较多的地方,编译错误,说白了就是程序在从java编译成.class文件时出现了问题,这个问题的现象比较明显,比如说语句写的有问题,那么对于这类问题的解决方法是什么呢,翻翻书,翻翻API(翻阅API

改善C#程序,提高程序运行效率的50种方法

改善C#程序,提高程序运行效率的50种方法 转自:http://blog.sina.com.cn/s/blog_6f7a7fb501017p8a.html 一.用属性代替可访问的字段 1..NET数据绑定只支持数据绑定,使用属性可以获得数据绑定的好处: 2.在属性的get和set访问器重可使用lock添加多线程的支持. 二.readonly(运行时常量)和const(编译时常量) 1.const只可用于基元类型.枚举.字符串,而readonly则可以是任何的类型: 2.const在编译时将替换成