Using The Assembler Language 07

By Roy Warner

Originally published in EUG #10

Post-Index (full name Post-Indexed Indirect) addressing is one form of assembly addressing, Page 207 of the handbook has a paragraph devoted to Post Index. Looking back at Part Five a line was added to PROCconstants to declare address &70 as "temp" and at line 207 there is LDA(temp),Y that is a Post-Index statement. Post-Index may only use a zero page address and the Y register. The Elk needs to locate a two byte address, so that it may load data stored at that address into the accumulator. Targetting or pointing to an exact location in memory is "addressing", "Him over there", "Her as should know better" are also forms of addressing but the electron not being blessed with human powers of deduction needs a specific instruction in a predetermined format.

In our orginal program the label "data" is an address, if the statement LDA data MOD256:STAtemp were to be written, RUN and then CALLed the low byte of data would be stored in &70 which had been declared as "temp", if a further statement LDA data DIV256:STAtemp+1 had also received the same treatment, the high byte of "data" would be stored in &70+1 = &71. The capital Y is of course the Y register.

Imagine that "data" was the label for address &2000 and that the value in the Y register was four, then temp (&70) would hold the value &00 and temp+1 (&71) would hold the value &20 the statement LDA (temp),Y would load the accumulator with the content of address &2000+4 = &2004. If the value in the Y register were to be decimal 12 the content of address &200C would be loaded into the accumulator.

Why not just load the low byte of data into &70 and the high byte into &71 direct and index it to Y? The post index statement would then be LDA (&70),Y. No reason except that zero page locations are in short supply. To designate two of them as temp and use them only as temporary storage areas prevents having to look back over lines of source code to find a free zero page address. Why use this method at all? The answer to that is "Our address is on the stack in two bytes". The orginal "data" is a label and a label may be indexed with either the X or Y register. Using PROCprt a single multi-user print routine, and jumping to it with JSRprt causes "data" to be stored on the stack in two bytes. That is ideal for Post-Index just pull the values and store them in temp and temp+1.

Imagine that a program requires blocks of data to be stored or retrieved. Then a table for storing those addresses is very useful and in some cases absolutely necessary.

To store the address in the table, the low byte would be placed in temp and the high byte in temp+1 and in the same way the high and low bytes of table would need to be stored in two more zero page addresses say loc and loc+1 (location).

Then the statement LDA(temp),Y:STA(loc),Y:INY:LDA(temp),Y:STA(loc),Y would place the address into successive bytes in the table. Consider that situation, by manipulating the value in the Y register ten addresses with a common high byte could be stored in eleven bytes instead of twenty. The high byte would be stored at the base of the table; after retrieving the high byte with Y set to zero Y would then be set to the offset for the particular low byte required (a value between two and eleven) and the low byte retrieved.

Take that further if the blocks of data were stable and did not move about in memory then the high byte need not be stored at all. The zero page temp+1 could be loaded absolute with high byte LDA#&20:STAtemp+1. Not elegant coding but needs must when the devil wills. Thirty kilobyte of user RAM is not a lot.

To sum up the syntax of LDA(temp),Y activates a routine in the 6502 chip that adds the low byte of an address to the high byte then adds the content of the Y register to give a final sixteen bit address.

Reverse colour text window? How did it go? My code is listed below. Load the program and alter it to my listing, PROCconstants has been altered slightly, merely to give us more control of the program. PROCprt has no changes.

PROCdata has altered the labels indicate the action of the code. Line 380 clears the screen with a VDU12. Colours are reversed at Line 390 where EQUD is introduced, four DIMs might have been used EQUB17:EQUB0 would have given a black foreground and EQUB17:EQUB129 white background.

Remember the Acorn routine at &FFEE3 reads and understands the control codes (Appendix F of the handbook).

EQUD is neater and saves some typing but both EQUD and EQUW only accept hexidecimal numbers, worse they insist that the numbers are in reverse order. At first sight line 390 is very confusing but divide it into four bytes, (use a scrap of paper) "&81" "&11" "&00" "&11" now ask your computer PRINT &81 the answer is 129; write it under the &81 and do the same with the others. Answer "129" "17" "0" "17" reading from right to left (Backwards) "17" "0" (black foreground) "17" "129" (white background).

Line 400 is different, the text window needs five bytes, the last byte of the EQUD statement is &1C 16+12=28 (VDU28); the next the left hand edge of the window "0" then the bottom edge "2" (0,1,2). 0 is a number to the computer so "2" gives three lines deep. &27 2x16+7=39 sets the right hand edge. Tucked on the end is an EQUB0 which sets the top edge. 410 clears the screen within the text window. 420 EQUW&081F; &1F equals 31 (VDU31) &08 for column eight and the EQUB1 line number 1. Line 440 returns the colours to standard and 450 window off. 460 tabs the cursor to column zero line 15 and the routine concludes with &FF.

EQUB, EQUW and EQUD are all used for inserting numbers into assembly code; they are basic statements that may only be used in assembly language source code. EQUB inserts a single byte, EQUW a word (two bytes) and EQUD inserts a double word (four bytes).

Next time start%, base% and scrn1 will be used to save the object code plus, if space permits, an OSBYTE call to the operating system.

Roy Warner

You can operate this program from the Utilities Menu or by typing CH."U.ASSEM" at the prompt.

Will Watts, EUG #10