CCGFCU.WS4
----------

CP/M-86 Compatibility Guide For CP/M-80 Users   (= CCGFCU...)

Copyright (c) 1980 Digital Research
Pacific Grove, California

(Revision of 10/21/80)  (= 21 October 1980)

(Retyped by Emmanuel ROCHE. Posted in comp.os.cpm in 2003)

CP/M-86  is  a single-user operating system for the  Intel  8086
microprocessor.  Since  the  Intel  8088  CPU  is   functionally
equivalent  to the 8086, CP/M-86 is suitable for use  with  both
processors.  The  design philosophy of CP/M-86 follows  that  of
CP/M  for  the  8080,  8085,  and  Z-80  microprocessors,   with
additional facilities to account for the increased address space
of  the  8086 family. The new features  also  allow  application
programs  to  easily  upgrade  to  the  MP/M-86  and   CP/NET-86
environment, where multi-programming and computer networking  is
supported.  This document assumes basic familiarity with the  8-
bit  CP/M  software  product,  and  specifically  describes  the
differences and extensions found in CP/M-86.

1.  CP/M-86 Operational Differences
-----------------------------------

CP/M-86   maintains  file  compatibility  with   previous   CP/M
versions,  and provides a familiar environment for the  operator
and  programmer.  Utility programs, such as ED, PIP,  STAT,  and
SYSGEN  operate in the same manner as their 8-bit  counterparts,
while ASM and DDT provide the basic tools for assembly  language
development using the 8086 microprocessor.

Under  CP/M-86,  multiple programs are loaded in  "stack  order"
into  memory  for  execution.  Programs  themselves  can   cause
additional programs to be loaded for subsequent execution. Thus,
for  example,  the background DESPOOLing utility  can  first  be
loaded,  followed by execution of DDT. DDT may, in turn, load  a
test  program for a debugging session, and transfer  control  to
the test program between breakpoints. In general, CP/M-86  keeps
account  of  the order in which programs are  loaded  and,  upon
encountering  the  program abort key  (Control-C),  discontinues
execution  of the most recent program activated at  the  console
command  level.  Thus,  in the above case, a  Control-C  at  the
command level first discards DDT and the test program, while the
second  Control-C  aborts  DESPOOL. At  this  point,  subsequent
Control-C  characters are ignored, since there are no  executing
programs activated at the console level.

2.  Memory Organization
-----------------------

The  8086 memory addresses range from 00000H to  0FFFFFH,  where
each  memory location holds an 8-bit value, resulting in  a  one
megabyte address space. The following terms are used  throughout
this document when 8086 memory organization is discussed:

        Nibble          4-bit half-byte
        Byte            8-bit value
        Word            16-bit value
        Double Word     32-bit value
        Paragraph       16 contiguous bytes
        Segment         Up to 64K contiguous bytes
        Offset          16-bit displacement in a segment
        Group           one or more segments

Word  values  are  standard Intel format, with  low  order  byte
stored first in memory. Double words consist of two word  values
in standard format, and often represent an offset followed by  a
paragraph  address. All paragraph addresses are on even  16-byte
boundaries,  and  thus a paragraph address has an  assumed  low-
order nibble value of 0, in order that the address can be stored
in  a word location. The paragraph address 0000H,  for  example,
represents   the  actual  memory  location  00000H,  while   the
paragraph address 0001H becomes the memory location 00010H.

CP/M-86 itself consists of the Console Command Processor  (CCP),
the   Basic  Disk  Operating  System  (BDOS),  and   the   user-
configurable  Basic  I/O System (BIOS). All three  portions  are
resident, and are not available as data space after a program is
loaded. CP/M-86 memory consists of a sequence of (possibly) non-
contiguous  areas,  which are addressed by a  memory  management
scheme  within CP/M-86. Up to eight non-contiguous memory  areas
can  be  defined  within the BIOS, in  order  to  provide  basic
allocation  information.  When non-contiguous memory  areas  are
mapped in this manner, the base memory addresses must be on  16-
byte  paragraph  boundaries.  Normally,  however,  8086   memory
consists of contiguous RAM beginning at location zero, and  thus
only one memory area is defined within the BIOS.

