# 5.4. Array Loop Shifted Index¶

The loop shown on the last page to loop over an array of words works fine, but uses a lot of registers for book keeping. We use one register for the base address of the array, another for the index of the array (to test when we are done), and another to keep track of the memory offset.

But, the index and offset are redundant. For word index 0 the offset will always be 0, for word index 1 the offset will be 4, for index 2 the offset will be 8,… The offset is always 4x the index.

The ARM instruction set provides a trick to avoid storing the index and 4x the index. When we go to use the index of an array to load data, we can shift it 2 bits. This effectively multiplies it by 4, turning the value 0 into 0, 1 into 4, 2 into 8, etc…

`LDR`rd, [rn, rm, lsl #]

Access the memory at the byte address rn + (rm shifted left # bits), and store its value into rd. Typically, we will use a shift of 2 to multiply rm by 4. Similar [rn, rm, lsl #] syntax is available for STR.

This code sample below demonstrates looping through an array using this technique. It copies data from myArray to the empty space at doubled and doubles each element of the array as it copies it. It is roughly equivalent to:

```int myArraySize = 5;
int myArray[5] = {10, 20, 30, 40, 50};
int doubled[5];

int i = 0;
while(i < myArraySize) {
doubled[i] = 2 * myArray[i];
i++;
}
```

In the assembly version, we hold the base address of the original array in `r2` and the address of doubled in `r3`. `r4` is the index - to use it to find the offset of an element in an array we shift it left 2 bits.

 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39``` ```.data @An array of 5 ints myArray: .word 10, 20, 30, 40, 50 arraySize: .word 5 @size of myArray doubled: .space 20 @20 bytes = 5 words .text _start: LDR r1, =arraySize @ r1 = &arraySize LDR r1, [r1] @ r1 = arraySize LDR r2, =myArray @ load myArray start address LDR r3, =doubled @ load newArray start address MOV r4, #0 @ r4 = loop counter B looptest @ jump ahead to loop test loopstart: @myArray[i]'s address is r2 + (4 * r4) LDR r5, [r2, r4, lsl #2] @ r5 = myArray[i] LSL r5, r5, #1 @double r5 @doubled[i]'s address is r3 + (4 * r4) STR r5, [r3, r4, lsl #2] @ doubled[i] = r5 @go to next step ADD r4, r4, #1 @ add one to counter looptest: CMP r4, r1 @ Compare counter r4 to size of array in r1 BLT loopstart @ If counter Less Than size, go back to start end: B end @stop here ```
Try sample