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

发布者:SereneMeadow最新更新时间:2024-09-18 来源: cnblogs关键字:ARM  程序结构  文件结构 手机看文章 扫描二维码
随时随地手机看文章

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


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


3、关于测试使用的工具           


一、ARM程序的组成

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


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


RO:是程序中的指令和常量      ,ReadOnly    只读的代码段和常量

RW:是程序中的已初始化变量  , ReadWrite  可读写的全局变量和静态变量

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

   2: void main(void)

   3: {

   4: ;

   5: }

Pro2:


   1: #include

   2: const char ch = 2;  // 常量

   3: void main(void)

   4: {

   5: ;

   6: }

Pro3:


   1: #include

   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

   2: char a = 5;

   3: void main(void)

   4: {

   5: ;

   6: }

Pro5:


   1: #include

   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

   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)

[1] [2] [3]
关键字:ARM  程序结构  文件结构 引用地址:ARM程序剖析--ARM程序结构,Image文件结构等

上一篇:S3C6410的JLink调试方法
下一篇:S3C6410 SPI全双工读写流程分析

推荐阅读最新更新时间:2024-11-10 16:32

ARM高分辨率压电陶瓷驱动电源设计
压电陶瓷驱动器(PZT)是微位移平台的核心,其主要原理是利用压电陶瓷的逆压电效应产生形变,从而驱动执行元件发生微位移。压电陶瓷驱动器具有分辨率高、响应频率快、推力大和体积小等优点,在航空航天、机器人、微机电系统、精密加工以及生物工程等领域中得到了广泛的应用。然而压电陶瓷驱动器的应用离不开性能良好的压电陶瓷驱动电源。要实现纳米级定位的应用,压电陶瓷驱动电源的输出电压需要在一定范围内连续可调,同时电压分辨率需要达到毫伏级。因此压电陶瓷驱动电源技术已成为压电微位移平台中的关键技术。 直流放大式压电驱动电源的系统结构 驱动电源电路主要由微处理器、D/A转换电路和线性放大电路组成。通过微处理器控制D/A产生高精度、连续可调的直流电压
[单片机]
<font color='red'>ARM</font>高分辨率压电陶瓷驱动电源设计
ARM JTAG SWD SWO SWV
JTAG - Joint Test Action Group JTAG(Joint Test Action Group)联合测试行动小组)是一种国际标准测试协议(IEEE 1149.1兼容) Test Access Port and Boundary-Scan Architecture 主要用于芯片内部测试及对系统进行仿真、调试。现在多数的高级器件都支持JTAG协议,如DSP、FPGA器件等。通常所说的JTAG大致分两类, 一类用于测试芯片的电气特性,检测芯片是否有问题; 一类用于Debug;一般支持JTAG的CPU内都包含了这两个模块。 一个含有JTAG Debug接口模块的CPU,只要时钟正常,就可以通过JTAG接口访问CPU
[单片机]
<font color='red'>ARM</font> JTAG SWD SWO SWV
基于ARM MCU通过AV端口对显示器的控制
设计背景 ARM处理器是世界上最流行的嵌入式处理器,广泛应用于个人通信等嵌入式领域。本文探讨的是基于普通ARM7核的CPU,在需要通过AV端口的显示器进行显示的方法,如在医疗监视器的显示等。 概述 采用基于ARM7核的LPC2104芯片,通过直接连接显示器的AV端口,由LPC2104的GPIO通过电平转换,输出显示器所需要的控制信号,在显示器显示声音和图像。系统有相应的按键,进行相应的菜单控制。 系统分析 通过AV端口在普通显示器要能显示图像,最主要的是能产生如图1所示的场同步脉冲。 图1 场同步脉冲 它必须要有64μs,4.7μs,5.8μs,1.5μs等精确定时信号。本系统采用LPC2104芯片,工作频率为11.0592
[电源管理]
基于<font color='red'>ARM</font> MCU通过AV端口对显示器的控制
柳暗花明:浅谈嵌入式ARM开发的前世今生
  在这个科技高度发达的今天,相信很多在校学生停留在51单片机上的种种应用开发,做一个小玩意,获得个好名次,这在无形中增加了对单片机的理解和认识,对以后的工作奠定雄厚的基础:汇编语言的使用,可以让你在ARM Bootloader的开发上如鱼得水;各种外围器件的使用,可以让你在应用开发中如沐春风。但是,如果仅仅停留在这个阶段,或者说停留在低端单片机的开发应用上,拿到手的 金子 也有限,这就需要你踏入更加广阔的电子领域---嵌入式开发。现在最流行的是 ARM+Linux 构架,如果在这条路上你走的比较远,那么,这对你的生活质量的提高也大有帮助。   由于 ARM+Linux 构架的嵌入式开发范围很广,如果想全部掌握,需要懂Linux使
