ASSEMBLY LANGUAGE PROGRAMMING PART SIX - MEMORY ACCESS II Last time, I presented a method of calling subroutines using interrupts. I also included a rather large listing which includes the routines we have developed up to now with the exception of the memory size tester from the first article. I have since discovered an error in that listing. Line 3500 contains the text LDY 20,U where it should contain the text LDY 20,S. I also provided no explanation of how the code works. Well, the routines were included in order to provide a decent example. You may have noted several places which seem to be wasteful, as well, most notably the branch table for the interrupt routine. That was done intentionally in order to maintain enough space in the code to add more routines in the future and to demonstrate that there are a rather large number of possibilities for this method and that there are numerous correct ways to do a piece of code, although some ways are better than others. I propose that now that we have a relatively hassle-free method of calling subroutines, we should build up a useful collection of these routines. Let's begin with the memory access routines. In my mind, the following routines would be useful: 1. Clear a block of memory specified by constant addresses 2. Clear a block of memory specified by dynamic addresses 3. Set a block of memory specified by constant addresses to a constant value 4. Set a block of memory specified by dynamic addresses to a constant value 5. Set a block of memory specified by dynamic addresses to a dynamic value 6. Set a block of memory specified by constant addresses to a dynamic value 7. Store a value in a specified memory location 8. Read a value from a specified memory location 9. Address conversion routines Clearly, there are more than just those possibilities. The method for specifying constant values should be obvious. We just store them in the program code following the SWI instructions. The dynamic values provide a more difficult problem. We need somewhere to store them that is not too much bother for the programmer to use them and that is not too complicated for use to use them in our routines. I recommend that whenever possible, the dynamic parameters should be stored in registers since registers are the easiest locations to access. Now, we need to come up with some codes for the routines. For simplicity, let's number them as follows: 00 Convert address in A,X to block/offset in B,Y 01 Convert block/offset in B,Y to address in A,X 02 Clear memory, constant boundaries (addresses) 03 Clear memory, A,X to B,Y (addresses) 04 Clear memory, constant boundaries (block/offset) 05 Clear memory, A,X to B,Y (block/offset) 06 Set memory, constant boundaries (addresses), constant value 07 Set memory, constant boundaries (addresses), value in accumulator B 08 Set memory, UH,X to UL,Y (addresses), constant value 09 Set memory, UH,X to UL,Y (addresses), value in B 0A Read memory to A, constant address 0B Read memory to A, address in B,Y 0C Read memory to A, constant block/offset 0D Read memory to A, block/offset in B,Y 0E Write A to memory, constant address 0F Write A to memory, address in B,Y 10 Write A to memory, constant block/offset 11 Write A to memory, block/offset in B,Y 12 Convert pair of addresses (A,X & B,Y) to block/offsets and leave results in (A,X & B,Y) 13 Convert pair of block/offsets (A,X & B,Y) to addresses and leave results in (A,X & B,Y) 14 Set memory, constant boundaries (block/offsets), constant value 15 Set memory, constant boundaries (block/offsets), value in B 16 Set memory, UH,X to UL,Y (block/offsets), constant value 17 Set memory, UH,X to UL,Y (block/offsets), value in B That looks like a lot of coding. Actually, it's nowhere near as bad as it looks, however. As you may have noticed, there appears to be a lot of repetition. That makes it possible to reuse most of the code. The code presented this time includes the code for routines 00 to 09. You will find the code in the file PART6A.ASM and PART6B.ASM. When using Disk EDTASM+, I overran the buffer creating the code, so I had to split it. It can be assembled using the following assembly code: 00100 INCLUDE PART6A.ASM 00110 INCLUDE PART6B.ASM Then use whatever assembly instruction you normally would, but make sure the disk with PART6A.ASM and PART6B.ASM is in the drive when you do. (I used A/IM/AO and it worked for me.) Note that the code does not include even rough skeletons of values from $14 to $17. Next time, we will look at creating macros to make calling the procedure easier. Until next time, keep programming.