ASSEMBLY LANGUAGE PROGRAMMING PART 4 - MEMORY ACCESS I We are now going to develop a series of subroutines which are useful for accessing the "extended" memory of the CoCo3. Obviously, refering to memory in the form "Block, Offset" is not always practical. Well, it is, in fact, quite easy to convert between Bloock, Offset and a Physical address. Unfortunately, we cannot use the Physical address to actually access the memory. That provides us with an obvious starting point for our collection (or library) of routines. We need to write conversion routines. One to go from a physical memory address to a block/offset structure and one to go the other way. Our lives are made somewhat easy by the fact that the block number is bits 18 through 13 of the physical address and the offset is bits 12 through 0. A little though presents the following algorithm for converting from physical to block: 1. grab the lower 13 bits and store that as the offset 2. grab bits 18 through 13 as the block A little more though presents the following algorithm for converting the other way: 1. get the block and shift it left five bits (it becomes a two byte number) 2. add in the first byte of the offset 3. store the result appropriately The code for these routines can be seen in the file PART4.ASM. Now that we have the requisite conversion routines, we need to figure out what else we may need. After some thought, I came up with the following list: - read/write one byte (peek/poke) - read/write a block - set a block to a specified value or clear it A few other useful subroutines might include: - bit set/reset/test - blocks of bits read/write - set/clear a block of bits - test for the size of memory If you have been following the series, you will realize that we already have routines for detecting the size of memory and for clearing/setting a block of memory. As for the rest of the list, I am going to concentrate on the byte level routines initially. It should be obvious that all we need for the set/reset byte commands is a "pointer" to the byte we want to change. We could use either method. I think we should provide an interface for both beacuse it could prove useful to have that flexibility later. Similarly for the block level commands, I think both methods should be allowed. We will follow the stack convention for passing parameters to most of the routines by virtue of the fact that we need to pass a fairly large amount of data. The two exceptions to this rule are the address conversion routines and the memory clearing routine we have already written. There will need to be some modifications to the method our existing memory block set/clear routines accept data and there will probably need to be several new subroutines to handle the different methods of specifying addresses. The code in PART4.ASM contains the complete package including the conversion routines (as noted above) and the memory set/clear routines. The code is has detailed comments in it so it should be relatively easy to decipher. Next time, a new method of calling subroutines will be introduced in some detail and the routines developed this time will be adapted to work under that paradigm. You will probably find this new method quite agreeable from a usage perspective though it does get a little complicated from the perspective of implementing it. Until next time, keep programming.