The  Boot  Loader resides on the first two  system  tracks.  For
future  expansion,  however, the CP/M-86 system itself  is  read
from the CPM.SYS file stored on the system disk. Thus, the  Boot
Loader  contains  a simple version of the  CP/M-86  BDOS,  which
allows  the  CPM.SYS  file to be opened and  read  into  memory,
similar  to  the operation of MP/M. The actual load  address  is
determined  when the Boot Loader is configured. CP/M-86  is  not
normally  operated  in the area from location  0  through  3FFH,
since this area is often used for interrupt vector  information.
For  standardization,  it is suggested that  CP/M-86  be  loaded
beginning  at  location 400H. In any case, the BIOS  memory  map
specifically  excludes the interrupt vector area and the  memory
area  in  which  CP/M-86  resides, so  that  this  area  is  not
available for allocation to user or system programs.

3.  Memory Models
-----------------

CP/M-86  loads programs into the Transient Program  Area  (TPA),
using  three  different  memory models  corresponding  to  three
popular memory segmentation techniques. The three models are:

        8080 Model
        Small Model
        Compact Model

The  8080 Model supports programs which are directly  translated
from  the 8-bit CP/M environment, where code and data areas  are
intermixed. The Small Model is similar to that defined by Intel,
where code and data spaces are separated into two segments of up
to  64K  bytes  each. The Small Model is  suitable  for  use  by
translated  8-bit  programs  where  code  and  data  are  easily
separated. The Compact Model allows execution of programs  which
perform  their  own segment management, allowing  programs  with
code  and data segments which reach the addressing  capacity  of
the host memory configuration. The three models differ primarily
in  the  manner in which the segment registers  are  initialized
upon program loading.

In  all  three models, the DS register addresses a  "base  page"
area,  similar  to 8-bit CP/M where various default  values  are
stored.  The base page extends from offset 0000H through  offset
00FFH  from  the DS register, and contains  the  following  pre-
defined areas:

                    +-----+-----+-----+
        DS + 0000H: | LC0 | LC1 | LC2 |
                    +-----+-----+-----+
        DS + 0003H: | BC0 | BC1 | M80 |
                    +-----+-----+-----+
        DS + 0006H: | LD0 | LD1 | LD2 |
                    +-----+-----+-----+
        DS + 0009H: | BD0 | BD1 | xxx |
                    +-----+-----+-----+
        DS + 000CH: | LE0 | LE1 | LE2 |
                    +-----+-----+-----+
        DS + 000FH: | BE0 | BE1 | xxx |
                    +-----+-----+-----+
        DS + 0012H: | LS0 | LS1 | LS2 |
                    +-----+-----+-----+
        DS + 0015H: | BS0 | BS1 | xxx |
                    +-----+-----+-----+
        DS + 0018H: | LX0 | LX1 | LX2 |
                    +-----+-----+-----+
        DS + 001BH: | BX0 | BX1 | xxx |
                    +-----+-----+-----+
        DS + 001EH: | LX0 | LX1 | LX2 |
                    +-----+-----+-----+
        DS + 0021H: | BX0 | BX1 | xxx |
                    +-----+-----+-----+
        DS + 0024H: | LX0 | LX1 | LX2 |
                    +-----+-----+-----+
        DS + 0027H: | BX0 | BX1 | xxx |
                    +-----+-----+-----+
        DS + 002AH: | LX0 | LX1 | LX2 |
                    +-----+-----+-----+
        DS + 002DH: | BX0 | BX1 | xxx |
                    +-----+-----+-----+
        DS + 0030H:         Not
          ...            Currently
        DS + 005BH:         Used
                    +-----------------+
        DS + 005CH: |   Default FCB   |
                    +-----------------+
        DS + 0080H: |  Default Buffer |
                    +-----------------+
        DS + 0100H: | Begin User Data |
                    +-----------------+

where each byte is indexed by 0, 1, and 2, corresponding to  the
standard Intel storage convention of low, middle, and high-order
(most significant) byte, and "xxx" marks unused bytes. LC is the
last  code  group  location  (24-bits), while  BC  is  the  base
paragraph  address  of  the code group (16-bits).  In  the  8080
Model, the low order bytes of the LC (LC0 and LC1) never  exceed
0FFFFH, and the high order byte (LC2) is always zero. It  should
be  noted  that bytes LD0 and LD1 appear in  the  same  relative
positions  of  the base page in both 8-bit  CP/M-80  and  16-bit
CP/M-86, thus easing the program translation task.

