MCS6500

Microcomputer Family

Programming Manual


CHAPTER 6

INDEX REGISTERS AND INDEX ADDRESSING CONCEPTS

6. GENERAL CONCEPT OF INDEXING

In previous sections techniques for using the program counter to
address memory locations after the operation code to develop the address
for a particular operation have been discussed. Other than cases when
the programmer directly changes the program memory, it can be considered
that the addressing modes discussed up until now are fixed or directed
addresses and each has the relative merits discussed under each individual
section. However , a more powerful concept of addressing is that of
computed addressing. There are basically two types of computed addressing;
indexed addressing and indirect addressing.
Indexed addressing uses an address which is computed by means of
modifying the address data accessed by the program counter with an
internal register called an index register.
Indirect addressing uses a computed and stored address which is
accessed by an indirect pointer in the programming sequence.
In the MCS650X product family, both of these modes are used and
combinations of them are available.
Before undertaking the more difficult concepts of indirect addressing
the concept of indexed instructions will be developed.
In order to move five bytes of memory from an address contained
in FIELD 1 to another set of addresses, starting with FIELD 2, the
following program could be written:

Example 6.1:  Moving Five Bytes of Data With Straight Line Code

LABEL  INSTRUCTION      OPERAND                    COMMENTS

START      LDA          FIELD 1      ───────\   Move First Value
           STA          FIELD 2      ───────/
           LDA          FIELD 1 + 1  ───────\   Move Second Value
           STA          FIELD 2 + 1  ───────/
           LDA          FIELD 1 + 2  ───────\   Move Third Value
           STA          FIELD 2 + 2  ───────/
           LDA          FIELD 1 + 3  ───────\   Move Fourth Value
           STA          FIELD 2 + 3  ───────/
           LDA          FIELD 1 + 4  ───────\   Move Fifth Value
           STA          FIELD 2 + 4  ───────/

In this example, data is fetched from the first memory location in
FIELD 1, as addressed by the next one or two bytes in program memory.
stored temporarily in A and then written into the first memory location
in FIELD 2, also addressed by the next one or two bytes in program memory.
This sequence is repeated, with only the memory addresses changing, until
all the data has been transferred. This type of programming is called
straight line programming because each repetitive operation is a separate
group of instructions listed in sequence or straight line form in
program memory. This is necessary even though the instruction OP CODES
are identical for each memory transfer operation because the specific
memory addresses are different and require a different code to be written
into the program memory for each transfer.
It takes a total of 10 instructions to accomplish the move when it
is implemented this way. It should be noted that it is not indicated
whether or not FIELD 1 and FIELD 2 are Zero Page addresses or Absolute
addresses.
If they were Zero Page addresses, the total number of bytes consumed
in solving the problem would be two bytes for each instruction
and thereby requiring 20 bytes of memory; it both FIELD 1 and FIELD 2
were Absolute memory locations, each instruction would take 3 bytes
and this program would require 30 bytes of program storage.

The Zero Page program would execute in three cycles per instruction
or 30 cycles and the Absolute location version would execute
in four cycles per instruction or 40 cycles.

A new concept has been introduced in this example, that of symbolic
notation rather than actual locations for the instructions.

The form that this short program is written in uses symbolic
addressing in which the address of the beginning of the program has
a name START. Symbolic representations of addresses such as "START"
are referred to as labels. The addresses in the two address field
used in this example have also been given names, the first address of the
first field is called FIELD 1; the first address of the second field is
called FIELD 2. Each additional address in the fields has been given
a number which is referenced to the first number; for example, the
third byte in FIELD 1 is FIELD 1+2. All of these concepts are implemented
to simplify the ease of writing a program because the user does
not have to worry about the locations of FIELD 1 and FIELD 2 until after
analyzing the memory needs of the whole program. Symbolic notation also
results in a more readable program.

Translation from symbolic form instructions and addresses into
actual numerical OP CODES and addresses is done by a program called a
symbolic assembler. Several different versions of symbolic assemblers
and cross assemblers are available for the MCS650X product family.
Symbolic notation will be used throughout the remainder of this text
because of its ease of understanding and because individual byte
addresses are unnecessary although for an explanation of a particular
mode, the byte representation may be used.

