2.10.8. Avoiding problems with MAP and FIELD directives

Using MAP and FIELD directives can help you to produce maintainable data structures. However, this is only true if the order the elements are placed in memory is not important to either the programmer or the program.

You can have problems if you load or store multiple elements of a structure in a single instruction. These problems arise in operations such as:

These operations require the data elements in the structure to be contiguous in memory, and to be in a specific order. If the order of the elements is changed, or a new element is added, the program is broken in a way that cannot be detected by the assembler.

There are several methods for avoiding problems such as this.

Example 2.27 shows a sample structure.

Example 2.27. 

MiscBase        RN      r10
                MAP     0,MiscBase
MiscStart       FIELD   0
Misc_a          FIELD   1
Misc_b          FIELD   1
Misc_c          FIELD   1
Misc_d          FIELD   1
MiscEndOfChars  FIELD   0
MiscPadding     FIELD   (-:INDEX:MiscEndOfChars) :AND: 3
Misc_I          FIELD   4 
Misc_J          FIELD   4
Misc_K          FIELD   4
Misc_data       FIELD   4*20
MiscEnd         FIELD   0
MiscLen         EQU     MiscEnd-MiscStart

There is no problem in using LDM and STM instructions for accessing single data elements that are larger than a word (for example, arrays). An example of this is the 20-word element Misc_data. It could be accessed as follows:

ArrayBase   RN      R9
            ADR     ArrayBase, MiscBase
            LDMIA   ArrayBase, {R0-R5}

Example 2.27 loads the first six items in the array Misc_data. The array is a single element and therefore covers contiguous memory locations. No one is likely to want to split it into separate arrays in the future.

However, for loading Misc_I, Misc_J, and Misc_K into registers r0, r1, and r2 the following code works, but might cause problems in the future:

ArrayBase   RN r9
            ADR     ArrayBase, Misc_I
            LDMIA   ArrayBase, {r0-r2}

Problems arise if the order of Misc_I, Misc_J, and Misc_K is changed, or if a new element Misc_New is added in the middle. Either of these small changes breaks the code.

If these elements are accessed separately elsewhere, you must not amalgamate them into a single array element. In this case, you must amend the code. The first remedy is to comment the structure to prevent changes affecting this section:

Misc_I      FIELD   4    ;  ==} Do not split/reorder
Misc_J      FIELD   4    ;    } these 3 elements, STM 
Misc_K      FIELD   4    ;  ==} and LDM instructions used.

If the code is strongly commented, no deliberate changes are likely to be made that affect the workings of the program. Unfortunately, mistakes can occur. A second method of catching these problems is to add ASSERT directives just before the STM and LDM instructions to check that the labels are consecutive and in the correct order:

ArrayBase   RN      R9
                            ; Check that the structure elements
                            ; are correctly ordered for LDM
    ASSERT  (((Misc_J-Misc_I) = 4) :LAND: ((Misc_K-Misc_J) = 4)) 
            ADR     ArrayBase, Misc_I
            LDMIA   ArrayBase, {r0-r2}

This ASSERT directive stops assembly at this point if the structure is not in the correct order to be loaded with an LDM. Remember that the element with the lowest address is always loaded from, or stored to, the lowest numbered register.

Copyright © 2000, 2001 ARM Limited. All rights reserved.ARM DUI 0068B