ARM program analysis--ARM program structure, Image file structure, etc.

Publisher:SereneMeadowLatest update time:2024-09-18 Source: cnblogsKeywords:ARM Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Note: 1. I learned about ARM programming today, so I searched for a lot of information online, but found that there were not many that were really useful. And after my actual test, there were quite a few differences from what some experts on the Internet said.


2. Test environment WinXp RVDS2.2 compiler and connector


3. About the tools used for testing


1. Composition of ARM Program

The "ARM program" mentioned here refers to the program being executed in the ARM system, not the image file saved in ROM. The image file burned into ROM is not exactly the same as the ARM program when it is actually running.


An ARM program consists of 3 parts: RO, RW and ZI


RO: Instructions and constants in the program, ReadOnly read-only code segments and constants

RW: initialized variables in the program, ReadWrite global variables and static variables that can be read and written

ZI: is an uninitialized variable in the program, ZeroInit is the segment of the variable to be initialized to zero in the RW segment (that is, the segment is contained in RW)

The above three points are expressed in C language:


1. The instructions and constants in C are compiled into RO type data.

2. Uninitialized or initialized variables in C are ZI type data after compilation. (Note this)

3. Variables in C that have been initialized to non-zero values ​​are RW type data after compilation.


I will illustrate the above with practical examples below.


2. Composition of ARM image files

The so-called ARM image file is actually an executable file, also known as an image file, also called an ELF file. It includes two formats, bin or hex, and can be directly burned into ROM for execution. During the AXD debugging process, we debug the .axf file, which is actually an image file. It just adds a file header and some debugging information to the bin file.


Image files are generally composed of domains, which are composed of up to three output segments (RO, RW, ZI), and the output segments are composed of input segments. The so-called domain refers to the area where the entire bin image file is located, which is divided into the loading domain and the running domain. The code we input generally has a code part and a data part, which is the so-called input segment. After compilation, it becomes the RO segment and RW segment in the bin file, and the so-called ZI segment, which is the output segment.


Loading domain: It is the area where the image is statically stored, generally refers to the entire bin file burned in the flash;


Running domain: Usually programs are moved to SDRAM to run, and the address space where the image is moved to SDRAM to work is the running domain.


For the output segments in the load domain, generally speaking, the RO segment is followed by the RW segment, and the RW segment is followed by the ZI segment. In the run domain, these output segments are not continuous, but RW and ZI must be connected. The data in the ZI segment and RW segment can actually be RW attributes.


Image files generally only contain RO and RW data. The reason why image files do not contain ZI data is that ZI data is always 0, so there is no need to include it. Just clear the area where ZI data is located before running the program. Including it will waste storage space.


In fact, the instructions in ROM should at least have the following functions:

1. Move RW from ROM to RAM. Because RW is a variable, variables cannot be stored in ROM.

2. Clear all RAM areas where ZI is located. Because the ZI area is not in the Image, the program needs to clear the corresponding RAM area according to the ZI address and size given by the compiler. ZI is also a variable, and similarly: variables cannot be stored in ROM

In the initial stage of program execution, the C program can access variables normally only after the instructions in RO complete these two tasks. Otherwise, only the code without variables can be executed.


3. Example Test

(1) RO segment test


The following two programs differ in one statement, which is to declare a character constant. Therefore, according to what we said before, the difference between them should only be the size of one statement in RO data.


Pro1:


1: #include

2: void main(void)

3: {

4: ;

5: }

Pro2:


1: #include

2: const char ch = 2; // constant

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 compilation result:


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 compilation result:


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 compilation result:


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)


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


From the compilation results above (especially the red part), we can see that the constant is placed in the RO segment, which verifies the first point. When a statement is added, the size of the Code section increases.


(2) RW segment test


The only difference between Pro4 and Pro1 is "variables initialized to non-zero". According to what was said before, initialized variables should be counted in RW, so there should be a difference in the size of RW between the two programs.


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 compilation result:


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 compilation result:


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)


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


Compared with Pro1, Pro4 only has 4 more bytes in the RW Data segment.


In Pro5, variables initialized to 0 are still placed in the RW area.


(3) ZI segment test


The difference between Pro5 and Pro1 is an uninitialized variable "a". From the previous understanding, it can be inferred that the only difference between the two programs should be the ZI size.


Pro5:


1: #include

2: char a;

3: void main(void)

4: {

5: ;

6: }

Pro5 compilation results:


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)


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


The actual situation is that uninitialized variables are placed in the RW area, not the ZI area.


IV. Conclusion

The above test found that ZI is not used at all. This is very puzzling. The following is the complete compilation file of Pro5

[1] [2]
Keywords:ARM Reference address:ARM program analysis--ARM program structure, Image file structure, etc.

Previous article:JLink debugging method for S3C6410
Next article:S3C6410 SPI full-duplex read and write process analysis

Latest Microcontroller Articles
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
    Since development under LINUX is still quite troublesome, is there a more convenient and simple development method under WINDOWS? The answer is yes. Of course, it is not a development tool like ADS, because it ...
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
  • Learn ARM development(18)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

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