Using the DOORS OS
If this operating system can be loaded into memory at any location, how do you design programs so that they can call these functions? If these subroutines aren't even a part of your user program (but instead reside only in the HC11's memory), how does the compiler/assembler know where they're located (remember, this OS can be loaded into just about any memory address)?
The simple solution would be to remember where in memory you placed the OS, then hard-code the addresses of the start and stop process functions into user programs. However, this approach presents several problems (What happens if you move the OS to a different memory location?). A better solutionand the one I actually usedis to have the OS keep a "pointer" to itself in memory location $0000 (the start of internal RAM on an HC11). Since this pointer is always in the same exact location, your programs will always be able to look it up.
So upon reset, the DOORS OS stores in address $0000 the address of the subroutine runCommand (in kernel.asm and Listing Four, available at www.ddj.com/code/). This subroutine is the one that the user program calls to access all required OS functions. When run, this subroutine checks to see what value register Y is (this is the only argument required by this function). If it's a 0, then startProcess is run; if it's a 1, then stopProcess is run. Likewise, if it's a 2, the time elapsed since reset is returned, or a 3, then the startProcess command is run with the request for an exact stack copy to be made.
With all this in place, you can see that it is easy to call an OS function. For example, to start a new process (without stack copy), load all internal registers with the needed data (mentioned before and as shown in Listing Five; available online), then store the value 0 in Y to specify that you want to run the startProcess command. This is followed by looking up the memory address that's stored at address $0000 and jumping to that address. runCommand takes it from there! Listing Five is a sample program in assembler that starts two processes.
The DOORS OS SDK includes the SmallC directory and readme.txt file with instructions on how to setup the SmallC++ compiler (www.geocities.com/waltsrobots/ smallc.html) to work with the OS. All that's required is to copy a few different files to different locations.
Once you've done this, your C++ programs can access OS features. By including the DoorsOS.h file in your program, you have access to the startProcess(), stopProcess(), getTime(), and fork() functions.
If you're familiar with the UNIX system call fork(), the DOORS OS version is virtually identical. When called, it creates an exact copy of the current process (creating an exact copy of the calling process's stack, which includes variables and return addresses) and returns control to the "parent" (the original calling process), which resumes running for the remainder of its time. Eventually, however, the "child" process (the new process that was created after the call to fork()) will run and resume execution from the same position after the fork() call.
Since both the parent and child processes resume execution from the same exact point (right after the call to fork()), how do you know which is which? Well, the fork() function returns a valid process ID (a value greater than 0) if the current process is the parent. Otherwise, a 0 is returned. Using this return value, a process can know exactly whether or not it's the parent or the new child process. Listing Five (available online) provides an example.
Even though this DOORS OS was originally designed to run on the HC11, there's nothing preventing you from porting the code over to your processor of choice. If you have any questions at all, please to send me an e-mail.