The Architecture of CP/M
The original CP/M is an operating system for 8-bit computers. It runs on either 8080 or Z80 processors in anything from 20k of RAM and it can use a mixture of floppy and hard drives up to a maximum of 16 drives. Other devices can be connected to the system such as a line printer, modem, or tape drive. The user communicates with the system through a terminal that has a keyboard and screen and is presented with a simple command line interface that looks something like this:
It is a very simple and straightforward operating system that is ideal for a single user. It doesn't try to do anything flash or clever and this makes it small, clean, and very easy to understand. This overview will help you to understand why.
What CP/M Does
The main job of CP/M is to help the user run programs one at a time. The operating system lets the user type in a command line which starts with the name of the program followed by parameters for the program to process. Then it finds the program on disk, loads it into memory, and runs it. While the program is running CP/M provides it with basic methods such as handling disk files, getting user input from the keyboard, and writing messages on the screen. When the program finishes control returns to CP/M and the user can type in the next command line to run another program.
The code for the actual operating system is divided into two main parts: the Basic Disk Operating system (usually called BDOS) and the Console Command Processor (usually called CCP).
The CCP handles command lines typed by the user. It is responsible for helping the user type the command line and edit it and then, when the line is complete, the CCP parses the line, searches for the program that the user wants to run, loads it into memory, and runs it.
The BDOS provides about 40 basic methods used by running programs and by the CCP to access disk files and talk to serial devices such as the user's terminal. A program can use one of these methods by making a 'system call' which jumps into the BDOS and starts executing the code for the chosen method. When the method is complete and any input or output that was requested has been done the BDOS returns to the program that called it and the program carries on running where it left off. In this way the BDOS works as a standard I/O library for all CP/M programs.
The CCP and BDOS that are provided with CP/M can be run on any suitable machine without changing them, but a third module is needed to provide an interface between the actual hardware and the BDOS. This third module is the Basic Input/Output System (usually called BIOS).
The BIOS provides about 20 very primitive I/O operations that are used by the BDOS. Where the BDOS is called to do things like open a named file or print a line on the user's screen the BIOS is called to position the disk head to a given track, read a single sector, or send a single character to a particular port. These primitive operations are always called in the same way by the BDOS no matter what machine it is running on, but the way they are carried out inside the BIOS is different from one machine to another. So the main parts of CP/M, the CCP and the BDOS, do not need to be changed to port the system to a new machine; instead all that is needed is a new BIOS that can perform 20 or so primitive operations. In this way the BIOS acts a layer of glue between CP/M and the hardware it is running on.
A new BIOS has to be written for each new design of machine and this is usually done by the maker of the machine. However, since it only needs to provide a few very basic I/O operations porting CP/M to a new machine can be very quick and very easy. Once it is written the BIOS will work on all machines that use the same hardware.
On some machines the BIOS is very simple and carries out its functions exactly when they are called, and it only returns control to the BDOS when the I/O has actually been done. On a more powerful machine the BIOS can be driven by hardware interrupts to capture unsolicited input from devices and to buffer output to slow devices. In this case I/O is not happening exactly at the times that the BDOS requests it, but the core code in the operating system can be left unchanged: the BDOS runs exactly as before and calls the BIOS to make primitive I/O requests and only the BIOS has to be aware that interrupts and buffers are being used.
A simple picture of how a CP/M system looks when it is loaded into memory is:
The operating system reserves a small space at the bottom of memory where it keeps a few working variables; the code for the CCP, BDOS, and BIOS is put right at the top of memory; and whatever space is left in between is available for programs to run in. This space in the middle of memory is called the Transient Program Area (or TPA).
As each command line is typed by the user the program for the line is loaded from a disk file into the bottom of the TPA and then executed. The program runs and can use as much or as little of the TPA as it needs for temporary data. When the program finishes control returns to the CCP which reads the next line and loads another program into the TPA. This constant reloading of programs is how they come by the name Transient: they are only loaded in memory while they are running whereas the CCP, BDOS, and BIOS always remain in memory.
The TPA starts at the same location in memory on all CP/M machines (location 0x0100) which means that once a program has been compiled or assembled on one machine it can be saved in a disk file, copied to another machine, loaded into the TPA, and it will run in exactly the same way. The link between a running program and the BDOS is kept at a fixed location in the workspace at the bottom of memory (location 0x0005) so it does not matter that the BDOS is in different locations on different machines; the link is always in the same place and that is all that a program needs to know to call the BDOS.
The size of the TPA is a critical measure of how useful a CP/M machine is. The more memory a machine has the bigger the TPA becomes and this gives a program more space to run in. A small TPA means you can only run small programs and they can only handle small quantities of data but a large TPA lets you run large programs and they can have much larger data areas in memory. CP/M makes no attempt at virtual memory or swapping programs to disk - a program and all its data must fit into the available TPA. Some of the cleverer programs written for CP/M swap parts of their code to and from disk as overlays or they swap chunks of data in and out of memory as they are needed, but this is controlled entirely by the individual program not by the operating system itself.
So, now that you know the basic structure of CP/M we can go back to why it is small, clean, and easy to understand.
Firstly, CP/M is small because it only provides the essential functions that are needed by a single user and her programs. The CCP only has to read a command line, do some simple parsing, and load programs into memory to start them executing. All of this can be done with a CCP that is just 2k bytes long. The BDOS provides a standard I/O library with 40 essential methods and this is coded in another 3.5k bytes. The BIOS varies from machine to machine, but since it only has to provide a few primitive I/O functions it can be very small. A CP/M operating system can take just 6k of memory leaving the rest available for transient programs.
Secondly, CP/M is clean because there is only one program executing at a time and that program is held entirely in memory. This means that there is no need for the operating system to keep track of resources, control access to devices, or do fancy swapping or paging. The current program is the program and it can do whatever it likes. However, one program at a time does mean that you don't usually see background processes running under CP/M. In practice this turns out to be fine when there is just one person doing one job at a time on their personal computer. Please remember: All computers are just as fast while they are waiting for a user to type something in.
And thirdly, CP/M is easy to understand because it is doing exactly one thing at a time. Either the CCP is receiving a command line from the user, a transient program is running, or the program has called the operating system to do some I/O and either the BDOS or BIOS is working on it. In most cases CP/M does not use interrupts or asynchronous I/O which saves a lot of complexity inside the operating system. Again this means CP/M can't do everything a modern operating system can, but in practice this seems to have little effect on a single user doing one thing at a time.