S100 Computers

Home S-100 Boards History New Boards Software Boards For Sale
Forum Other Web Sites Quiz Index    
An 8086 Monitor
Any 8086 S-100 board normally needs a built in monitor program to monitor its ability to interact with other S-100 bus boards.  Unlike the typical situation for 8 bit CPU's there are typically no space limitations so more code can be added than you would normally see in  say a Z80 monitor for example.  That said, it is usually desirable not to have the monitor ROM extend  below the region found in an IBM-PC (F0000-FFFFFH). For example the PC Video board RAM at A0000H- BFFFFH (and/or) C7FFFH-EFFFFH. Above F0000H everything is up for grabs for us. We will use this space here for  extensive board system diagnostics, we will write our own code to emulate standard PC calls so the software "thinks" it is talking to an IBM-PC.    To do this we need quite a bit of space. Our 8086 monitor therefore will start at F8000H with much of the code space up to FFFFFH filled with true monitor type commands. 
Here is a typical layout:-

8086 Monitor Memory map
The 8086 (and above) family of CPU's all start from a reset at FFFF0H in RAM. This includes by the way the 80286, 80386 etc., CPU's.  In an 8086 there is not much forward space left, (16 bytes), so at that location there is always a jump downwards to the start of the actual monitor. (As an aside, the 8089 I/O coprocessor actually uses some of the remaining 16 bytes there). 

Remember all addresses on the 8086 are obtained by adding a 4 bit shifted left CS: register value with the IP register. The so called "Segment:offset addressing scheme".  Put another way:-

Segment Register        xxxxXXXX0000
IP Register                +yyyyYYYY
8086 20 bit Address =   ZZZZZZZZZZZZ

Upon reset the 8086 CS register will have F000H, the IP register FFF0H, so the initial reset address is FFFF0H.  In our monitor at that address we jump immediately to F8000H which is the start of the monitor.  The first thing we do is set a few things up. We set the DS,ES and SS segment registers to this same CS (F000H) value (upon reset they were all 0's).  This way when we want to print strings etc the DS: is pointing to the same EPROM location as the code.

mov ax,cs     ;Note cs will be F000H
mov ds,ax     ;DS will also be F000H
mov es,ax     ;As will ES
mov ss,ax

Next we  need to setup a valid stack pointer to a valid RAM location. Now normally with a board like this you would use a 1MG RAM board so the stack would be just below the EEPROM at ~ F7FFFH.  However I did not want to make that a requirement. I wrote a little module to find the top of available RAM and place the stack segment and stack pointer there.   So for example this monitor  (and CPM86+) would work  would work fine with only 128K or RAM.  I do not recommend this however.

With a valid stack we and CALL a routine to print a signon message and initialize some hardware.
Next we call the routine PrintRegisters that displays the current values of the segment registers and SP.

If you enter the "K" command you will see all the monitors options. Here is a picture of the screen:-

K Command

Most of the commands are self explanatory.  However there is one feature you need to keep in mind and that has to do with memory addressing.   Most monitor commands are modeled after the TDL/Zapple/Z80 commands. Because we are now dealing with potentially up to 1MG of RAM for many commands, the start, stop RAM locations can take up to 5 digits.  However the actual span/range for any command is limited to 64K.

The following example fills RAM with 76H from 1A000H to 21234H.

Of course for the lowest 64K of RAM the "normal" 4,3,2 or 1 byte formats can be used

Note because of the 64K range limitation, the following will give an error
F1A000,31234,76 or F1A000,1B000,76

I considered using the Intel style Segment:Offset  (xxxx:yyyy) approach, but decided against it, because calculations can sometimes be frustrating, also I want to later extend the monitor for Intel true 32 bit CPU's and the 68K family.  That said, it was a pain to do because we always have to check segment wrap around!

The monitor consists of 3 main sections. It assumes an 8086 (does not use opcodes of the 80286+)
 Section 1. This is a classical monitor. Display, Change RAM/ports etc.
 Section 2. This is a self contained set of routines run diagnostic tests on the S100Computers/N8VEM IDE board.
 Section 3. This fairly complex section. It emulates most of the IBM-PC ROM BIOS interrupts (hard & soft) such that MS-DOS (V4.01)/FreeDOS can be run on the system - without DOS modifications.
Section 1
The first section of the monitor is very generic and should work with very little modification for any hardware setup. Only console I/O etc need to be adjusted for your setup.

Section 2
The second main section of the monitor is activated with the "N" command. This brings up the Dual Board IDE diagnostic package with its own menu shown here:-

N Command

This menu allows you to check out your IDE Drives/CF Cards with the 8086 board and our Dual IDE Board.  For example if you can copy (exactly) one CF card to another using the "Y" command.  Afterwards the "V" command will read each sector and verify that both cards are identical.   You need to be able to demonstrate this before you install CPM86+ or MSDOS in your system.

The software itself is a little tricky because again we cannot make any assumptions as to how much RAM is in the system. I wanted to have the disk sector buffers up out of the way in top memory.  I used the SS:[BP+offset] to access all IDE drive parameters and buffers. Because we are using the SS segment the whole process will work with any memory configuration.  The other commands are fairly straightforward and are the same as for the equivalent 8 bit program MYIDE.ASM (bottom of the page).

Here is a short video demonstrating some of the 8086 Monitor menu items for the basic monitor commands and the IDE drive(s) "N" sub-menu commands:-

Section 3

The third section of the monitor is activated with the "X" command. This brings up the "IBM-PC BIOS"  diagnostic package and run time routines.  This part is the most complex part of the monitor and represents in fact the bulk of the code. 
The "X" command brings up its own sub-menu which is shown here:-

X Command

Most of the commands are fairly self explanatory as you use them. The main function of the diagnostic commands (E,F,G,O etc) is to checkout that the 8259A interrupt hardware is functioning correctly.  For example with the "E" command, when you hit the keyboard, an interrupt is generated (V1 on the S-100 bus) and the key is stored in the BIOS keyboard buffer.

There are also tests for the floppy and hard disk drive sector read and write interrupts.   If you are using the ZFDC and IDE controller boards these tests should work without any modifications.  If you are using another floppy or hard disk controller board you will need to modify (carefully) the code in these sections.  These diagnostic routines allow you to see the contents of a read sector.  It's critical you are reading the same sector as defined by the IBM-PC parameters.

On a PC (at least the early ones)  sectors are defined is terms of Cylinders, Heads & Sectors. INT 13H interrupts for sector reads and writes designate sectors in a somewhat convoluted way (for historical reasons), parameters passed are always as follows:-
AH = 02h
AL = number of sectors to read/written (must be nonzero)
CH = low eight bits of cylinder number
CL = sector number 1-63 (bits 0-5). The high two bits are for cylinder bits 6-7. (hard disk only)
DH = head number
DL = drive number (bit 7 set for hard disk)
ES:BX -> data buffer

Throughout the INT 13 section you will see these values used a lot.   Because only 16 heads are allowed with this format a hard disk can only get to 512MG.   To go to higher disk capacities you need a later version of MSDOS and a BIOS that utilizes "LBA" addressing.   Both formats are implemented on our IDE board but for now I will stick with "CHS" addressing.

Fortunately there are excellent descriptions elsewhere on the web about these issues.   One of the best is the famous "Ralf Brown Interrupt List".  This is a must read for anybody doing a MS-DOS/PC BIOS.

Here is a short video demonstrating some of the 8086 Monitor menu items for the IBM_PC BIOS monitor commands,  the  "X" sub-menu commands:-

Here is another short video demonstrating the use of the 8086 Monitor debugging output option where information about all software interrupts is sent to another serial terminal.

As you look over the code it may be helpful in understanding the Hard Disk sector R/W section to understand in MS-DOS how sectors are identified in the "Cylinder, Head Sector", (CHS) format. See here.  Remember unlike CPM, MS-DOS may ask for a run of up to 80H contiguous sectors in one BIOS call.  It is the BIOS'es job to take care of end of track, heads etc.

The complete source code for this monitor (8086.a86) can be seen here.
The source code itself (8086 Monitor.zip) can be downloaded here.

If you are not familiar with 8086 assembly language code you should study this program in detail.  It utilized a number of the key features of the 8086 CPU and is fairly well documented.

Burning a Monitor PROM using Digital Research's ASM86.COM
Realizing there was a "chicken and egg " problem moving to a 16 bit 8086 operating system from an 8080 based system, Digital Research conveniently provided an 8080 based 8086 cross assembler (and linker) called ASM86.com (and LINK86.com) . This allows you to assemble 8086 code such as our monitor on a standard CPM (8bit) system.  There is only one problem, the HEX file spewed out is not the usual Intel 8 bit standard HEX file but a ".H86" file that also contains segment information for the CPM86 linker.   Unfortunately the Wellon EPROM programmer (and as best I can tell other PROM burners) cannot utilize HEX files in this format.

To get around this I wrote a (crude) simple program in C that takes the ASM86 generated .H86 file, strips away the segment information to yield a standard Intel .HEX file.   This program called H86TOHEX can be obtained here.

This whole process of assembling the 8086 monitor and converting it to a .HEX file that can be loaded with ZSID for example is contained in the following CPM submit file. See here.  Early versions of this monitor (see bottom of this page) were written in code compatible with ASM86.

Burning a Monitor PROM using NASM
The above ASM86 process is slow and cumbersome however. As the monitor grew in size and complexity I got "symbol overflow" errors with ASM86. Currently there are over 9000 lines of code!  I rewrote the code to be compatible with the public domain 8086 (and others),  assembler called NASM.    I regret I did not do this earlier.  It is a fast, efficient and uses clear logical syntax. See the home page that describes this assembler. It can be found here:-  http://www.nasm.us/

Amongst the many output file formats that NASM generates is a .bin file.   This is a straight byte output of the assembly code -- exactly what an EPROM programmer uses. The Windows 7 version of NASM is included in the above 8086 Monitor.zip file.  I recommend you use this system setup instead of the older Digital Research version.

To burn a 28C256 EEPROM's with a Wellon VP280 Programmer...
Load the 8086.BIN file. Select Even bytes (1st of 2) for one ROM and "From File HEX address" and "Buffer Address" leave them as 0000H in the load dialog boxes.
The Edit BOX the code should appear at 4000H-7FFFH in a 28C256 EEPROM.  
Simply press the "Program" button. 
Repeat for ODD addresses.

Currently we only need the top half of the 28C256 EEPROM. The jumpers on the 8086 board are set to only read the EEPROM for addresses F8000 to FFFFFH.  This leaves the RAM space below the monitor free.  Of course should you need more or less EEPROM space you just configure the jumpers on the 8086 board differently.  Early versions of the monitor in fact used only 28C64's.  

If you don't have the Wellon (or similar) Programmer and need to split out the high/low bytes of the code for (example) using the Ackerman Digital Prom Blaster do the following:-

Load the 8086 monitor HEX/BIN code into RAM to 4000H.
Run Split.com  (A quick and dirty program I wrote)
It will put the EPROM low bytes at 4000H - 5FFFH and high Bytes at 8000H - 9FFFH.

Burn two 2764 EPROMS
THN22764     (For Hitachi 2764 EPROMS)

(For Hitachi 2764 EPROMS)

The source for split can be obtained here.  BTW, I really recommend the Wellon family of programmers.  They are Windows 7 compatible (32 & 64bit)  and USB linked.  The company is in Hong Kong but US deliveries are within a week. Also e-mail questions to them are rapidly answered.

First Time Installation of the 8086 Monitor

Starting off for the first time with an 8086 on the S-100 bus is a bit challenging.  The problem is that the 8086 family of CPU's all start after a reset at FFFF0H in high RAM.  Your typical 8 bit Z80/8080 starts at 0H in RAM and cannot reach an address past FFFFH in RAM.  What is need is a quick way to get the initialized 8086 to jump down to (say) 500H in RAM.  The bytes:-

EA 00 50 00  00

in memory at FFFF0H will do this.  I have outlined various ways you can get this code at that location elsewhere.

To test and configure this 8086 monitor for initial usage I have written a small custom version (it does not contain the IDE or IBM-PC BIOS code) for testing purposes.  It can be downloaded here.  You should load this version with CPM's SID into RAM at 500H with the command:-

SID 8086x.bin               (This will load the image to 600H to ~3000H). (CPM adds 100H!)
MOV 600,3000,500        (This will place the code at the correct absolute address 500H in RAM)

After switching to your 8086 Board (IN, port EDH), have the 8086 jump to there with:-
At location FFFF0H:- EA 00 05 00 00 (either in its onboard EEPROM or done by hand in RAM).

The monitor should sign on.  This however is a "fragile" version of the monitor. It is used to debug basic things like console I/O etc.  The stack is located at 4FFH -- do not overwrite it!  That said many of the basics display/modify/move RAM etc functions should work.

Do not however spend a lot of time with this version. Once you have console I/O going, burn a ROM version for the high memory addressee (F8000H). 

Once you have a PROM based version of the 8086 monitor running things get much simpler.  You may still need debugging.  For this reason in the monitor code there is a line:-

MONITOR_ROM EQU FALSE              ;TRUE = Monitor at F000:8000H, FALSE = Monitor in a RAM area (F000:2000H)

When FALSE the monitor code will be assembled to reside at F000:2000H in RAM (change as you require).  You can assemble the code on your PC with NASM, and move it across to your CPM80 system.  Then type:-

SID 8086.BIN

The monitor code will reside at 2100H up to ~7600H.

If you reset and activate the 8086 ROM monitor, the "Y" command will move the above code up to F2000H in RAM and jump to that location, bringing up your test version.   This saves many keystrokes and frustration!

This monitor will  boot IBM's MS-DOS (Currently V4.01) and FreeDOS unaltered from  1.44M 3.5" floppy disk. The code can be easily modified to do the same thing from a 5" disk.

More importantly the monitor will also boot MS-DOS from drive #2 on our IDE Board. All "well behaved" MS-DOS programs seem to work.  The code can be easily modified to utilize the IDE drive #1 (or the older single IDE drive boards).  Take care however, you don't want to overwrite your CPM system.

Very important! You can place the 1.44M Floppy disk or CF-CARD in a standard Windows 7 PC and read, copy modify files going back and forth between both computers.  The CF card (currently) appears as a 512M disk to MS-DOS/Windows 7.

I have yet to write code to allow formatting of disks and drives. The former is fairly easy with our ZFDC board.  For the one time requirement of the Hard disk/CF Card using a PC is easiest.  It's best to try and do this on an older PC that allows you to set the Hard Disk "type".   Use a custom type of 255 cylinders, 16 heads and 256 sectors.   Alternatively if you know how, you can alter the Hard Disk Partition Table Parameters. Much of this is amply discussed on the web.

Hardware Interrupts.
Currently the BIOS utilizes only two S-100 hardware interrupts.

VI0.  This is for the system tick. On a PC this interrupt is generated 18.2 times a second (by a 8253 programmable timer).  In my case I utilize the PIC-RTC MM581657A clock chip. It outputs an interrupt every 0.1 seconds.  I have not yet gotten around to adjusting the difference in the BIOS system Tick handler so the time will be off as the system is used.  I do read the time however at startup from the RTC.  My intension is to put together an S-100 board with a "proper" CMOS clock chip as there was on the IBM-AT.  This will allow me to have a better system tick but also utilize the CMOS RAM for data storage for variables used in later PC versions.

VI1.  This is the keyboard input interrupt. Whenever a keyboard key is pressed this interrupt is triggered. The interrupt inputs the keyboard character(s) and places it in the BIOS keyboard buffer.  In this BIOS we input data from our Propeller driven Console IO board. Unfortunately I did not include interrupt capabilities on the board.  A serious oversight!  Fortunately there is a patch area on the board and an unused Propeller pin (pin 17).  By adding one 74LS07 chip you can bring pin 17 to the S100 bus via an Open Collector output to S-100 line #5 (VI1). [Connect R21 to pin 13 of the 74LS07. Connect pin 12 of the 74LS07 to the S-100 line #5. Also connect pin 12 via a 1K resistor, to +5V]. Obviously the next version of the board will include this modification.

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.

(Digital Research ASM86 format)   (06/21/2011)
PDF FILE OF THE 8086 MONITOR   (09/17/2011)

This page was last modified on 09/19/2011