In this example, only direct addresses were used. A program to
reduce the number of bytes required to move the five values follows:

Flow Chart — Moving Five Bytes of Data with Loop
Example 6.2 is a program listing that corresponds to the flow chart: Example 6.2: Moving Five Bytes of Data With Loop LABEL INSTRUCTION OPERAND COMMENTS INITIALIZE CLC START LDA FIELD 1 ─────────┐ OTHER STA FIELD 2 ─────────┘ Move Loop LDA START + 1 ───────┐ ADC #1 │ STA START + 1 │ LDA OTHER + 1 │ Modify Move Values ADC #1 │ STA OTHER + 1 ───────┘ CMP #FIELD 2 + 5 ──── Check for End BNE START NOTE: For ease of reading, labels have been written in the form "FIELD 1", This is incorrect format for use in the various symbolic assemblers. "FIELD 1" must be written "FIELDl" when coding for assembler formats. Assuming Zero Page, direct addressing, Example 6.3 is written below with one byte per line just as it would appear in program memory. This will provide a more detailed description of Example 6.2. Example 6.3: Coded Detail of Moving Fields With Loop LABEL CODE NAMES COMMENTS CLC Clear Carry START LDA (FIELD 1) → A FIELD 1 OTHER STA A → (FIELD 2) FIELD 2 LDA From Address → A START + 1 ADC A + 1 → A 1 STA A → From Address START + 1 LDA To Address → A OTHER + 1 ADC A + 1 → A 1 STA A + To Address OTHER + 1 CMP A - ORIGINAL FIELD 2 + 5 ORIGINAL FIELD 2 + 5 BNE If not, loop to START START In this example, the program is modifying the addresses of one load instruction and one store instruction rather than writing ten instructions to move five bytes of data and fifty instructions to move twenty-five bytes of data. The address of the Load A instruction is located in memory at START + 1 and the Store instruction at OTHER + 1. In order to perform this operation, the address must be modified once for each move operation until all of the data is moved. Checking for the end of the moves is accomplished by checking the results of the address modification to determine if the address exceeds the end of the second field. When it does, the routine is complete. If a hundred values were to be moved this program would remain 20 bytes long, whereas the solution to the first problem would require a program of 200 instructions. The type of coding used in this example is called a "loop". Although the program loop in this case requires as many bytes as the original program, more values could be moved without increasing the length of the program. The greater the number of repetitive operations that are to be accomplished, the greater the advantage of the loop type program over straight line programming. Important Note: The execution time required to move the five values is significantly longer using the loop program than the straight line program. In the straight line program, if a Zero Page operation is assumed, the time to perform the total move is 30 cycles. Using the loop program, the execution time to move five values is five times through the entire loop, which takes 25 cycles. Therefore the time to move five values is 125 cycles. While loops have an advantage in coding space efficiency, all loops cost time. If the programmer has a problem that is extremely time dependent, taking the loop out and going to straight line programming, even though it is extremely inefficient in terms of its utilization of memory, will often solve the timing problem. The straight line programming technique becomes very useful in some control applications. However, it is not recommended as a standard technique but should only be used when there are extreme timing problems, Using loops will normally save a significant number of bytes but they will always take more time. The technique used in the loop program example has two major problems: 1. The necessity to modify program memory. This should be avoided to take advantage of the ability to put programs into read only memory with the corresponding savings in hardware costs. 2. Although this is the simplist form of computed addressing, less program bytes would be necessary than the more sophisticated form of program shown in the following flow chart:
Moving Five Bytes of Data with Counter
In the MCS650X microprocessor family, the counter is called an index register. It is an 8-bit register which is loaded from memory and has the ability to have one added to it by an increment instruction (INX,INY) and can be compared directly to memory using the compare index instruction (CPX,CPY). Example 6.4 shows the program listing for the flow chart of Figure 6.2. Example 6.4: Moving Five Bytes of Data With Index Registers BYTES LABEL INSTRUCTION OPERAND COMMENTS 2 LDX 0 Load Index With Zero 3 LOOP LDA FIELD 1,X 3 STA FIELD 2,X 1 INX Increment Count 2 CPX 5 Compare For End 2 BNE LOOP 13 for Absolute In this example, index register X is used as an index and as a counter. It is initialized to zero. Data is fetched from memory at the address "FIELD 1 plus the value of register X", and placed in A. The data is then written from A to memory at the address "FIELD 2 plus the value of register X". Register X is incremented by one and compared with 5 in order to determine if all five data values have been transferred. If not the program loops back to LOOP. In this example. "FIELD 1" is called the "Base Address" which is the address to which indexing is referenced. This only takes 11 or 13 bytes, depending on whether or not the field is in Page Zero or in absolute memory. It still takes 13 or 15 cycles per byte moved, again confirming that loops are excellent for coding space but not for execution time. It can be seen from the example that there are basically two criterias for an index register; one, that it be a register which is easily incremented, compared, loaded, and stored, and two, that in a single instruction one can specify both the Base Address and the value of X. In the MCS650X microprocessor, the way that the indexed instruction is symbolically represented is OP CODE, Address, X. This indicates to the symbolic assembler that an instruction OP CODE should be picked, which should specify either the absolute address modified by the content of index X register. In performing these operations, the microprocessor fetches the instruction OP CODE as previously defined, and fetches the address, modifies the address from the memory by adding the index register to it prior to loading or storing the value of memory. The index register is a counter. As discussed previously, one of the advantages of the flags in the microprocessor is that a value can be modified and its results tested. Assume the last example is modified so that instead of moving the first value in FIELD 1 to the first value in FIELD 2, the last value in FIELD 1 is moved first to the last value in FIELD 2, then the next to the last value, etc. and finally the first value. With the index register preloaded with 5 and using a decrement instruction the contents of the index register would end at zero after the 5 fields of data were transferred. The zero indicates that the number of times through the loop is correct and the loop exited by use of the zero test. The program listing for this modification is shown in Example 6.5: Example 6.5: Moving Five Bytes of Data By Decrementing the Index Register LABEL INSTRUCTION OPERAND LDX 5 LOOP LDA FIELD 1-1,X STA FIELD 2-1,X DEX BNE LOOP In this example, Index Register X is again used as an Address Counter but it will count backwards. It is initialized to five for this example. Data is fetched from memory at the address "FIELD 1 plus the value of Register X" and placed in A. The data is then written from A to memory at the address "FIELD 2 plus the value of Register X." Register X is decremented by one. If the decremented value is not zero, as determined by a Branch on Zero instruction, the program loops back to LOOP. The loop has been decreased to 9 or 11 bytes and the execution time per byte has been decreased from 15 cycles to 13 cycles per value which shows the advantage of using the flag setting of the decrement index instruction. The two index registers, X and Y, can now be added to the system block diagram as in Figure 6.3
Partial Block Diagram of MCS650X Including Index Registers
Each of the index registers is 8 bits long and is loaded and stored from memory, using techniques similar to the accumulator. Because of this ability, they can be considered as auxiliary channels to flow data through the microprocessor. However, their primary use is in being added to addresses fetched from memory to form a modified effective address, as described previously. Both index registers have the ability to be compared to memory (CPX,CPY) and to be incremented (INX,INY) and decremented (DEX,DEY). Because of OP CODE limitations, X and Y have slightly different uses. X is a little more flexible because it has Zero Page operations which Y does not have with exception of LDX and STX. Aside from which modes they modify j the registers are autonomous j independent and of equal value. 6.1 ABSOLUTE INDEXED Absolute indexed address is absolute addressing with an index register added to the absolute address. The sequences that occur for indexed absolute addressing without page crossing are as follows: Example 6.6: Absolute Indexed; With No Page Crossing Address Data External Internal Cycle Bus Bus Operation Operation 1 0100 OP CODE Fetch OP CODE Increment PC to 101, Finish Previous Instruction 2 0101 BAL Fetch BAL Increment PC to 102, Interpret In- struction 3 0102 BAH Fetch BAH Increment PC to 103, Calculate BAL + X 4 BAH,BAL+X OPERAND Put Out Effective Address 5 103 Next OP Fetch Next Finish Operations CODE OP CODE BAL and BAH refer to the low and high order bytes of the base address, respectively. While the index X was used in Example 6.7, the index Y is equally applicable. If a page is not crossed, the results of the address low + X does not cause a carry. The processor is able to pipeline the addition of the 8-bit index register to the lower byte of the base address (BAL) and not suffer any time degradation for absolute indexed addressing over straight absolute addressing. In other words, while BAH is being fetched, the add of X to BAL occurs. Both addressing modes require four cycles with the only difference being that X or Y must be set at a known value and the OP CODE must indicate an index X or Y. The second possibility is that when the index register is added to the address low of the base address that the resultant address is in the next page. This is illustrated in Example 6.7. Example 6.7: Absolute Indexed; With Page Crossing Address Data External Internal Cycle Bus Bus Operation Operation 1 0100 OP CODE Fetch OP CODE Finish Previous Operation Increment PC to 101 2 0101 BAL Fetch BAL Interpret Instruction Increment PC to 102 3 0102 BAH Fetch BAH Add BAL + Index Increment PC to 103 4 BAH,BAL Data Fetch Data Add BAH + Carry +X (Ignore) (Data is ignored) 5 BAH+1, Data Fetch Data BAL+X 6 103 Next OP Fetch Next Finish Operation CODE OP CODE The most substantial difference between the page crossing operation and no page crossing is that during the fourth cycle, the address high and the calculated address low is put out, thereby incorrectly addressing the same page as the base address. This operation is carried on in parallel with the adding of the carry to the address high. During the fourth cycle the address high plus the carry from the adder is put on the address bus, moving the operation to the next page. Thus there are two effects from the page crossing. 1. The addressing of a false address. This is similar to what happens in a branch relative during a page crossing. 2. The operation takes one additional cycle while the new address high is calculated. As with the branch relative this page crossing occurs independently of programmer action and there is no penalty in memory for having crossed the page boundary. It is possible for the programmer to predict a page crossing by knowing the value of the base address and the maximum offset value in the index register. If timing is of concern, the base address can be adjusted so that the address field is always in one page. As with absolute addressing, absolute indexed is the most general form of indexing. It is possible to do absolute indexed modified by X, and absolute indexed modified by Y. Instructions which allow absolute indexed by X are ADC, AND, ASL, CMP, DEC, EOR, INC. LDA, LDY, LSR, ORA, ROL, SBC, and STA. The instructions which allow indexed absolute by Y are ADC, AND, CMP, EOR, LDA, LDX, ORA, SBC, and STA. 6.2 ZERO PAGE INDEXED As with non-computed addressing, there is a memory use advantage to the short-cut of Zero Page addressing. Except in LDX and STX instructions which can be modified by Y, Zero Page is only available modified by X. If the base address plus X exceeds the value that can be stored in a single byte, no carry is generated, therefore there is no page crossing phenomena. A wrap-around will occur within Page Zero. The following example illustrates the internal operations of Zero Page indexing. Example 6.8: Illustration of Zero Page Indexing Address Data External Internal Cycle Bus Bus Operation Operation 1 0100 OP CODE Fetch OP CODE Finish Previous Operation, 0101 → PC 2 0101 BAL Fetch Base Interpret Instruct- Address Low ion, 0102 → PC (BAL) 3 00,BAL Data Fetch Add: BAL + X (Dis- Discarded carded Data 4 00,BAL Data Fetch Data +X 5 0102 Next OP Fetch Next OP Finish Operation CODE CODE As can be seen from the example, there is no time savings of Zero Page indexing over absolute indexing without page crossing. In the case of the indexed absolute during cycle 3 the address high is being fetched at the same time as the addition of the index to address low. In the case of the Zero Page, there is no opportunity for this type of overlap; therefore, indexed Zero Page instructions take one cycle longer than non-indexed instructions. In both Zero Page indexed and absolute indexed with a page crossing, there are incorrect addresses calculated. Provisions have been made to make certain that only a READ operation occurs during this time. Memory modifying operations such as STORE, SHIFT, ROTATE, etc. have all been delayed until the correct address is available, thereby prohibiting any possibility of writing data in an incorrect location and destroying the previous data in that location. As has been previously stated, there is no carry out of the Zero Page operation. 00 is forced into address high under all circumstances in cycle 4. For example, if the index register containing a value of 10 is to be added to base address containing a value of F7, the following operation would occur: Example 6.9: Demonstrating the Wrap-Around Cycle Address Bus Internal Operation 3 00F7 F7 + 10 4 0007 This indicated the wrap-around effect that occurs with Zero Page indexing with page crossing. This wrap-around does not increase the cycle time over that shown in the previous example. Only index X is allowed as a modifier in Zero Page. Instructions which have this feature include ADC, AND, ASL, CMP, DEC, EOR, INC, LDA, LDY, LSR, OKA, ROL, SBC, STA and STY. Note that index Y is allowed in the instructions LDX and STX. 6.3 INDIRECT ADDRESSING In solving a certain class of problems, it is sometimes necessary to have an address which is a truly computed value, not just a base address with some type of offset, but a value which is calculated or sometimes obtained as a group of addresses. In order to implement this type of indexing or addressing, the use of indirect addressing has been introduced. In the MCS650X family indirect operations have a special form. The basic form of the indirect addressing is that of an instruction consisting of an OP CODE followed by a Zero Page address. The microprocessor obtains the effective address by picking up from the Zero Page address the effective address of the operation. The indirect addressing operation is much the same as absolute addressing except indirect addressing uses a Zero Page addressing operation to indirectly access the effective address. In "the case of absolute addressing the value in the program counter is used as the address to pick up the effective address low, one is added to the program counter which is used to pick up the effective address high. In the case of indirect addressing, the next value after the OP CODE, as addressed with the program counter, is used as a pointer to address the effective address low in the zero page. The pointer is then incremented by one with the effective address high fetched from the next memory location. The next cycle places the effective address high (ADH) and effective address low (ADL) on the address bus to fetch the data. An illustration of this is shown in Figure 6.4.
Indirect Addressing-Pictorial Drawing
The address following the instruction is really the address of an address, or "indirect" address. The indirect address is represented by IAL in the figure. A more detailed definition of indirect addressing is included in the appendix. Although the MCS650X microprocessor family has indirect operations, it has no simple indirect addressing such as described above. There are two modes of indirect addressing in the MCS650X microprocessor family? 1.) indexed indirect and 2.) indirect indexed. 6.4 INDEXED INDIRECT ADDRESSING The major use of indexed indirect is in picking up data from a table or list of addresses to perform an operation. Examples where indexed indirect is applicable is in polling I/O devices or performing string or multiple string operations. Indexed indirect addressing uses the index register X. Instead of performing the indirect as shown in the Figure 6.4, the index register X is added to the Zero Page address, thereby allowing varying address for the indirect pointer. The operation and timing of the indexed indirect addressing is shown in Figure 6.5.
Indexed Indirect Addressing
Example 6.10: Illustration of Indexed Indirect Addressing Address Data External Internal Cycle Bus Bus Operation Operation 1 0100 OP CODE Fetch OP CODE Finish Previous Operation, 0101 → PC 2 0101 BAL Fetch BAL Interpret In- struction, 0102 → PC 3 00,BAL DATA (Dis- Fetch Discard- Add BAL + X carded) ed Data 4 00,BAL ADL Fetch ADL Add 1 to BAL + X + X 5 00,BAL ADH Fetch ADH Hold ADL + X + 1 6 ADH,ADL DATA Fetch DATA 7 0102 Next OP Fetch Next OP Finish Operation CODE 0103 → PC One of the advantages of this type of indexing is that a 16-bit address can be fetched with only two bytes of memory, the byte that contains the OP CODE and the byte that contains the indirect pointer. It does require, however, that there be a table of addresses kept in a read/write memory which is more expensive than having it in read only memory. Therefore, this approach is normally reserved for applications where use of indexed indirect results in significant coding or throughput improvement or where the address being fetched is a variable computed address. It is also obvious from the example that the user pays a minor time penalty for this form of addressing in that indexed indirect always takes six cycles to fetch a single operand which is 25% more than an absolute address and 50% more than a Zero Page reference to an operand. As in the Zero Page indexed, the operation in cycles three and four are located in Zero Page and there is no ability to carry over into the next page. It is possible to develop a value of the index plus the base address where the result exceeded 255, in this case the address put out is a wrap-around to the low part of the Page Zero. Instructions which allow the use of indexed indirect are ADC, AND, CMP, EOR, LDA, ORA, SBC, STA. 6.5 INDIRECT INDEXED ADDRESSING The indirect indexed instruction combines a feature of indirect addressing and a capability of indexing. The usefulness of this instruction is primarily for those operations in which one of several values could be used as part of a subroutine. By having an indirect pointer to the base operation and by using the index register Y in the normal counter type form, one can have the advantages of an address that points anywhere in memory, combined with the advantages of the counter offset capability of the index register. Figure 6.6 illustrates the indirect indexed concept in flow form while Example 6.11 indicates the internal operation of a non-page rollover of an indirect index.
Indirect Indexed Addressing
Example 6.11: Indirect Indexed Addressing (No Page Crossing) Address Data External Internal Cycle Bus Bus Operation Operation 1 0100 OP CODE Fetch OP CODE Finish Previous Operation, 0101 → PC 2 0101 IAL Fetch IAL Interpret In- struction, 0102 → PC 3 00,IAL BAL Fetch BAL Add 1 to IAL 4 00,IAL BAH Fetch BAH Add BAL + Y + 1 5 BAH,BAL DATA Fetch Operand + Y 6 0102 Next OP Fetch Next OP Finish Operation CODE CODE 0103 → PC The indirect index still requires two bytes of program storage, one for the OP CODE, one for the indirect pointer. Once beyond the indirect, the indexing of the indirect memory location is just the same as though it was an absolute indexed operation in the sense that if there is no page crossing, pipelining occurs in the adding of the index register Y to address low while fetching address high, and therefore, the non-page crossing solution is one cycle shorter than the indexed indirect. In Example 6.12 it is seen that the page crossing problem that occurs with absolute indexed page crossing also occurs with indirect indexed addressing. Example 6.12: Indirect Indexed Addressing (With Page Crossing) Address Data External Internal Cycle Bus Bus Operation Operation 1 0100 OP CODE Load OP CODE Finish Previous Operation, 0101 → PC 2 0101 IAL Fetch IAL Interpret In- struction, 0102 → PC 3 00,IAL BAL Fetch BAL Add 1 to IAL 4 00,IAL BAH Fetch BAH Add BAL to Y + 1 5 BAH,BAL DATA (Dis- Fetch Data Add 1 to BAH + Y carded) (Discarded) 6 BAH + 1 DATA Fetch Data BAL + Y 7 0102 Next OP Fetch Next OP Finish This CODE CODE Operation, 0103 → PC When there is a page crossing, the base address high and base address low plus Y are pointing to an incorrect location within a referenced page. However, it should be noted that the programmer has control of this incorrect reference in the sense that it is always pointing to the page of the base address. In one more cycle the correct address is referenced. As was true in the case of absolute indexed, the data at the incorrect address is only read. STA and the various read, modify, write memory commands all operate assuming that there will be a page crossing, take the extra cycle time to perform the add and carry and only perform a write on the sixth cycle rather than taking advantage of the five cycle short-cut which is available to read operations. This added cycle guarantees that a memory location will never be written into with incorrect data. Instructions which allow the use of indexed indirect are ADC, AND, CMP, EOR, LDA, ORA, SBC, STA. In the following two examples can be seen a comparison between the use of absolute modified by Y and indirect indexed addressing. In these examples the same function is performed. Values from two memory locations are added and the result stored in a third memory location, assuming that there are several values to be added. The first example deals with known field locations. The second example, such as might be traditionally used in subroutines, deals with field locations that vary between routines. A two byte pointer for each routine using the subroutine is stored in Page Zero. The number of values to be added for each routine is also stored. Example 6.13: Absolute Indexed Add - Sample Program #Bytes Cycles Label Instruction Comments 2 2 START LDY #COUNT -1 Set Y = End of FIELD 3 4 LOOP LDA FIELD 1,Y Load Location 1 3 4 ADC FIELD 2,Y Add Location 2 3 4 STA FIELD 3,Y Store in Location 3 1 2 DEY 2 3 BPL LOOP Check for Less Than Zero __ __ _____________________________________________ 14 19 Time for 10 Bytes = 171 Cycles Example 6.14: Indirect Indexed Add - Sample Program #Bytes Cycles Label Instruction Comments 2 2 START LDY #COUNT -1 Set Y = End of FIELD 2 5 LOOP LDA (PNT1),Y Load FIELD 1 Value 2 5 ADC (PNT2),Y Add FIELD 2 Value 2 5 STA (PNT3),Y Store FIELD 3 Value 1 2 DEY 2 3 BPL LOOP __ __ _____________________________________________ 11 22 Time for 10 Bytes = 201 Cycles The "count" term in these examples represents the number of sets of values to be added and stored. Loading the index register with COUNT-1 will allow a fall through the BPL instruction when computation on all set of values has been completed. There is a definite saving in program storage using indirect because it only requires two bytes for each indirect pointer, the OP CODE plus the pointer of the Page Zero location, whereas in the case of the absolute, it takes three bytes, the OP CODE, address low and address high. It is noted that there are six bytes of Page Zero memory used for pointers, two bytes for each pointer. The number of memory locations allocated to the problem are 17 for the indirect and 14 for the problem where the values are known. The execution time is longer in the indirect loop. Even though the increase in time for a single pass through the loop is only three cycles, if many values are to be transferred, it adds up. It is important to note that loops require time for setup but it is only used once. But in the loop itself, additional time is multiplied by the number of times the program goes through the loop; therefore, on problems where execution time is important, the time reduction effort should be placed on the loop. Even though the loop time is longer and the actual memory expended is greater for the indexed indirect add, it has the advantage of not requiring determination of the locations of FIELD 1, FIELD 2, and FIELD 3 at the time the program was written as is necessary with absolute. An attempt to define problems to take advantage of this shorter memory and execution time by defining fields should be investigated first. However, in almost every program, the same operation must be performed several times. In those cases, it is sometimes more useful to define a subroutine and set the values that the subroutine will operate on as fields in memory. Pointers to these fields are placed in the Zero Page of memory and then the indexed indirect operation is used to perform the function. This is the primary use of the indexed indirect operation. 6.6 INDIRECT ABSOLUTE In the case of all of the indirect operations previously described, the indirect reference was always to a Page Zero location from which is picked up the effective address low and effective address high. There is an exception in the MCS650X microprocessor family for the jump instruction in which absolute indirect jumps are allowed. The use of the absolute indirect jump is best explained in the discussion on interrupts where the addressing mode and its capabilities are explained. 6.7 APPLICATION OF INDEXES As has been developed in many of the previous examples, an index register has primary values as a modifier and as a counter. As a modifier to a base address operation, it allows the accessing of contiguous groups of data by simple modification of the index. This is the primary application of indexes and it is for this purpose they were created. By virtue of the fact that all of the MCS650X instructions have the base address in the instruction, or in the case of the indirect, in the pointer, a single index can usually be used to service an entire loop, because each of the many instructions in the loop normally are referring to the same relative value in each of the lists. An example is adding the third byte of a number to its corresponding third byte of another number, then storing the result in the memory location representing the third byte of the result; therefore, the index register only needs to contain three to accomplish all three of these offset functions. Some other microprocessors use internal registers as indirect pointers. The single register requirement is a significant advantage of the type of indexing done in the MCS650X. Even though the MCS650X has two indexes, more often than not, a single index will solve many of the problems because of the fact that the data is normally organized in corresponding fields. The second feature of the MCS650X type of indexing is that, if used properly, the index register also contains the count of the operations to be performed. The examples have tried to show how to take advantage of that feature. There are two approaches to counting; forward counting and reverse counting. In forward counting, the data in memory can be organized such that the index register starts at zero and is added to on each successive operation. The disadvantage of this type of approach is that the compare index instruction, as used in Example 6.13 must be inserted into the loop in order to determine that the correct number of operations is completed. The reverse counting approach has been used in the latter examples. The data must be organized for reverse counting operation. The first value to be operated on is at the end of the FIELD, the next value is one memory location in front of that, etc. The advantage of this type of operation is that it takes advantage of the combined decrement and test capability of the processor. There are two ways to use the test. First there is the case where the actual number of operations to be performed is loaded into the index register such as was done in Example 6.13. In this case, the index contains the correct count but if added to the base directly, would be pointing to one value beyond the FIELD because the base address contains the first byte. Therefore, when using the actual count in the index register, one always references to the base address minus one. This is easily accomplished as shown in the examples. The cross assembler accepts symbolic references in the form of base address minus one, and the microprocessor very carefully performs the operation shown. The advantage of putting the actual count in the register is that the branch if not equal instruction CBNE) can be used because the value of the register goes to zero on the last operation. The second alternative is to load the counter with the count minus one as done in Example 6.14. In this case, the actual value of the base address is used in the offset. However, the branch back to loop now is a branch plus, remembering that the value in the index register will not go to minus (all ones) until we decrement past zero. Values of count minus one through zero will all take the branch. It is only when attempting to reference less than the base address that the loop will be completed. Either approach gives minimum coding and only requires that the user develop a philosophy of always organizing his data with the first value at the end. In many cases, the operations such as MOVE can be performed even if the data is organized the other way. Experienced programmers find that this reverse counting form is actually more convenient to use and always results in minimum loop time and space. Although for most applications, the 8-bit index register allows simple count in offset operations, there are a few operations where the 256 count that is available in the 8-bit register is not enough problem. First, to code the program with two sets of bases, that is duplicating the coding for the loop with two different address highs, each one a page apart. The second, more useful solution, is to go to indirect operations because the indirect pointer can be modified to allow an infinite indexed operation. An example of the move done under 256 and over 256 is shown in the following example: Example: 6.16: Move N Bytes (N<256) ───────────── ─────────────────── Number of Program Instruction OPERAND Cycles Label Mnemonics FIELD Comments 2 LDX #BLOCK Setup 2 Cycles 4 LOOP LDA FROM-1,X 4 STA TO -1,X LOOP Time: 2 DEX 13 cycles 3 BNE LOOP Memory Required: 11 Bytes Example 6.17: Move N Bytes (N>256) Number of Program Instruction operand Cycles Label Mnemonics FIELD Comments 2 MOVE LDA #FROML 3 STA FRPOINT 2 LDA #FROMH Move from address to 3 STA FRPOINT + 1 an indirect pointer 2 LDA #TOL Move A to address 3 STA TOPOINT to an index pointer 2 LDA #TOH 3 STA TOPOINT + 1 2 LDX #BLOCKS Setup # of 256 blocks 2 LDY #0 to move 5 LOOP LDA (FRPOINT),Y Loop time: 16 cycles/ 6 STA (TOPOINT),Y byte. Move 256 bytes 2 DEY 3 BNE LOOP 5 SPECIAL INC FRPOINT + 1 Increase high 5 INC TOPOINT + 1 pointer 2 DEX 2 BMI OUT Check for last move 3 BNE LOOP 2 LDY #COUNT 3 BNE LOOP Setup last move OUT --- --- Memory Required: 40 Bytes