The main difference between pre-indexed and post-indexed addressing modes in Arm Cortex M is that in pre-indexed addressing, the offset is added to the base register value first and then the result is used as the address for the memory access operation. In post-indexed addressing, the value in the base register is used directly as the address, and then the offset is added to the base register value after the memory access.
Overview of Addressing Modes in Arm Cortex M
The Arm Cortex M processors support several different addressing modes to access memory. These include:
- Register Addressing – The address is contained in a register like R0, R1 etc.
- Immediate Addressing – The address is specified as an immediate value in the instruction itself.
- Absolute Addressing – The full address is directly encoded in the instruction.
- PC-Relative Addressing – The address is specified as a relative offset from the current PC value.
- Indexed Addressing – The address is calculated by adding an offset to a base register value.
The indexed addressing mode is further divided into pre-indexed and post-indexed addressing:
- Pre-Indexed – Offset is added to base before memory access.
- Post-Indexed – Offset is added to base after memory access.
Pre-Indexed Addressing
In pre-indexed addressing mode, the offset is first added to the value contained in the base register. The result of this addition is then used as the address for the memory access operation. Some key points about pre-indexed addressing:
- The offset can be a register value or an immediate value encoded in the instruction.
- The base register value is unchanged, only the address calculation is affected.
- Good for array access where offset can be index into the array.
- Same address value can be reused by enclosing in a loop.
For example: LDR R0, [R1, #8] // R1 has base address, 8 is offset STR R2, [R3, R5] // R3 has base, R5 is offset register
In both cases above, the offset is first added to the base register value and the result is used to fetch/store from memory. The base register R1 and R3 remain unchanged after the instruction executes.
Post-Indexed Addressing
In post-indexed addressing mode, the value contained in the base register is directly used as the address for memory access. The offset is then added to the base register value after the memory access completes. Some key points about post-indexed addressing:
- The offset can be a register value or an immediate value encoded in the instruction.
- The base register is updated with the new address after the access.
- Useful for pointer manipulation like traversing arrays, linked lists etc.
- Base register contains updated pointer once instruction completes.
For example: LDR R0, [R1], #8 // Load from R1, then add 8 to R1 STR R2, [R3], R5 // Store to R3, then add R5 to R3
In both cases above, the base register R1 and R3 are used directly as the address for memory access. After the access, the value of R1 and R3 are updated by adding the offset.
Pre-Indexed vs Post-Indexed Addressing
Here is a summary of the key differences between pre-indexed and post-indexed addressing modes in Arm Cortex M:
- Offset application – Pre-indexed adds offset first, post-indexed adds offset after memory access.
- Base register – Not updated in pre-indexed, updated in post-indexed.
- Use cases – Pre-indexed good for array access. Post-indexed good for pointer manipulation.
- Reusing address – Easier with pre-indexed addressing.
In terms of performance, there is no significant difference between pre-indexed and post-indexed addressing. The processor can perform both types of address calculation efficiently.
The choice depends mainly on the algorithm and data structure used. Pre-indexed addressing is useful when you want to reuse the same calculated address multiple times, for example when accessing array elements in a loop. Post-indexed addressing helps traverse data structures like linked lists by updating the pointer after each access.
Pre-Indexed Addressing Example
Here is an example of pre-indexed addressing to add two arrays element-by-element: // R1 = pointer to array A // R2 = pointer to array B // R3 = pointer to array C // R0 holds sum LOOP: LDR R0, [R1, #i] // Load A[i] LDR R4, [R2, #i] // Load B[i] ADD R0, R0, R4 // R0 = A[i] + B[i] STR R0, [R3, #i] // Store result to C[i] ADD i, i, #4 // Increment index to next element CMP i, #100 BLT LOOP
In the above example, R1, R2 and R3 point to the start of the arrays A, B and C respectively. The index value ‘i’ is used as the offset from these base registers to access individual elements. Since ‘i’ is incremented in each loop iteration, the next element is automatically accessed.
Pre-indexed addressing allows reusing the same offset ‘i’ efficiently to calculate the address for the load, store operations. The base registers R1, R2, R3 remain unchanged after the loop completes.
Post-Indexed Addressing Example
Here is an example of post-indexed addressing to traverse a linked list: // R1 points to head of linked list LOOP: LDR R2, [R1] // Load link field, contains address of next node LDR R0, [R1, #4] // Load data field STR R0, [R3, #i] // Store data to array ADD R1, R1, R2 // Update R1 to point to next node ADD i, i, #4 // Increment index CMP R1, #0 // Check for end of list BNE LOOP
In this example, R1 points to the current node in the linked list. The link field contains the address of the next node. So R1 is updated using post-indexed addressing to point to the next node after accessing each node.
This allows the linked list to be traversed efficiently without needing an additional register to hold the next pointer. The base register R1 is updated automatically by the post-indexed addressing mode.
Guidelines for Choosing Addressing Mode
Here are some general guidelines on when to use each addressing mode:
- Use pre-indexed for array, table, matrix access – offset can be index.
- Use post-indexed for traversing linked lists, trees etc – pointer updated automatically.
- If offset is variable, prefer pre-indexed so base doesn’t change.
- If offset is fixed or loop counter, prefer post-indexed.
- Choose the mode that needs fewer instructions/registers for addressing.
The ARM Cortex M Assembly language provides flexibility to use both modes. Choose the addressing mode based on the algorithm and data structure to write efficient code.
Conclusion
Pre-indexed and post-indexed addressing provide different ways to access memory based on program requirements. Pre-indexed leaves the base register unchanged while post-indexed updates it after the access. Understanding the difference allows selecting the right mode to optimize code for array access, pointer manipulation and other use cases on Arm Cortex M platforms.