S100 Computers

Home S-100 Boards History New Boards Software Boards For Sale
Forum Other Web Sites News 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 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 CALL a routine to print a signon message, initialize some hardware and display the current value of the stack segment 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.
F1A000,21234,76

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

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 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 listing for this monitor can be found at the bottom of this page
The source code itself (8086 Monitor.zip) can be downloaded also found at the bottom of this page.

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 NASM
Currently there are over 13,000 lines of code in the 8086 monitor!  A while back I rewrote the early CPM86.A86 code to be compatible with the public domain 8086 assembler called NASM.    I regret I did not do this earlier.  It is a fast, efficient and uses a clear logical syntax. See the home page that describes this assembler. All my more recent versions of 8086 code use the NASM assembler.

NASM info 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 binary byte output of the assembly code -- exactly what a typical EPROM programmer uses. The Windows 7 version of NASM is included in the above 8086 Monitor.zip file at the bottom of this page.  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 a 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).  

You will notice that I put the stack (and BP buffers) lower down in RAM, at segment D000H.  This is to allow the RAM at E000H to be free and utilized for the many early test versions of the monitor. This way when they are loaded from the PC with the monitor "W" command they do not overwrite the current stack.  Clearly you can later move then up if you really need the extra space.


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 in a ROM 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. With it you should be able to see all RAM 0-1MB.

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 (at 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 (E000:0000H)

When FALSE the monitor code will be assembled to reside at E000:0000H 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 use the monitor "W" command (or the CPM PCLOAD.COM program)  to deposit the program in RAM.  You can also use the (old) monitor "Y" command to move code at 100H in RAM (loaded with SID for example),  up to E0000H, however this approach is now superseded by the combined "W" & "G" commands in the more recent versions of the monitor.


BOOTING PC-DOS
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.


From V7.0 onwards the monitor incorporates three console output options. You can either send console data to the Propeller driven Console I/O board, a Lava-10 Video board or to an IBM-PC CGA/VGA compatible video board (Monitor "B" command).  Currently I am using the Lomas "Color Magic S-100 board" for the third option.  (A future Cirrus Logic GP-5420 based S-100 video board is being planned!). 


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 8254 programmable timer).  In my early system I utilize the PIC-RTC MM581657A clock chip to generate a system tick. It outputs an interrupt every 0.1 seconds.  The BIOS software needs to be adjusting for the slower system tick so the interrupt handler matches that used in the IBM-PC BIOS. 

More recently I have switched over to using our MS-DOS Support board  that utilizes the same 8254 Timer the IBM-PC utilized for the system tick. The PC uses an unusual clock frequency (1.193MHz) to drive the timer.   I generated this frequency using a common 14.318 MHz TV oscillator and a 74LS92 divide by 12 counter. This generates the required 18.2 ticks/second.


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 early versions of that 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). See the bottom of the page here for more details.

The V2 of this board now incorporates that feature. 
Note MSDOS will not sign on unless these interrupts are implemented in hardware (typically with the MS-DOS Support Board)

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.

EARLY VERSION OF THE 8086 MONITOR SOFTWARE   
(Digital Research ASM86 format)   (V3.6   06/21/2011)
8086 MONITOR SOFTWARE (Using MM58167 Clock Chip)     (V7.1   10/16/2011)


MOST CURRENT VERSION PDF FILE OF THE 8086 MONITOR   (Using DS12887 Clock Chip+ Lava Output)   (V10.33a   8/9/2014)
MOST CURRENT VERSION OF THE 8086 MONITOR SOFTWARE (Using DS12887 Clock Chip+Lava Chip Output)   (V10.33a  8/9/2014)
NASM Assembler and Documentation   (2/8/2013)

This page was last modified on 09/18/2016