[单片机]
柳暗花明:浅谈嵌入式<font color='red'>ARM</font>开发的前世今生
arm 2440中nandflash特定存储单元写入一个字节
目标描述: 需要构建一个nandflash_write()函数,入口参数有两个,一个是unsigned int 变量,一个是 unsigned long addr_for_write,然后nandflash_write()函数完成将这个变量写入到addr_for_write中。 解决办法: 第一步:判断所给的这个地址是否是字对齐,否则返回,因为不对齐的话操作起来很麻烦 第二步:选中nandflash芯片 第三步: 复制现成的nand.c文件到我的工程目录下,编译出现如此多的错误,如图 全是尼玛缺少identifier,什么情况啊?在nand.c本身所在工程目录下编译一个
[单片机]
ARM 和DSP的地震加速度信号处理系统设计
1 系统构成及工作原理 地震加速度计由传感探头、光电转换及信号处理系统构成.传感探头由采用基于3x3耦合的光纤M z干涉仪和相关机械部分组成.如图1所示,干涉仪的输入端是一只2x2耦合器,输出端是一只3x3耦合器,被测信号加在干涉仪的传感臂上. 干涉仪的两臂光纤分别缠绕在传感头中的上下两个力臂圆筒上,当外部施加振动时,简谐振子施加给信号臂光纤一个纵向的应力,光纤的长度产生变化 △L (应变效应)、光纤芯的直径d产生变化 △d(泊松效应)、纤芯折射率n产生变化 △n(光弹效应),这些变化将导致光纤中光波的相位发生变化.泊松效应相对应变效应和光弹效应造成的相位变化非常小,可以忽略不计,从而即完成加速度信号对光信号的相位调制.参考臂
[单片机]
<font color='red'>ARM</font> 和DSP的地震加速度信号处理系统设计
Android arm linux 系统调用实现
In this article we will dive into system call interface implementation in arm linux(with gnu eabi).我们将从bionic中的open函数开始追溯arm linux的系统调用实现(使用gnu eabi)。 Linux的应用程序要想访问内核必须使用系统调用从而实现从usr模式转到svc模式。在arm中,这个过程是通过swi(或者和它等价的指令)来实现模式转换的。 从bionic libc中的open函数追溯系统调用实现 相关文件: bionic/libc/unistd/open.c bionic/libc/arch-arm/
[单片机]
浅谈ARM Cortex-M0/M0+ 中的中断抢占问题
简介:Cortex-M0/M0+, M3/M4 中的中断控制器英文名叫做NVIC,Nested Vectored Interrupt Controller,翻译过来就是嵌套向量中断控制器,所谓中断嵌套是指当正在执行一个中断服务程序时,这时如果来了优先级更高的中断,新来的中断会打断原来还没有处理完的中断服务程序,等新中断处理完毕之后再回到原中断服务继续处理。 下面让我们在Kinetis KL26芯片上来实际操作一把吧。KL26芯片为ARM Cortex M0+内核。 硬件:FRDM_KL26Z 软件:FRDM-KL26Z_SC_Rev_1.0 + IAR7.4 1) 先做第一个实验:程序中开启了两个定时器,一个为TP
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved