Bringing Up CPM86+ for the First Time
Bringing up CPM86 (using an 8086 S-100 Board) can be a somewhat daunting task
for beginners. Not only is the hardware different and you have to worry
about its (often untested) functionality, but the software is an order of
magnitude more complex. On top of that you have a kind of chicken and egg
situation in that you need a functional running 8086 system to build a system.
Way back in the early 1980's Digital Research put out its CPM86 (V1.0) operating
system to run on such 8086 systems. It was functional, reliable, but was
really just a warmed over CPM (V2.1). There were none of the very nice
"extras" you had in CPM3 (also called CPM+). Once the latter was published
there was a ground swell for the equivalent operating system for the 8086. It
was developed in 1983 and was called CPM86+ or CPM86 Plus. It had all the nice
interactive features of CPM+.
These features included:-
performance, especially random I/O, was improved over that of CP/M-86 v1.0 by
hash coding the directory entries and Least Recently Used
(LRU) buffering of directory and
The BDOS performed auto-login of removable media
drives. The implementation of door open interrupts on removable media drives was
highly recommended as an additional check on data integrity and for providing
disk I/O performance improvements of up to 30%. The door open interrupt
information allowed the BDOS to treat removable media drives in a manner similar
to permanent media drives.
The file system capacity was
larger allowing a storage capacity of up to 512
megabytes for each of the 16 possible logical drives, and the maximum
file size was 32 megabytes. The file system also provided time and date
Live control characters and type-ahead were supported
by cooperating routines in the BDOS and BIOS. The live control characters were
CTRL-C, CTRL-S, CTRL-Q, and CTRL-P and their functions were performed when a
keyboard interrupt occurred.
The CCP could be
a permanent part of the system or loaded as a transient program. When the CCP
was a transient, it was loaded and remained in memory until the memory was
needed by another transient program.
The mapping of the logical
devices CONIN:, CONOUT:, AUXIN;, AUXOUT:, and LST: onto different physical
devices was standardized and made more flexible. This allowed the dynamic
remapping of the console to another device, such as a graphics console. Logical
device output could be directed to several physical devices at once.
CP/M86+ could run
up to four programs (processes) at once, one in the foreground and up to three
in the background. However only the foreground program had access to the
physical console; the background programs had to have console I/O redirected
from and to files.
The interface to
hardware drivers was greatly simplified and improved by use of a BIOS Kernel.
The Kernel was intended for unchanged use in any BIOS implementation. However,
the source was provided if you need to alter the Kernel.
performed Blocking/Deblocking instead of the BIOS. BIOS disk reads and writes
transferred physical sectors and up to 16 Kbytes on each call.$ GENCPM created the CP/M86+ image contained in the CPM3.SYS
file and provided many configuration options. GENCPM could automatically all
allocates buffers while building the system image. This allowed the testing of
many combinations of disk and directory buffers enabling the system implementer
to optimize disk performance and memory usage.
For a single user efficient operating system this really was what CPM should
have been all along. As we shall see below it was a joy to write a BIOS
for its very simple and symmetrical interface.
However there was one very serious disadvantage -- you had to have a functional
CPM86 (V1.0) system up and running to build a CPM86+ system. This is
because the building process requires RASM86 & LINK86 (a CPM86 reloadable
assembler & linker) and it also needs CPM86 to run the program "GENCPM" which
actually splices together the code modules (interactively) to make the final
This means you must first build a CPM86 (V1.0) operating system. That thing is
primitive, I can assure you, you will count the hours until you have a CPM86+ system
going and never go back! However the one thing CPM86 (V1.0) had
going for it was you could construct a CPM86 BIOS on a Z80/8080 CPM system.
Digital Research provided ASM86.COM, an 8086/8080 cross assembler for this
purpose. They went even further and provided XLT86, an 8080 program that
(crudely) converted 8080 assembly source (but not Z80) code listings into the equivalent 8686
ones. Useful for writing your first 8086 CPM BIOS.
Build CPM86 Plus - The Process
So this is the process: We will construct an absolutely stripped down version of
CPM86 utilizing our ZFDC Floppy disk controller board utilizing only 128 byte
sectors on a SSSD IBM format 8" disk. We will allow for two disks A:
The reason we don't utilize the faster IDE board (or other larger disk formats)
is that CPM86 requires sector buffering for sectors larger that 128 bytes in the
BIOS. This is somewhat complicate for beginners. We will then
utilize this basic CPM86 system to construct a CPM86+ system on our Dual IDE
board system. From then on all CPM86+ system improvements/disk additions
will be from that board. CPM86+ handles any disk format with any sector size
within its own DOS kernel -- you never have to worry about those things in
CPM86+ as we will see below.
Now there is one possible shortcut. If you can find a CPM86 system (on the
web) that runs on an old IBM-PC box and it boots OK you can go directly to the
second step below. While I did not look extensively, I did not find
a good CPM86 (or emulator) that would work with my current Windows 7 hardware.
BTW, your system must have a 1.2M 5" floppy disk (CPM86 came out before 1.4M, 3"
One final unusual twist on this story.... It turns out that Digital
Research never actually officially released CPM86-Plus. Because of
competition from MS-DOS at the time, they wend directly to "Concurrent CPM86".
This was a more powerful operating system allowing multiple independent tasks to
be run at once. However it is much more difficult to implement and
probably not for most beginners, certainly not for a non IBM-PC box initially
anyway. BTW, our CPM86+ signs on with a serial number of 0000-00000-0000!
Nevertheless the "unofficial" CPM86+ version has been around for years and is
quite popular. I looks like it was released in some kind of official
version in Europe with a few different non IBM-PC machines. It behaves at a user level almost identically to CPM3.
Most importantly both operating systems can share the SAME disk and files.
Documentation however was less common. I managed to track down a hard copy of
the (unpublished) CPM86+ Installation Guide I had from 30 years back! Here
is the .PDF file:-
CPM86 Plus Operating System
You really must read this (well documented) guide very carefully to understand
the BIOS. It contains everything you need to know to put together a very
fast and efficient disk operating system and unlike earlier Digital Researches
earlier documentation is well written.
Step 1: Building CPM86 (V1.0)
The BIOS for CPM86 is very similar to the CPM (V2.0) BIOS. As I said
above, both the systems assume all disk sectors are 128 bytes in size. If you
use larger sectors you must do a two step process of working with larger sector
in memory and then passing 128 byte sections of it to/from the BIOS. Since
we are going to using a one time only "quick & dirty" system, we will utilize
only the very standard CPM 8" SSSD 128 byte floppy disks on our ZFDC. This
approach should work for any S-100 FDC board.
The source listing for this BIOS can be obtained
All the files necessary to build the operating system can be downloaded
There is there a submit file (FBIOS.SUB) that does
everything automatically for you under CPM using the Altair CPM3 Emulator (see
If you have written CPM V1.0 BIOS's you will see there is nothing spectacular
about the CPM86 BIOS code.
You will end up with a file FBIOS.HEX. This is the "converted" .H86 File.
(Remember the HEX file spewed out by ASM86 is not the usual Intel 8 bit
standard HEX file but a ".H86" file that also contains segment information for
the CPM86 linker).
However there is a bug in my H86TOHEX program that I have not had time to track
down, (perhaps somebody else can). The last line of the HEX file (still)
contains segment information that confuses SID (see below). With an editor, you
need to delete the last line of the FBIOS.HEX file and in its place put:-
Then save the file as FBIOS.HEX.
Then run the MAKE86.SUB file. FYI, this submit file contains :-
(then run) CPM86T.COM
Running CPM86T under CPM will launch your new CPM86
There is a little more to this this than appears on
the surface. The image of CPM86-.COM actually begins at 600H in RAM. This is
Digital Researches' true CPM86. We splice the BIOS directly on top of that and
then save the whole image (100H to ~3FFFH) as CPM86T.COM. Note how it is a
CPM80 .COM file. This means we can load it directly from any CPM80 disk
with a Z80. When that is done the CPM80 jumps to 100H in RAM (just like any
other CPM80 .COM file). Here it finds:-
at that location the Z80 will find:-
This will cause the 8086 to take over the S-100 bus and put the Z80 is a hold
state (at location 4F3H).
The 8086 monitor check's to
see if there are 90H's (8086 NOP's) in RAM at 500H (indicating that CPM86
has probably been loaded) and then does a Far Jump to 500H
in RAM. The 8086 is in control now. It plows through some more NOP's until
it gets to 580H in RAM. There it does a Far Jump
into CPM86 itself (to 600H + 2500H or CPMINIT in the BIOS) never to return.
The reason for this somewhat roundabout process is that the first 400H bytes of
RAM are always reserved for the 8086 Interrupt vectors. For the 8086, no
practical code can be below 400H in RAM. The reason for the gap
between 400H and 600H (where CPM86 begins) is we need space to switch CPU and
check CPM86 is in fact loaded. This clearly would only take a few bytes,
but in an early system I had I also utilized the powerful Intel 8089 I/O
co-processor. A discussion on this is beyond the scope of this article, suffice
to say the 8089 co-processor needed RAM as well. The rest is history!
OK we are almost there. Next we take a clean formatted IBM 8" SSSD disk
and load a simple text file on it. The above FBIOS.A86 is a good one. Then
launch the CPM86T.COM program from whatever CPM or CPM3 (Z80) you normally
use. After some disk grinding, CPM86 should appear on your screen then following
some disk grinding the A: should appear on the screen.
Enter TYPE FBIOS.A86 (or whatever test
file you loaded on the disk).
The file should display correctly with all the lines in the correct order.
If they are out of order, your sector/track numbering code is incorrect.
Next rename the file. It goes through correctly and you can still read the
file with its new name your write sector function is probably OK.
Next reboot your old CPM system and load across the CPM86 files
and reboot COM86 again as above.
Check you can:-
If no errors you are in good shape.
Display the directory with
The files sizes should match.
At this stage you probably have a correct and basically functional CPM86 system.
Good enough to build CPM86+ on those 8" disks!
In case you run into problems I have written a self contained Diagnostic program
to Read/Write to sectors on an 8" disk using the ZFDC Board. That program
ZFDCTEST.A86 can be seen and downloaded
here. Neither the
BIOS of Diagnostic program is "bullet proof", they are one time affairs, so
don't assume everything has been tested.
Here are the relevant files mentioned above:-
To view the FBIOS.A86 please click
To download all components mentioned above click
Step 2 Building CPM86+
We now use the above crude CPM86 Operating System to build our CPM86+ system.
This as I have to say above can be a frustrating experience because disk
space is limited and slow. You may have to switch files back and forth between
your CPM80 disk(s) and the above floppies to get the job done. [I have to
admit here, I first used a 1MG memory disk (with 128 byte sectors), to do
everything described below. I will not describe that here because
these boards are not common, and writing an CPM86(V1.0) 8086 BIOS is
more difficulty than that for a standard 8" floppy].
Before we get started however read the
Documentation one more time. It will save you a lot of headaches later!
Also, if you are not familiar with Digital Researches concept of Disk Parameter
Tables (DPB's) and Disk Parameter Headers (DPH's) go to my section on
Bringing Up CPM3 where these are explained in detail. It is very
important you understand the relevance of the DPH and DPB tables in CPM86+.
Load all the files here on to your CPM86(V1.0) Floppy.
Let us look at the files we are going to work with in the submit file on that
disk to build CPM86+:-
rasm86 bioskrnl $$szpz
rasm86 init $$szpz
rasm86 chario $$szpz
rasm86 clock $$szpz
rasm86 disk3 $$szpz
We normally don't touch the bioskrnl.A86 file
The first thing we will do is edit the CPM86 modules
INIT.A86 and CHARIO.A86. You can look
through the source code I supply. There is nothing special or unusual there.
The module CLOCK.A86 takes care of system
interrupts and the Time/Date functions. We will leave them unused at this point.
BTW, CPM86+ really shines when certain interrupts are used . That said,
they are tricky to implement and definitely should not be in early versions of
The main file is disk3.a86. This file
contains the complete CPM86+ BIOS module for the
Board. Please look through the code first by clicking
At the bottom you will see the two DPH tables for the two Disk Drives; Here is
the one for the A: drive:-
If you have worked with CPM3 BIOS'es you will see this
table is very similar. We enter 0FFFFH's for the disk checksum vectors etc
and allow GENCPM (see below) to calculate the values for you.
0000H ;TRANSLATE TABLE (NONE FOR HARD
0,0,0H ;SCRATCH AREA
0H ;DOOR OPEN FLAG
0,0H ;SCRATCH AREA
DPB0 ;DISK PARAMETER TABLE
0FFFFH,0FFFFH ;CHECKSUM, ALLOCATION VECTOR
0FFFFH ;DIRECTORY BCB
0FFFFH ;DATA BCB
0FFFFH ;HASH TABLE
0 ;UNIT 0 ON
0 ;ZERO FLAGS
AT THE MOMENT
You will notice below the pointers to:-
The disk/hardware initialization routine for that particular disk
The disk login routine for that particular disk
The sector read routine for that particular disk
The sector write routine for that particular disk.
Different disks can utilize the same routines (or in the case of disk
initialization, just return back to the BDOS). Two subtle points to keep in
mind. The call to disk login is made only once (or after a ^C) and it is
primarily there for hardware cases to determine and flag disk densities. It is
NOT called for each sector read/write.
For sector reads and writes Digital Research took advantage of the 8086's
ability to utilize the stack to pass values. As you can see all sector
parameters are passed to the bios using the SS:[BP+Offset].
This is very clean and efficient. The offset values are:-
iopb_mcnt equ byte ptr 15
;Sector count for multi sector R/W's
iopb_drive equ byte ptr 14 ;Selected Drive
iopb_track equ word ptr 12 ;Selected track
iopb_sector equ word ptr 10 ;Selected Sector
iopb_dmaseg equ word ptr 8 ;Selected DMA Segment
iopb_dmaoff equ word ptr 6 ;Selected Segment offset
So in a sector read routine if you wish to
get the requested Drive you would in effect have-
AL, Byte Ptr 14 [BP]
What is really nice is that you can check and modify the value at the memory
pointer directly. CPM86+ utilizes the concept of multi sector reads and
writes. So instead or writing one sector at a time with each BIOS call,
you can write a number of contiguous sectors to a disk all at once. The count of
sectors to be written is passed as
iopb_mcnt. We just decrease this value with each sector
transferred. Again see my code in the above example to better understand
The other table we need to construct in the BIOS is the DPB table.
This table describes the layout of each disk (sectors, tracks etc). I
describe it in detail in the CPM3 write-up, see
For our first IDE Drive it looks like this:-
DPB0 EQU OFFSET $ ;DISK
;PHYSICAL SECTORS/TRACK (Note CPM3 uses LOGICAL 128 byte sectors)
DB 4H ;BLOCK
DB 0FH ;BLOCK MASK
DB 0H ;EXTNT
DW 0F2FH ;DISK SIZE - 1 (3887)
DW 3FFH ;DIRECTORY MAX
DB 0FFH ;ALLOC0
DB 0FFH ;ALLOC1
DW 8000H ;CHECK SIZE (NONE)
DW 1H ;OFFSET
DB 02H ;PHYSICAL
RECORD SHIFT FACTOR
Now there is no equivalent RASM86 DISKDEF
macro like there is for CPM3 to calculate these values. The good
news is that (with the exception of the first entry) the values are the same as
those calculate for CPM3. These values are in fact difficult to calculate
for beginners. So the easiest thing to do is put together a macro for CPM3 (a 2
line assembly file) and use RMAC to run the macro. Look at the .PRN file and
pick up the values. For my IDE board with a CF card the macro is:-
The above macro will generate the above table. There is one highly
critical difference between the two systems. In the case of CPM86+ the first
entry is always the number of actual Physical sectors/track. (
In our case these sectors are 512 bytes in size).
In the case of CPM3 (and the macro generated), the first entry is the
number of Logical 128 byte sectors/track. In our case it would
be 61X4 = 244. This is a very common error beginners make.
The first entry aside, the DPB table values in your CPM86+ table must be EXACTLY
the same as the DPB table values in your CPM3 system if both operating systems
are to share the same disk(s). If there are differences you will
have untold problems in the future. Often they don't show up immediately
but over time, so be very careful.
Two other points while I am on sharing system disks: CPM86+ can work with
disk sizes up to 512MG/disk. The normal (DISKDEF) generated max size for CPM3 is
8MG. Digital Research says you can "hand do" larger CPM3 disks. I
have never done this and would be interested if somebody else did.
Second, in their wisdom!, Digital Research names the final GENCPM generate
operating file "CPM3.sys". This of course is
the same name as that of the CPM3 system file required to boot that system.
So... if you are building CPM86+ make sure not to have it in User 0 of your boot
disk. Otherwise you will blow yourself out of the water on the next CPM3 boot.
Why the CPM86+ file was not called CPM86.sys is a
complete mystery to me.
OK, so assuming we have assembled all our BIOS modules into .OBJ files. We next
need to link them together. We use the CPM86 (V1.0) LINK86 and an input
file which I call BIOS-H.INP
reads the following (text) file:-
Don't worry about zero.l86 for now. We end up
with our critical CPM3.sys file (on the same A: floppy disk).
To make life easy Digital Research then provided a CPM86 based program called
"GENCPM" that interactively configures the above
CPM3.SYS file for your exact hardware makeup. Its very similar the
equivalent program in CPM3. It allows you for example to you to define your boot
disk, how much memory to set aside for buffers etc. The program will use a
file called GENCPM.DAT as your default input values if you type :-
It will use the parameters in that file instead of you having to type them in
each time. Its intelligent enough that if you add a new disk, of make disk
parameter changes, it will ask you for new GENCPM parameters.
The program will rename the above CPM3.sys to
CPM3.old and write a new file CPM3.SYS
containing all your updated parameters.
Again we are almost there! If you load this CPM3.sys file into RAM at 480H
with SID and have your 8086 after a reset do a far jump to 600H in RAM, CPM86+
will boot and you will have a perfectly operating system. But that would
be too simple! We want to have the CPM3.sys file be bootable from CPM3 and
do the switching in software. So we pull the same stunt we did above
for CPM86 (V1.0) above.
My CPM3 MPATCH.SUB file will do all this for you and write the file CPM86x.COM
on the floppy disk A:. Note it's now a .COM file and can be launched from any
CPM (v1.2 or 3) system. Its counting on two things. Your 8086 takes
control of the S100 Bus whenever you input from port EDH and in doing so always
does a far jump to 500H in RAM.
The first time you bring this IDE Board based CPN86+ system up be careful. Don't
do anything that writes sectors to the disk. Read a file with text to be sure
the sector read order is correct. Preferably a large file. Next just
rename a file. This writes to just one sector (minimizing potential damage).
Check the file is gone. Then PIP one file to another using a
different name and the [V] (verify) option. Lastly put in a blank CF-Card in tee
second drive and copy with verify a whole user group. It that is OK you probably
have a basic CPM86+ operating system up and running. Enjoy!
With this functional CPM86+ system on your IDE drive you can now move everything
across to a unique user number on your CF Card/Disk.
Step 3: Adding Floppy Disks To CPM86+
Finally we will add floppy disk capability to our CPM86+ system. You
must first write a BIOS module exactly along the lines we described above for
the IDE drives. I have written one for a system containing two 8" IBM 128
byte sectors SSSD on drives B: and C: , a 5" disk on Drive D: (using the
standard IBM-PC CPM86 Format) and a 1.44M 512 byte sectors DDDS disk on
drive H: utilizing our
ZFDC Board. Note how simple it is to write such a BIOS using the ZFDC
Board. We just send simple commands to the board. The onboard Z80/WD2793 does
The Source code for this ZFDC based BIOS (FLOPPY.A86) can be seen
All files necessary to construct a IDE + ZFDC CPM86+ system can be downloaded
The CPM86+ Plus Operating System Installation Guide can be obtained
The CPM86 (V1.0), Systems Guide can be obtained
The links below will contain the most recent versions of the above software.
Note, it may change over time and may not correlate
exactly with the text in the article above.
MOST CURRENT CPM86
MOST CURRENT CPM86+
(For IDE Drives Only) SOFTWARE
MOST CURRENT CPM86+
(For IDE & ZFDS Floppy Drives) SOFTWARE
CPM86+ CMD Files
This page was last modified