说明: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 <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)
================================================================================
至于原因,还没验证出来,等后面接着验证吧!!