LD  and BD provide the last position and paragraph base  of  the
data  group. Note that the last position is one byte  less  than
the  group  length.  The M80 byte is equal to 1  when  the  8080
Memory  Model  is  in  use. LE and BE  provide  the  length  and
paragraph  base of the (optional) extra group, while LS  and  BS
give  the  (optional)  stack group length and  base.  The  bytes
marked  LX  and  BX  correspond to  a  set  of  four  (optional)
independent  groups,  which may be required for  programs  which
execute  using the Compact Model. The initial values  for  these
descriptors  are  derived from the header record in  the  memory
image file, described below.

4.  Memory Image File Format
----------------------------

Similar  to 8-bit CP/M, CP/M-86 loads and executes memory  image
files,  with  the  file type "CMD"  corresponding  to  "command"
files.  The command file results from the GENCMD program,  which
accepts  either  Intel  L-modules, or  Intel  8086  "hex"  files
produced using Intel translators or the Digital Research  ASM-86
assembler. A CMD file begins with a header record created by the
GENCMD  program. The header record is a total of 128 bytes,  and
begins with a sequence of one or more group descriptors of  nine
bytes each, with zero fill to the end of the record. The  format
of each descriptor is shown below.

          8-bit   16-bit     16-bit     16-bit     16-bit
        +------+----------+----------+----------+----------+
        |G-Form| G-Length |  A-Base  |  G-Min   |  G-Max   |
        +------+----------+----------+----------+----------+

where G-Form describes the group form, or has the value zero  if
no  more descriptors follow. If G-Form is non-zero, then the  8-
bit value is decomposed into two fields:

               G-Form:
           4-bit    4-bit
        +---------+--------+
        | x x x x | G-Type |
        +---------+--------+

        G-Type  Group Type
        ------  ----------
          1     Program Code Group
          2     Independent Data Group
          3     Independent Extra Group
          4     Independent Stack Group
          5     Independent Auxiliary Group #1
          6     Independent Auxiliary Group #2
          7     Independent Auxiliary Group #3
          8     Independent Auxiliary Group #4
         9-14   Unused, but Reserved
          15    Escape Code for Additional Types

All  remaining  values  in the group  descriptor  are  given  in
increments of 16-bytes. That is, each value is the high order 16
bits  of  the 20-bit base or length, with an assumed  low  order
nibble  of  zero.  Thus,  allocation  requests  are  always   in
"paragraph"  increments. G-Length gives the actual size  of  the
group.  Given a G-length of 0080H, for example, the size of  the
group is 00800H = 2048 bytes. A-Base defines the base  paragraph
address  for  a  non-relocatable group.  The  group  is  assumed
relocatable  if  A-Base  is 0000H. G-Min and  G-Max  define  the
minimum  and maximum size of the memory area to allocate to  the
group.  Normally,  the value of G-Length, G-Min, and  G-Max  are
identical  for  a group containing object code, but  may  differ
when the group designates a data area. A program which  performs
I/O  processing, for example, may contain a data area  used  for
buffers where the size of the allocated area may vary, depending
upon available storage.

The  particular  memory  model used by a  transient  program  is
determined  implicitly by the group descriptors. The 8080  Model
occurs when only a code group is included, since no  independent
data  group  is  named.  The  Small  Model  is  implied  by  the
occurrence  of a code group and a data group, but no  additional
group descriptors. Otherwise, the Compact Model is implied.

5.  Program Initialization
--------------------------

Following  program  load, the CCP transfers control  through  an
8086  Far  Call. The Stack Segment register (SS) is set  to  the
base paragraph address of CP/M-86, while the Stack Pointer  (SP)
references  the current base of the CCP stack. Similar to  8-bit
CP/M,  the  transient program must save these  registers  before
switching to a local stack if return to the CCP is  anticipated.
In this case, the transient program must reinstate the SS and SP
registers,  and execute an 8086 Far Return.  Alternatively,  the
program  may  return control to CP/M-86 through a  call  to  the
BDOS,  using  function code 0, as described below.  The  initial
values of the remaining segment registers upon program load  are
determined by the memory model.

When  the  8080 Model is used, the Code Segment  register  (CS),
Data Segment register (DS), and Extra Segment register (ES)  are
set  to the base of the transient program area. The  Instruction
Pointer (IP) is initialized to 0100H. The reserved locations and
initial values for maximum memory size, default FCB, and default
buffer in the base page are in the same relative position as  8-
bit  CP/M.  In particular, the base page is a part of  both  the
code and data space, with the size of memory provided at address
DS+0006H.

