STACKING THINGS UP As promised last month, the BASIC loader I used for CLRSCN is included this month. Your version (if you did one) may appear substantially different to mine, but if it works, it probably uses the same principles. Here is my program: 10 CLEAR200,&H7EFF 20 FORX=&H7F00 TO&H7F0A 30 READA$:POKEX,VAL("&H"+A$) 40 NEXT 50 DATA9E,FC,96,FB,A7 60 DATA80,9C,FE,23,FA,39 NOTE: the space between &H7F00 and TO is absoulutely neccessary. THE STACK Many instructions use the stack to store temporary information or expect to find information there. A jump or branch to subroutine stores the current program counter value on the stack and RTS takes this value and puts it back into the program counter. The stack builds down from high RAM. All 16-bit values are stored as though with a ST instruction. The S register points to the current memory location of the stack (the first byte of the most recently stored data). You can access the stack through indexed operations too, but this will not be discussed here. There are two instructions which are used to store and retreive information to or from the stack: PSHS and PULS. There is also another stack, the user stack (S points to the hardware stack), or U register. It is generally used as an index register but it has similar instructions: PSHU, and PULU. There are, however, no other instruction which affect the user stack. The operant byte for PSH/PUL instructions is interpreted as a series of 8 flags; one for each register being pushed or pulled. * bit# 7 6 5 4 3 2 1 0 PC U/S* Y X DP B A CC * Bits are usually numbered from least significance to greatest significance and written the other way. A math textbook may be of help if you do not understand how binary works. Suffice to say, take the bit number appropriate to the register and raise 2 to that power. Add on other registers required in the same manner. This will create the byte you must place in your instruction. ** You can push any of the CPU registers to the stack except the register which points to the stack you are using. Therefore, U will be pushed to S and S would be pushed to U. Usually, PSHS is used at the beginning of a section of code which wants to preserve the contents of one or more registers. These registers are pushed onto the stack and then retreived at the end of the section of code with a PULS. You may, if you are retrieving the registers at the end of a subroutine, use PC as part of the list and then omit the RTS insrtuction--this save a byte and some processing time. Let us put this protection into CLPSCN in case you wish to call it from another machine code program: 7F00 00010 ORG $7F00 7F00 34 12 00020 CLPSCN PSHS X,A 7F02 9E FC 00030 LDX <$FC 7F04 96 FB 00040 LDA <$FB 7F06 A7 80 00050 LOOP STA ,X+ 7F08 9C FE 00060 CMPX <$FE 7F0A 23 FA 00070 BLS LOOP 7F0C 35 92 00080 PULS PC,X,A I will express my complete trust in you not to fry your CoCo by allowing you to write your own driver for this program. INDIRECT ADDRESSING The remainder of this article will be rather dry but contains some useful information. I am going to discuss one form of INDIRECT addressing--extended indirect. This is used to call a routine whose address varies but is always stored in the same location. This is the method your BASIC manual suggests for calling DSKCON (the disk control routine), POLCAT (keyboard scan), CHROUT (character out), etc. I suggest you always use this mode to call DSKCON since there is a difference between DECB2.0 and DECB2.1. The code for this mode is the indexed operation code for your instructon followed by any of $9F, $BF, $DF, or $FF, followed by the address which contains the location of your routine. An example of such an instruction might be: 6E 9F A002 JMP [$A002] (calls CHROUT and ends your subroutine) AD 9F A000 JSR [$A000] (calls POLCAT) A7 9F 1234 LDA [$1234] (gets value at $1234 and $1235 as the address and loads A with the value at this address) CONSTANT OFFSETS Constant offsets are offsets from an index register or the stack pointer which are hard coded into the program. You can use no offset, a 5-bit offset, an 8-bit offset, or a 16-bit offset from any of X,Y,U, or S. The binary codes for these modes are included in the first article of the series. No offset is simply marked as ,R in the assembly code where R is the register being used for indexing. 5-bit offsets: these are used for accessing information within 16<=offset<=+15. This and No Offset use only one byte for an operand. 8-bit offsets: these are the same as 5-bit relative addressing except it is relative to R. The offset range is -128<=offset<=+127. This consists of the byte from part one plus the byte containing the offset. 16-bit offsets: these are the same as 8 bit relative addressing except you use two bytes for the offset; the range is -32768<=offset<=+32767. No offset, 8-bit offset, and 16-bit offset can be used in an indirect mode by adding [] around the instruction. 8-bit offsets are forced via < and 16-bit via >. The assembly form is offset,R. ACCUMULATOR OFFSETS You can also use the value of an accumulator as a signed offset from the index register. Accumulators A & B work exactly like the operand in a Bxx instruction and accumulator D (A and B together) works the same except it is a 16-bit offset. The form is ACC,R where ACC is the accumulator and R is the index register. The codes are in the first article. You can use any accumulator offset in the indirect mode. AUTO INCREMENTING AND DECREMENTING Auto incrementing and decrementing can be useful for stepping through tables of data or stringing operations together. An increment is performed after the instruction is complete while a decrement is performed before the instruction. You may increment or decrement by 1 or 2 by using the appropriate number of + or - signs. You may only use the 2 byte increments and decrements in the indirect form. Examples of form: ,X++ ; ,-Y. PROGRAM COUNTER RELATIVE This is the last form of indexed addressing. This form is used in position independent code to load an point to a location in the program. There are 8-bit and 16-bit forms of this addressing mode. The 8-bit form works exactly like the Bxx instructions. The 16-bit form can be caluclated by using the same method but expanding the count to two bytes. The form of this instruction is as follows: LABEL,PCR - forced 16-bit offset Just a note in case you were wondering: the LBxx instructions work in the same manner as the 16-bit PCR instructions. The next article will not have any programs in it. I will explain the logic and arithmetic operations, provide a description of binary and hexadecimal number systems (I think this may help those of you unfamiliar with this). It will be faily dry but it will be worth the wait for the final programming project.