Beyond Page 6
Most beginning assembly language programmers write short routines that will fit easily in short blocks of memory. That's why the engineers who designed your Atari set aside page 6, a block of memory extending from $0600 to $06FF, as an area for user written assembly language programs. As you become more and more skilled at assembly language programming, however, it's more than likely that you'll eventually start writing programs that consume more than 256 bytes of memory available on page 6. Figuring out where to put long assembly language programs in an Atari computer can be a tricky problem.
The main problem is not usually the amount of free memory that's available, but rather where it is situated in your computer's RAM. In most computers, most of the memory available for user written programs is almost all in one place. It usually extends from a low address, just above where the computer's operating system ends, to a high address, just below the place where a block of RAM called screen memory begins.
The memory organization of an Atari computer is not quite that simple. In an Atari computer, the space available for user written programs is scattered all over the memory map, and learning how to discover little corners where you can stash object code without clobbering your Atari's operating system can become quite a challenging, if sometimes frustrating, task. This situation exists because there are several different kinds of Atari computers, and because all of them are very versatile machines. Atari computers have RAM capacities that range from 16K to 64K, and they can be used in many different graphics modes and with one to four disk drives. Yet they are all software compatible and keeping them software compatible has led to some interesting tricks that have been pulled by Atari in memory design.
Unfortunately, the people who design Atari computers haven't yet found a way -- and it's doubtful that anyone could -- to keep all Atari computers compatible and to keep their memory organization simple at the same time. Nevertheless, there are a few safe places to store your assembly language programs in your Atari's memory. To help you find them, here's a simple memory map of your computer's RAM:
The High Rent District
From $0000 to $00FF
Page zero, the block of memory that extends from $0000 to $00FF, is the high rent district in your computer's RAM. Memory space there is so valuable that very little of it is available for short term use by user written programs. If you want to write high performance programs, particularly programs that use indexed addressing, then you'll have to find at least a few free memory locations on page zero. If you look around carefully, you'll find a few free locations there.
Your Atari's operating system consumes most of page zero. There are a couple of small memory blocks that aren't used by the OS, but they aren't always available for user written programs, since they are often dedicated to other uses. When you write a program using an assembler, for example, your assembler always uses some of page zero. If your program is designed to be called from BASIC, then the BASIC interpreter that you'll have to use will use up more of page zero.
The floating point math routines in your Atari's operating system also consume a block of memory on page zero. However, if you write programs that don't use the Atari FP package, then the block of memory reserved for that package will be free. Specifically, these are the memory locations on page zero that you can use, and the conditions under which you can use them:
Memory Map for Page Zero
- $00 - $AF - Reserved for use by operating system.
- $B0 - $CF - Bytes left free by Assembler Editor cartridge.
- $CB - $D1 - Bytes left free by BASIC cartridge.
- $D4 - $FF - Free if you don't use your OS floating point package, the Atari Assembler Editor cartridge, or a BASIC program that uses the Atari OS floating point routines.
Zero Page Locations You Can Use
In the programs presented in this book, all of the page zero locations that have been used have fallen into the block of memory extending from $B0 to $CF. Look at the last chart, and you'll see why. When you write a program using the Atari Assembler Editor cartridge, the $B0 to $CF block is the only part of page zero that's not used either by your computer's operating system or your Assembler Editor cartridge. (The MAC/65 assembler uses less of page zero, but the programs in this book were written to be compatible with both assemblers.) If you're writing a program designed to be called from BASIC, the portion of page zero that you can use is even smaller. Then your free space will extend only from memory address $CB through memory address $D1. That's seven whole bytes of page zero that you can use for your program! There are two easy ways to get around this limitation. Either write programs that use very little of page zero, or write programs that don't have to be called from BASIC!
Memory Addresses $100 - $6FF
Operating System RAM
Memory addresses $100 to $5FF in your computer are reserved for operating system RAM. Here's how this block of memory is divided up:
- $100- $1FF - Your computer's hardware stack. You can use this block of memory, but only for stack manipulation operations. You remember those: PLA, PHA, PLP, PHP, JSR and RTS.
- $200 - $3BF - IOCB's (input/output control blocks) and miscellaneous OS variables. Your computer uses this section of memory mainly for communicating with input and output devices. It's not available for use by user written programs.
- $3C0 - $3E7 - Printer buffer, where data is held while it's on its way to your printer.
- $3E8 - $3FC - Reserved for OS; not available to you.
- $3FD - $47F - Cassette buffer, a holding area for data between your computer and data cassette recorder.
- $480 - $57D - Reserved for use by BASIC cartridge. May be used by assembly language programs not called from BASIC.
- $57E - $5FF - OS floating point package. Used by BASIC. May also be used by user written assembly language programs. Free for other uses in assembly language programs if floating point routines and BASIC cartridge are not used.
- $600 - $6FF - "Page 6". This is usually available for use by user written assembly language programs. There is one important exception, however. When the INPUT statement is used in a BASIC program, and more than 128 characters are input via the keyboard, the characters in excess of 128 are stored on page 6. In this case, object code stored from $600 to $67F might be erased. However, addresses $680 to $6FF are unconditionally available for user written programs.
Memory Addresses $700 - "MEMLO"
DOS Dedicated RAM
Beginning at memory address $700, there's a block of memory that's reserved for use by your computer's disk operating system. The size of this block of memory is affected by a number of factors, including how many disk drives you use, and whether or not you're currently using the disk utility programs listed on your computer's DOS menu. Because the size of this memory block varies so widely from computer to computer, and from application to application, your Atari has been equipped with a special 16-bit variable that can tell you at a glance how large its DOS and DOS related block of memory is. That variable is called MEMLO, and it's stored in memory addresses $2E7 and $2E8 (743 and 744 in decimal notation). The 16-bit value that MEMLO contains is a very important number. It's not only the address where your computer's DOS routines end; it's also the address where the biggest block of user addressable memory in your computer begins. Once you know what the value of MEMLO is, you'll know exactly where to start the object code for your own machine language programs.
From "MEMLO" to "MEMTOP"
The RAM that you can use freely extends from the variable called MEMLO ($2E7 AND $2E8) to another 16-bit variable named, logically enough, MEMTOP. You can see what value MEMTOP contains by peering into the contents of memory addresses $2E5 and $2E6 (741 and 742 in decimal notation). Once you know what the value of MEMTOP is, you'll know the upper limit of the block of memory in which you can store your assembly language programs.
The memory block extending upward from MEMTOP is your computer's screen display area, an area reserved for the data it uses to create its screen display. Programs that create their own custom screen displays can overwrite this block of RAM, but if you use your computer's built in screen displays, you'll have to stay out of this section of memory, because that's where they are located.
$8000 to $9FFF
"Cartridge Slot B"
When the Atari 800 was designed, this block of memory was dedicated to "Cartridge B," the right-hand slot in a pair of cartridge slots. As it turned out, the Cartridge B slot was utilized by only one or two programs written for the Atari. So newer Atari computers, the 1200XL and subsequent models, have been designed with only one cartridge slot. And that means that memory addresses $8000 to $9FFF, originally designed for" Cartridge B," are now available for use in user written programs.
$8000 to $BFFF
Cartridge Slot A
Cartridge Slot A is the slot that holds most Atari cartridges, the Atari Assembler Editor cartridge, and all other kinds of cartridge based programs. Many disk based programs also use this block of memory. When you write programs using cartridges or utility programs that occupy this memory block, there's no easy way for you to use that space for your programs. If you get good at writing relocatable code, however, there's no reason you can't use this memory block; after all, other Atari assembly language programmers do! Usually this slot goes from $A000 to $BFFF, but some can go from $8000 to $BFFF.
$C000 to $CFFF
Not used in Atari 400 and 800 because they do not contain this RAM location. Used by OS in the newer models. Enter at your own risk; not recommended for use in user written programs.
$D000 to $D7FF
Atari hardware Read/Write registers
Not available for user written programs.
$D800 to $DFFF
Floating Point ROM
Available for use by user written programs if the OS floating point package is not used, and if BASIC routines that call FP routines are not used. This is only available in the XL line, the Atari 400 and 800 do not have RAM available here.
$E000 to $FFFF
Operating System ROM
Not available for use by user written programs.
The Problem of Allocating Memory
Once you know your Atari's memory map like the palm of your hand, you'll almost be ready to start allocating memory to assembly language programs. Almost, but not quite. First you'll have to learn how to solve two big problems that can be a real pain in the neck to Atari assembly language programmers. These two problems are:
- Making sure that your source code programs and your object code programs don't overwrite each other.
- Keeping BASIC and machine language programs away from each other in the computer's memory.
Actually, these two problems are not difficult to solve. But they seem to be more complicated than they really are because of a confusing system that has been developed by Atari for keeping track of the lowest address of free memory.
In your computer's operating system, there are two variables, or pointers, that are designed to help you figure out where you can start machine language programs in your computer's memory. One of these variables is called LOMEM, and the other is called MEMLO. If you think that's confusing, that's only the beginning. Sometimes LOMEM and MEMLO are interchangeable, and sometimes they aren't. While their abbreviations are merely confusing, their full names are downright misleading. On pages D-1 and D-2 of your Atari BASIC Reference Manual, MEMLO is identified as your computer's operating system low memory pointer, and LOMEM is identified as your Atari's BASIC low memory pointer. Unless you want to wind up totally baffled, don't pay any attention to either of these names. Here's how your computer's LOMEM and MEMLO pointers really work, and what they can really tell you.
The LOMEM Pointer
Your Atari's LOMEM pointer is a 16-bit variable stored in memory addresses $80 and $81 (or 128 and 129 in decimal notation). LOMEM always contains the beginning address of a block of memory in your computer called the edit text buffer. The edit text buffer is a special buffer designed to hold ATASCII text while that text is being written and edited. When you write or edit a BASIC program, the edit text buffer is where your program is stored until you're ready to run or solve it. The edit text buffer is also used to store assembly language source code programs.
When you turn your computer on, the address in LOMEM is the lowest address of your computer's free RAM, the lowest address (not including page 6) at which user written programs can safely begin. If you don't have any disk drives connected to your computer, then the value of LOMEM will be $0700 when you turn on your computer system. If you do have one disk drive or more hooked-up to your computer, and they're turned on, then the block of RAM that lies just below LOMEM will be the memory block where your computer's disk operating system (DOS) is stored.
Changing the LOMEM Pointer
Even though the value of LOMEM is automatically set to a predetermined value when you turn your computer on, you can change it any time you like. When the value of LOMEM changes, the starting address of your computer's edit text buffer will automatically shift to the address that has been loaded into the LOMEM pointer. What this means, is that you can change the location of your computer's edit text buffer at any time you like by merely poking (or loading) a new 16-bit address into the LOMEM pointer.
Why would you want to change the location of the edit text buffer? The most common purpose for doing it is to keep source code programs and object code programs away from each other while source code is being written, edited and assembled. To understand how LOMEM can be manipulated to keep source code and object code away from each other, it helps to understand how LOMEM and MEMLO are related.
The MEMLO Pointer
MEMLO is also a 16-bit value, but is stored in memory addresses $2E7 and $2E8 of your computer (or 743 and 744 in decimal notation). When you turn your computer on, without a cartridge or a disk in it, your computer's MEMLO pointer always contains the lowest free address in RAM, the lowest address at which user written programs can begin. That means, that when you turn your computer on, MEMLO and LOMEM contain exactly the same address, the lowest free address in RAM. That address is also the starting address of your computer's edit text buffer.
Now let's suppose that you're sitting at your computer, and that your computer, assembler, your disk drives and your program data disk are all up and running and ready to go. Let's now suppose that your assembler's EDIT prompt has just come on, and that you're ready to start typing in some source code. Since you've just turned your computer on, your LOMEM and MEMLO pointers will contain the same address when you begin your editing session, the lowest free address in your computer's RAM. Since you haven't changed any default values, that address will also be the starting address of your computer's edit text buffer.
When you start typing in source code, therefore, your source code will always start at the lowest free address in your computer's memory, which brings us to an unfortunate but obvious conclusion: When you write an assembly language program using the MAC/65 assembler or the Atari Assembler Editor cartridge, you can't start your object code program at the address contained in your LOMEM and MEMLO pointers; if you try to do that, your source code and your object code will attempt to overwrite each other, and your computer will reward you with an error message!
Solving the Problem
So what's a poor programmer to do? Well, you can do a couple of things. For example, you could use a special command called SIZE that's provided as a special bonus with both the MAC/65 assembler and the Atari Assembler Editor cartridge. It's easy to use the SIZE command. All you have to do is put your assembler into its EDIT mode, type the word SIZE, and hit your RETURN key. Your computer will then print a line on your screen that looks something like this:
1CFC 2062 9C1F
What the "SIZE" Line Means
The first of these three numbers, 1CFC, is the current value of your computer's LOMEM pointer - the lowest usable address in your computer's RAM. The second number, 2062 in our example, is the value of your computer's MEMLO pointer -- the address at which your edit text buffer currently ends. (We used the word "currently," because the length of your Atari's edit text buffer can vary; as you type in source code, your edit text buffer will get longer. When you delete source code, it will get shorter).
The third number in your assembler's SIZE line (9C1F in our sample line) is the value of another important pointer -- MEMTOP, the highest memory address that can be used safely in a user written program. (Just above MEMTOP is where your computer's screen display memory begins.)
Three Basic Facts
Your assembler's SIZE command, then, can provide you with three important facts that can help you with your memory allocation problems. It can tell you:
- Where your source code program begins.
- Where your source code program ends.
- How much free RAM there is between the end of your source code program and the start of your computer's screen display memory.
A Word of Caution
If you use the SIZE command to decide where to store your object code, however, we do have one more warning: Most assembly language programs produce a symbol table, a list of labels used within a program and their corresponding memory addresses. When you write a program containing labels using an Atari Assembler Editor cartridge, your assembler will automatically store a symbol table just above your computer's edit text buffer. So when you use the Atari Assembler Editor to write a program that produces a symbol table, you must always leave some space between the end of your edit text buffer (the second number in the SIZE line) and the beginning of your object code program. Otherwise, your symbol table and your object code program may overwrite each other, with potentially disastrous results.
No Need to Guess
Fortunately, you don't have to guess how much room you'll need for a symbol table; you can figure that out. You'll need three bytes for each label in your program, plus one byte for each typed character in each label. That sounds like a lot of calculating, and it is; but if you do it long enough, you'll eventually become very proficient at guessing the lengths of symbol tables.
There's an Easier way!
Now that you know all that, here's some good news. There's another command that can be used with both MAC/65 and the Atari Assembler Editor, a command called LOMEM, that can make this whole business of allocating memory much easier. Here's how to use the LOMEM command: When you've loaded your assembler into RAM -- or have slipped your assembler cartridge into your computer and turned your computer on, just type the word LOMEM followed by a hexadecimal number like this:
Then hit your RETURN key. That simple procedure will automatically reset your computer's LOMEM pointer, and will place any source code you subsequently write above the object code that it will generate, instead of below it. You can then store your source code anywhere you like, in the wide open spaces above your machine code, instead of in the cramped space beneath it
With the LOMEM command, you'll never have to worry about what the current value of MEMLO is, and you'll never have to count the number of typed characters in a symbol table. There's one fact to remember, though; if you want to use the LOMEM command, you must use it before you start writing a program. If you use the LOMEM command with a MAC/65 assembler, it will wipe out everything stored in RAM, just like the command NEW. When you're writing programs using the Atari Assembler Editor cartridge, LOMEM must be the very first command you use when you turn your computer on. Otherwise, it simply won't work. If you forget that and still want to use LOMEM, you'll have to turn your computer off and then back on again.
Another Memory Management Problem
You can also run into memory allocation problems when you mix BASIC and assembly language, that is when you write an assembly language program that's designed to be called from a BASIC program. When you want to call a machine language program from BASIC, it's obviously necessary for both programs to be present in your computer at the same time. It's also obvious, unfortunately, that the two programs can't start at the same address. If they did, one program would overwrite the other, and chaos would result. Fortunately, there are ways to solve this problem.
Changing Your MEMLO Pointer
When you load a BASIC program into your computer's memory, your computer uses the value in MEMLO to determine where the program should be stored. If MEMLO points to the lowest free RAM address in your computer when the BASIC program is loaded, then the program will be loaded into your computer's memory starting at that address. But if MEMLO points to a higher address when a BASIC program is loaded into memory, then the program will be loaded into RAM starting at that address.
Obviously, then, the way to keep a BASIC program from overwriting a machine language program stored in low memory is to change MEMLO to a higher address before the BASIC program is loaded. It's easy to change MEMLO to a higher value before a BASIC program is loaded. All you have to do is use a routine like this:
CHANGING THE VALUE OF THE MEMLO POINTER
10 ; 20 ;NEWMEMLO.SRC 30 ; 40 *=$0600 50 ; 60 NEWMLO=$5000 ;NEW MEMLO ADDRESS 65 MEMLO=$2E7 ;ADDRESS OF MEMLO POINTER 70 ; 80 LDA #NEWMLO&255 90 STA MEMLO 100 LDA #NEWMLO/256 110 STA MEMLO+1 120 RTS
What Have You Done?
When you assemble and run this routine, it will store a new address, in this case $5000, into your computer's MEMLO pointer. If you then load a BASIC program into your computer's memory, the starting address of that program will not be the lowest address in free RAM, as it would ordinarily be. Instead, the BASIC program will start at memory address $5000. That will reserve a big block of memory for user written machine language programs: the block extending from the lowest byte in free RAM (the value of LOMEM) to memory address $4FFF.
A Better Way
Although the routine we've just presented will work fine in programs you run yourself, it may not be adequate in programs designed to be run by other people. That's because the MEMLO pointer is set not only at power-up time, but also when the Atari SYSTEM RESET button is pushed. So if the SYSTEM RESET button is pressed accidentally by a program user, MEMLO will be reset to its default value. A more complex MEMLO setting program that is immune to accidents such as the hitting of SYSTEM RESET can be found on pages 8-11 of De Re Atari, the assembly language programmer's guide published by Atari. That program, yours for the typing, can even be run as an AUTORUN.SYS routine, and is just about as user transparent as such a program can be.
Return to Table of Contents | Previous Chapter | Next Chapter