In  the case of the Small Model, the CS register is set  to  the
base  of  the  code  area, while the DS  and  ES  registers  are
initialized  to  the base paragraph address of  the  data  area.
Again,  the base page addressed by DS and ES correspond  closely
to 8-bit CP/M, in order to simplify translation to CP/M-86. Note
that  the only essential difference between the 8080  Model  and
the Small Model is that code and data must be separate, which is
often  the case with well-structured 8-bit programs.  The  Small
Model  has  the advantage that the code and data  space  is  not
limited to a total of 64K bytes.

Finally,  in the case of the Compact Model, the CS, DS,  and  ES
registers are initialized to the base paragraph addresses of the
code,   data,  and  extra  groups,  respectively.  It   is   the
responsibility  of the transient program to manage  the  various
segment  registers from the base page values filled-in when  the
program is loaded by the CCP if any group exceeds 64K bytes,  or
if auxiliary groups are included.

6.  BDOS Function Calls
-----------------------

Programmatic interface to CP/M-86 corresponds to 8-bit CP/M with
only  a  few  exceptions, thus allowing  simple  translation  of
existing 8-bit programs to the 8086 environment.

The  BDOS  is entered using 8086 interrupt 224,  which  overlaps
that  of Intel's RMX-86 monitor. Register values upon  entry  to
the BDOS are given below:

        Function Code   CX
        Byte Parameter  DL
        Word Parameter  DX

Addresses  passed  to the BIOS are offset from the  DS  register
which  is positioned at the base of the CP/M-86 data area.  Note
that  the total code and data space required by the  CCP,  BDOS,
and  BIOS is considerably less than 64K, and thus CS and DS  are
placed at the first address of the region occupied by CP/M.

Register  content  is not preserved through BDOS  calls.  Values
resulting  from  BDOS  calls  are  returned  in  the   following
registers:

        Byte Value              AL
        Word Value              AX and BX
        Double Word Offset      BX
        Segment Address         ES

A  number of additional function codes are provided in  CP/M-86.
Note  also that function code (0) has a single  parameter  value
under CP/M-86.

        (0) System Reset (Warm Start)
        Restores CP/M-86 to the reset state, with a standard CCP
        prompt.  The parameter value in the DL register has  two
        possible values: if DL = 00H, then the currently  active
        program   is  terminated  (equivalent   to   Control-C).
        Otherwise,  DL  must be 01H, in which case  the  program
        remains  in  memory,  and the  memory  allocation  state
        remains  unchanged. (If DL is neither 00H or 01H, it  is
        currently treated as if it were 00H.)

        (50) Direct BIOS Call
        Transfers control through the BDOS to the BIOS, with the
        DX  addressing  a five-byte memory area  containing  the
        BIOS call parameters:

                  8-bit    16-bit       16-bit
                +------+------------+------------+
                | Func | Value (CX) | Value (DX) |
                +------+------------+------------+

        where  Func  is the BIOS function  number,  starting  at
        zero,  and  Value  (CX) and Value (DX)  are  the  16-bit
        values which would normally be passed directly in the CX
        and  DX  registers  with the BIOS call. The  CX  and  DX
        values  are  loaded into the 8086 registers  before  the
        BIOS call is initiated.

        (51) Set DMA Segment Base
        Sets the base register for subsequent DMA transfers. The
        word  parameter  gives  the  paragraph  address  of  the
        referenced  segment.  Note that,  upon  initial  program
        loading, the default segment base is set to DS, and  the
        DMA offset is set to 0080H, which provides access to the
        base page.

        (52) Get DMA Base
        Returns  the  double  word value  corresponding  to  the
        current DMA segment base and offset.

Several  of  the codes given below reference  a  Memory  Control
Block  (MCB), defined in the transient program, which takes  the
form:

                16-bit     16-bit    8-bit
             +----------+----------+-------+
        MCB: |  M-Base  | M-Length | M-Ext |
             +----------+----------+-------+

