Skip to main content
\(\newcommand{\doubler}[1]{2#1} \newcommand{\binary}{\texttt} \newcommand{\hex}{\texttt} \newcommand{\octal}{\texttt} \newcommand{\prog}{\texttt} \newcommand{\lt}{<} \newcommand{\gt}{>} \newcommand{\amp}{&} \)

Section15.1Arrays

An array in C/C++ consists of one or more elements, all of the same data type, arranged contiguously in memory. An example is the C-style text strings we have been using in the past few chapters. So far, we have been accessing the elements sequentially, one immediately after the other. This array processing only requires the address of the beginning of the array.

To access a single element in an array we need to specify two address-related items:

  • The beginning of the array.

  • The number of the element to access.

For example, given the declaration in C:

int array[50];

you can store an integer, say \(123\text{,}\) in the \(i-th\) element with the statement

array[i] = 123;

In this example the beginning of the array is specified by using the name, and the number of the element is specified by the [...] syntax. The program in Listing 15.1.1 shows how to access each element in an array directly, both storing a value and reading it.

/* printArray1.c
 * Stores index number in each element of array
 * and prints the array.
 * Bob Plantz - 29 July 2016
 */
#include <stdio.h>

int main(void)
{
  int intArray[10];
  register int index;
   
  for (index = 0; index < 10; index++)
    intArray[index] = index;
    
  for (index = 0; index < 10; index++)
    printf("%i\n", intArray[index]);
  return 0;
}
Listing15.1.1Filling an array and printing it. (C)

Listing 15.1.2 shows a way to access array elements in assembly language.

        .arch armv6
        .fpu vfp
        .file   "printArray1.c"
        .section   .rodata
        .align  2
.LC0:
        .ascii  "%i\012\000"
        .text
        .align  2
        .global main
        .type   main, %function
main:
        @ args = 0, pretend = 0, frame = 40
        @ frame_needed = 1, uses_anonymous_args = 0
        stmfd   sp!, {r4, fp, lr}
        add     fp, sp, #8
        sub     sp, sp, #44
        mov     r4, #0          @@ index = 0;
        b       .L2
.L3:
        mov     r3, r4, asl #2  @@ 4 * index
        sub     r2, fp, #12     @@ address of end of array
        add     r3, r2, r3      @@ index-th element beyond end
        str     r4, [r3, #-40]  @@ minus length of array
        add     r4, r4, #1      @@ index++
.L2:
        cmp     r4, #9          @@ check for end
        ble        .L3
        mov     r4, #0
        b       .L4
.L5:
        mov     r3, r4, asl #2
        sub     r2, fp, #12
        add     r3, r2, r3
        ldr     r3, [r3, #-40]
        ldr     r0, .L7
        mov     r1, r3
        bl      printf
        add     r4, r4, #1
.L4:
        cmp     r4, #9
        ble        .L5
        mov     r3, #0
        mov     r0, r3
        sub     sp, fp, #8
        @ sp needed
        ldmfd   sp!, {r4, fp, pc}
.L8:
        .align  2
.L7:
        .word   .LC0
        .ident        "GCC: (Raspbian 4.9.2-10) 4.9.2"
Listing15.1.2Filling an array and printing it. (gcc asm)

In the code sequence:

mov     r3, r4, asl #2  @@ 4 * index
sub     r2, fp, #12     @@ address of end of array
add     r3, r2, r3      @@ index-th element beyond end
str     r4, [r3, #-40]  @@ minus length of array

the number of bytes from the beginning of the array to specified element is computed by multiplying the index number by four. Next, the address of the end of the array is computed. The byte offset of the specified element is added to the address of the end of the array, which leaves r3 pointing to an address beyond the end of the array. Storing the value (index number in this program) uses a negative offset equal to the total length (in bytes) of the array. So the net result is that the value is stored in the proper location in the array.

I do not know why the compiler writer decided to use this algorithm to access an array. I have used a more direct approach in Listing 15.1.3

@ printArray2.s
@ Stores index number in each element of array
@ and prints the array.
@ Bob Plantz - 29 July 2016

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    nElements,10    @ number of elements in array
        .equ    intArray,-44    @ array beginning
        .equ    decString,-56   @ for decimal text string
        .equ    locals,56       @ space for local vars

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        stmfd   sp!, {r4, r5, fp, lr}   @ save caller's info
        add     fp, sp, 12      @ our frame pointer
        sub     sp, sp, locals  @ for the array
        
        add     r4, fp, intArray  @ address of array beginning
        mov     r5, 0           @ index = 0;
fillLoop:
        cmp     r5, nElements   @ all filled?
        bge     allFull         @ yes
        lsl     r0, r5, 2       @ no, offset is 4 * index
        str     r5, [r4, r0]    @ at index-th element
        add     r5, r5, 1       @ index++;
        b       fillLoop
allFull:
        add     r4, fp, intArray  @ address of array beginning
        mov     r5, 0           @ index = 0;
printLoop:
        cmp     r5, nElements   @ all filled?
        bge     allDone         @ yes
        lsl     r0, r5, 2       @ no, offset is 4 * index
        ldr     r1, [r4, r0]    @ get index-th element
        add     r0, fp, decString  @ to store decimal string
        bl      uIntToDec       @ convert it
        add     r0, fp, decString  @ get decimal string
        bl      writeStr        @ write it
        bl      newLine
        add     r5, r5, 1       @ index++;
        b       printLoop
allDone:
        mov     r0, 0           @ return 0;
        add     sp, sp, locals  @ deallocate local var
        ldmfd   sp!, {r4, r5, fp, lr}   @ restore caller's info
        bx      lr              @ return
Listing15.1.3Filling an array and printing it. (prog asm)

In my algorithm I use r4 as the base register to hold the address of the beginning of the array and r5 to maintain the array element number (index):

add     r4, fp, intArray  @ address of array beginning
mov     r5, 0           @ index = 0;

It is then a simple matter to access any element of the array by computing the byte offset from the beginning of the array, storing this value a register, and using the register addressing mode (Section 11.1):

lsl     r0, r5, 2       @ no, offset is 4 * index
str     r5, [r4, r0]    @ at index-th element

Subsection15.1.1Exercises

1

Write a program in assembly language that prompts the user to enter ten signed integers and then displays them in reverse order.

Hint Solution