Section 9.7
A pointer example

Remember the discussion in Section 8.5 of how LDS and STS worked? Towards the end of that section, we saw how an array of integers can be added up using LDS. The following C program and the subsequent CSC-1 assembler program implement that program directly, using pointers rather than array indexes as in the last section.

main()
{
     int array[5];    /* contains 8, 2, 1, 4, 6 */
     int sum;
     int *pointr;
     int i;
     int max = 5;

     pointr = &array[0];
     sum = 0;
     i = 0;

     while (i < max) {       /* could have used a for loop here */
          sum += *pointr;
          pointr++;
          i++;
     }
}

Some concessions were made to clarity and to enable the C code to be more closely tied to the following CSC-1 assembler version. A while loop was used instead of a for-loop for this reason and some other contractions were omitted as well. For example, the while loop could have been squished down to:

     while (i++ < max)
          sum += *pointer++;

Here is the CSC-1 assembler code for the C version above:

   0:           LDI   2500   ; Put the address of the array into pointer
   1:           STD   POINTR
   2:           LDI   0      ; Put 0 into sum and i
   3:           STD   SUM
   4:           STD   I

   5:  LOOP:    LOD   MAX    ; is i == max?
   6:           SUB   I
   7:           JZ    ENDLOOP; if so, then we are done

   8:           LOD   POINTR ; Get pointer to current array element
   9:           A2S          ; Save in S to be used in indirect load
  10:           LDS          ; Actually fetch the value

  11:           ADD   SUM    ; Add current sum to this
  12:           STD   SUM    ; store back into sum

  13:           LOD   POINTR ; Add 1 to the pointer
  14:           ADD   ONE    ; so that it points to the next element
  15:           STD   POINTR ; for the next round of the loop

  16:           LOD   I      ; Add 1 to the counter
  17:           ADD   ONE    ; so we can know when we've looked at all
  18:           STD   I      ; the elements of the array

  19:           JMP   LOOP   ; Back to the top of the loop
  20:  ENDLOOP: HLT          ; When done, halt the computer

  21:  MAX:     NUM   5      ; maximum size of the array
  22:  I:       NUM   0      ; loop counter
  23:  ONE:     NUM   1      ; Constant 1 used to increment I

       =1000
1000:  POINTR:  NUM   0      ; a pointer to the current element of the array
       =1500
1500:  SUM:     NUM   0      ; will hold sum of all elements of array
       =2500
2500:  ARRAY:   NUM   8      ; The array of integer
2501:           NUM   2
2502:           NUM   1
2503:           NUM   4
2504:           NUM   6

Let's examine the heart of the while loop to see how indirect addressing is used.

POINTR is the pointer variable that is used to point at successive elements of the array. Though it would have been more natural to use something like array[i], the approach of using pointers is quite natural in C. POINTR is put at location 1000 in memory to tie it into the diagrams in Section 8.5. Likewise, the array occupies words 2500 through 2504 and the sum is in location 1500. The equals directive is an assembler command that tells the assembler to write the code so that these values are placed at the desired locations.

POINTR is set to point at the first word of the array by actually loading that address, 2500, and storing it into the pointer. C allows this to be done more easily without knowing exactly what the number is, by using the address-of operator, as in pointr = &array[0]; Recall that an array is addressed by its first element (or the first byte of the first element). There is really no other way to address a large chunk of memory in machine language.

The expression *pointr is what is called a dereferencing of a pointer. What this means is that the pointer is followed to the object that it points to and that object is fetched and used. This happens in instructions 8 through 10, leaving the value in A. Next we add SUM to that value and store it back into SUM. No elements of the array are changed in this program.

Then the pointer's value is increased by 1 so that it will point to the next element of the array. This takes 3 instructions, load, add and store, as does adding 1 to the loop counter.

The approach to arrays taken in this program differs from that in Section 9.6 where an explicit index variable is added to the base address. The base address of the array in the program above is 2500, but instead of adding 1 to it, we actually do pointer arithmetic on the pointer. When pointers are used for linked lists or graphs or other structures than arrays, they must be used as above; the array element notation is not available. But as we saw in Section 9.6, even array[i] gets turned into instructions that use LDS and STS.