where  M-Base  and M-Length are either input  or  output  values
expressed  in 16-byte paragraph units, and M-Ext is  a  returned
byte  value, as defined with each function below. Note  that  an
error condition is normally flagged with a 0FFH returned  value,
in order to match the file error conventions of CP/M.

        (53) Get Max Mem
        Allocate  the  largest contiguous area of  memory.  Upon
        entry, DX addresses a MCB which will be filled-in by the
        BDOS. If successful, M-Base is set to the base paragraph
        address  of  the  allocated area, and  M-Length  is  the
        paragraph  length  of the allocation. AL has  the  value
        0FFH  upon  return  if  the  requested  memory  is   not
        available, and 00H if the request was successful.  M-Ext
        is   set  to  1  if  there  is  additional  memory   for
        allocation, and 0 if no additional memory is available.

        (54) Get Abs Max
        Allocate  the  largest  contiguous memory  area  at  the
        absolute  address given by M-Base. Returned  values  are
        the same as those of function (53).

        (55) Get Mem
        Allocate a memory area according to the MCB addressed by
        DX.  In  this  case,  the  allocation  request  size  is
        obtained from M-Length on input. The resulting values of
        the MCB fields are identical to function (53).

        (56) Get Abs Mem
        Allocate memory at the absolute address given by M-Base,
        for  the length given by M-Length. The resulting  values
        are identical to function (53).

        (57) Free Mem
        Release  the memory area of length M-Length at  location
        M-Base given in the MCB addressed by DX.

        (58) Free All
        Release all memory in the CP/M-86 environment  (normally
        used only by the CCP upon initialization).

        (59) Program Load
        Load  the  program  in the file  described  by  the  FCB
        addressed  by DX. AX has the value 0000H if the  program
        load was unsuccessful. Otherwise, AX and BX both contain
        the paragraph address of the base page belonging to  the
        loaded program. Note that, upon program load at the  CCP
        level,  the default paragraph address is initialized  to
        the base page of the loaded program, and the default DMA
        address  is initialized to offset 0080H. Note,  however,
        that this is a function of the CCP, and thus a  function
        59 does not initialize these registers. In this case, it
        is  the  responsibility of the  program  which  executes
        function 59 to first execute function 51 to set the  DMA
        base, and then initialize the DS register before passing
        control to the loaded program.

In addition to these functions, two specific differences between
8-bit CP/M and CP/M-86 exist. First, the IOBYTE function is only
accessible  through  the BDOS, as described in  the  8-bit  CP/M
documentation.  Second,  Direct  BIOS calls  are  provided  only
through the BDOS.

7.  BIOS Interface
------------------

The  interface to the CP/M-86 BIOS is identical to  8-bit  CP/M,
with  the addition of four jump vector elements. The  BIOS  jump
vector  consists of a sequence of 3-byte 8086 Near Jumps to  the
individual  subroutines.  The additional BIOS entry  points  are
listed  below,  and  immediately  follow  the  SECTRAN   (Sector
Translate) entry point defined in 8-bit CP/M version 2:

        JMP     SETDMAB         ; Set DMA Base segment address
        JMP     GETSEGT         ; Return address of SEGment Table
        JMP     GETIOB          ; Get I/O Byte
        JMP     SETIOB          ; Set I/O Byte

Entry points receive their first parameter in CX, and (optional)
second parameter in DX. Values are returned as described in  the
BDOS interface, above.

SETDMAB  (Set  DMA  Base) sets the base  paragraph  address  for
subsequent DMA operations.

The  GETSEGT  returns  the offset to  the  BIOS-resident  Memory
Region Table (MRT). The Memory Region Table has the form:

               8-bit
             +-------+
        MRT: | R-Cnt |
             +---------------+---------------+
          0: |     R-Base    |    R-Length   |
             +---------------+---------------+
          1: |     R-Base    |    R-Length   |
             +---------------+---------------+
                            ...
             +---------------+---------------+
          n: |     R-Base    |    R-Length   |
             +---------------+---------------+
                   16-bit         16-bit

where R-Cnt is the number of memory region descriptors (equal to
n+1  in the above diagram), while R-Base and R-Length  give  the
paragraph base and length of each physically contiguous area  of
memory,  not including the interrupt vector addresses  (0-3FFH),
or  the area of memory where CP/M-86 resides. If all  memory  is
physically  contiguous, R-Cnt = 1 and n = 0. In this  case,  the
single region descriptor normally addresses the first  paragraph
beyond  the  last BIOS address, with an  R-Length  which  allows
access to the highest paragraph address in the region.

The GETIOB and SETIOB entry points return and change the IOBYTE,
as defined in 8-bit CP/M. The IOBYTE value itself is  maintained
in the BIOS.

EOF