Shouldn't line 103 be LDR number instead of #0?

46 Views Asked by At

screenshot of textbook (The code is an example of adding a list of numbers together and storing the answer using a loop)

100 LDM #0             ; Load 0 into ACC
101 STO total  
102 STO counter  
103 LDR #0             ; Load 0 into IX
104 loop:  
105 LDX number         ; Load the number indexed by IX into ACC
106 ADD total  
107 STO total  
108 INC IX  
109 LDD counter  
110 INC ACC  
111 STO counter  
112 CMP #3  
113 JPN loop  
114 END  
115 number: #5  
116 #7  
117 #3  
118 counter:  
119 total:  

If zero is stored in the index register instead of the address at which "number" is defined, I don't see how the intended number would be loaded into the accumulator.
If line 105, "LDX number" is loading the address into IX, the comment next to it "Load the number indexed by IX into ACC" confuses me. Is it loading the address to IX, and the number at this address into ACC at the same time?

2

There are 2 best solutions below

1
Martin Rosenau On

Is it loading the address to IX, and the number at this address into ACC at the same time?

No:

It adds the address of the element (e.g. variable) specified in the instruction (number) to the value in IX.

The result is an address.

The CPU loads the content of the memory at this address (the sum of the addition) into the register ACC.

In other words:

If the register IX contains the value 5, the instruction loads the 6-th word (on most CPUs: byte) of the variable number into the register ACC.

If you start with IX=0, continue with IX=1 and so on, you first load the first word of number, then the second word and so on ...

Shouldn't line 103 be LDR number instead of #0?

You might do it the following way, too:

...
LDR # number
loop:
LDX 0
...

In this case, IX already contains the "correct" address where to load from so nothing needs to be added in the LDX instruction.

However, the following code would not work:

...
LDR # number
loop:
LDX number
...

This code would load ACC from the address IX+number. If n is the address of the first word of the variable number, the code would load words from 2*n, 2*n+1, 2*n+2 ... instead of n, n+1 and so on ...

1
Erik Eidt On

In C terms, it is doing the following:

int counter = 0;
int total = 0;
int ix = 0;                    // initialize ix as an index, i.e. start at 0
do {
   total = total + number[ix]; // dereference array "number" at index ix
   ix++;
   counter++;
while ( counter < 3 );

Alternately, as @Martin says, we can use a pointer instead:

int counter = 0;
int total = 0;
int *ix = &number;       // initialize ix as pointer, i.e. to hold address of "number"
do {
   total = total + *ix;  // dereference pointer to fetch numbers
   ix++;
   counter++;
while ( counter < 3 );

On some machines, the pointer approach is shorter/faster because *ix, having no 2nd operand, is shorter to encode and easier to execute than number[ix] — this snippet is inside the loop so (presumed to be) executed repeatedly.  The trade off of larger initialization of ix is worthwhile because that is outside the loop and thus only happens once by comparison.


It would not work to mix the two C approaches, in C you'd get type errors from the compiler, which indicate logic errors in the code.  Assembly won't offer such compile-time errors, but would still be error in logic to mix the pointer initialization outside the loop with array indexing inside the loop.