SID86UG.WS4     ("SID-86 User's Guide" 2nd Ed. for CP/M-86)
-----------

(Retyped by Emmanuel ROCHE. Posted to comp.os.cpm.amethyst by
Roche on 18 Apr 2005.)

"SID-86 User's Guide"
First Edition: March 1982       (With Q, SR, and Z commands added by me.)
Second Edition: August 1982     (Code-macros are still not documented...)

(Pages i and ii missing.)


Table of Contents
-----------------

(To be done...)


Section 1: SID-86 Operation
---------------------------

SID-86  is a powerful symbolic debugger designed for use with the CP/M-86 and
MP/M-86 operating systems. It expands on the features of the standard CP/M-86
debugger,  DDT-86,  allowing users to test and debug  programs interactively.
SID-86  includes  symbolic  assembly and  disassembly,  expressions involving
hexadecimal,  decimal, ASCII, and symbolic values, permanent breakpoints with
pass  counts,  and trace without call. You should be familiar with  the Intel
8086  processor,  ASM-86  and  the CP/M-86 or  MP/M-86  operating  system, as
described in the "CP/M-86 Operating System System Guide" or "MP/M-86 Operating
System System Guide".


1.1 Invoking SID-86
-------------------

Invoke SID-86 by entering one of the following commands:

        (a) SID86
        (b) SID86 filename
        (c) SID86 filename {,filename...}
        (d) SID86 * filename {,filename...}

Form  (a)  simply  loads and executes SID-86.  After  displaying  its sign-on
message and prompt character, #, SID-86 is ready to accept your commands. Form
(b) is similar to form (a), except that, after SID-86 is loaded, it loads the
file specified by "filename". If the filetype is omitted from "filename", CMD
is assumed. Note that SID-86 cannot load a file of type H86.

Form (c) is similar to form (b) but, once the program is loaded, SID-86 loads
the other files in the command line into its symbol table. Form (d) is similar
to form (c), except that no program is loaded, only symbol files.

Forms (b), (c), and (d) are analogous to the command sequences:

        A>SID86
        SID86 x.x
        #Efilename

        A>SID86
        SID86 x.x
        #Efilename {,filename...}

        A>SID86
        SID86 x.x
        #E* filename {,filename...}

At this point, the program that was loaded using form (b) or (c) is ready for
execution.  (See Section 3.4, "The E Command", for a complete  description of
file loading.)


1.2 SID-86 Command Conventions
------------------------------

When  SID-86  is ready to accept a command, it prompts you with a  pound sign
("#").  In  response,  you can type a command line, or a  Ctrl-C  to  end the
debugging  session  (see  Section  1.4). A command line  can  have  up  to 64
characters, and must be terminated with a carriage return. While entering the
command, use standard CP/M-86 line-editing functions (Ctrl-X, Ctrl-H, Ctrl-R,
etc) to correct typing errors. SID-86 does not process the command line until
a carriage return is entered.

The first character of each command line determines the command action. Table
1-1  summarizes SID-86 commands. SID-86 commands are defined  individually in
Section 3.

        Table 1-1. SID-86 Command Summary
        ---------------------------------

        Command Action
        ------- ----------------------------------
           A    Enter assembly language statements
           B    Compare blocks of memory
           D    Display memory in hexadecimal and ASCII
           E    Load program and symbols for execution
           F    Fill memory block with a constant
           G    Begin execution with optional breakpoints
           H    Hexadecimal arithmetic
           I    Set up file control block and command tail
           L    List memory using 8086 mnemonics
           M    Move memory blocks
           P    Set, clear, display pass points
           Q    Query I/O ports
           R    Read disk file into memory
           S    Set memory to new values
           SR   SeaRch pattern in memory
           T    Trace program execution
           U    Untraced program monitoring
           V    Show memory layout of disk file read
           W    Write contents of memory block to disk
           X    Examine or modify CPU state
           Z    Examine 8087 co-processor

The  command character can be followed by one or more arguments, which can be
symbolic  expressions,  filenames,  or other  information,  depending  on the
command.  Arguments  are  separated from each other by commas  or  spaces.No
spaces are allowed between the command character and the first argument. Note
that,  if the first character of a SID-86 command line is a  semicolon (";"),
the  entire line is treated as a comment and ignored. Several commands (G, P,
S,  T,  and U) can be preceded by a minus sign. The effect of the  minus sign
varies  between  commands.  (Section 3, "SID-86  Commands",  provides  a full
explanation of the effect of the minus sign on individual commands.)


1.3 Specifying a 20-Bit Address
-------------------------------

Most SID-86 commands require one or more address as operands. Because the 8086
can address up to 1 megabyte of memory, addresses must be 20-bit values. Enter
a 20-bit address as follows:

        ssss:oooo

where "ssss" represents an optional 16-bit segment number and "oooo" is a 16-
bit  offset.  SID-86  combines these values to produce a  20-bit  address, as
follows:

          ssss
        +  oooo
        -------
          eeeee

The  segment value, ssss, is optional. If you omit the segment  value, 
uses  a default value appropriate to the command being executed, as described
in Section 3.4, "The E Command".


1.4 Terminating SID-86
----------------------

Terminate SID-86 by typing a Ctrl-C in response to the pound sign prompt. This
returns  control  to the CCP. Note that CP/M-86 or MP/M-86 does not  have the
SAVE  facility  found in CP/M for 8-bit machines. Thus, if SID-86 is  used to
patch  a file, write the file to disk using the W command before exiting SID-
86.


1.5 SID-86 Operation with Interrupts
------------------------------------

SID-86 operates in systems with interrupts enabled or disabled, and preserves
the  interrupt state of the program being executed under SID-86.  When SID-86
controls the CPU, either when initially invoked or when regaining control from
the  program being tested, the condition of the interrupt flag is the same as
it  was  when  SID-86 was invoked, except for a  few  critical  regions where
interrupts  are  disabled. While the program being tested has control  of the
CPU,  the  user's  CPU  state, which can be  displayed  with  the  X command,
determines the state of the interrupt flag.


Section 2: SID-86 Expressions
-----------------------------

An  important facility of SID-86 is the ability to reference absolute machine
addresses through expressions. Expressions can involve names obtained from the
program  under  test  that are included in the SYM file  produced  by ASM-86.
Expressions  can  also consist of literal values in hexadecimal,  decimal, or
ASCII  character string form. You can then combine these values  with various
operators,  to provide access to subscripted and indirectly-addressed data or
program areas. This section describes expressions, so that you can incorporate
them  as command parameters in the individual command forms that  follow this
section.


2.1 Literal Hexadecimal Numbers
-------------------------------

SID-86  normally  accepts  and  displays  values  in  hexadecimal.  The valid
hexadecimal  digits  consist  of  the  decimal digits  0  through  9  and the
hexadecimal  digits A, B, C, D, E, and F, corresponding to the decimal values
10 through 15, respectively.

A  literal  hexadecimal number in SID-86 consists of one  or  more contiguous
hexadecimal  digits. If you type four digits, then the leftmost digit is most
significant,  while  the rightmost digit is least significant. If  the number
contains  more than four digits, the rightmost four are taken as significant,
and  the remaining leftmost digits are discarded. The examples below show the
corresponding hexadecimal and decimal values for the given input values.

        Input Value     Hexadecimal     Decimal
        -----------     -----------     -------
               1           0001             1
             100           0100           256
            fffe           FFFE         65534
           10000           0000             0
           38001           8001         32769


2.2 Literal Decimal Numbers
---------------------------

Enter decimal numbers by preceding the number with the # symbol. In this case,
the number that follows must consist of one or more decimal digits (0 through
9)  with  the most significant digit on the left, and  the  least significant
digit  on the right. Decimal values are padded or truncated according  to the
rules  of hexadecimal numbers, as described above, by converting  the decimal
number to the equivalent hexadecimal value.

The  input  values shown to the left below produce  the  internal hexadecimal
values shown to the right below:

        Input Value     Hexadecimal
        -----------     -----------
              #9           0009
             #10           000A
            #256           0100
          #65535           FFFF
          #65545           0009


2.3 Literal Character Values
----------------------------

SID-86 accepts one or two graphic ASCII characters enclosed in apostrophes as
literal  values in expressions. Characters remain as typed within  the paired
apostrophes  (i.e.,  no case translation occurs) with the  leftmost character
treated as the most significant, and the rightmost character treated as least
significant. Character strings of length one are padded on the left with 
Strings of length greater than zero are not allowed in expressions, except as
described in the S command.

Note that the enclosing apostrophes are not included in the character string,
nor  are they included in the character count, with one exception: a  pair of
contiguous  apostrophes is reduced to a single apostrophe and included in the
string as a normal graphic character.

The  strings shown to the left below produce the hexadecimal values  shown to
the  right below. (For these examples, note that upper-case ASCII alphabetics
begin at the encoded hexadecimal value 41; lower-case alphabetics begin at 61;
a space is hexadecimal 20, and an apostrophe is encoded as hexadecimal 27.)

        Input String    Hexadecimal
        ------------    -----------
              'A'          0041
             'AB'          4142
             'aA'          6141
             ''''          0027
           ''''''          2727
             ' A'          2041
             'A '          4120


2.4 Register Values
-------------------

You  can use the contents of registers in the CPU state of the  program under
test  in  expressions. Simply use the register name wherever  a  number would
normally  be valid. For example, if you know that, at a certain point  in the
program, the BX register points to a data area you want to see, the command

        DBX

displays the desired area of memory.

Note  that,  when assembling 8086 instructions using the A  command, register
names are treated differently than in other expressions. In particular, use of
a  register  name in an assembly language statement entered in the  A command
refers to the name of a register, and not its contents.


2.5 Stack References
--------------------

Elements in the stack can be included in expressions. A caret ("^") refers to
the  16-bit  value  at  the top of the stack (pointed to  by  the  SS  and SP
registers  in the user's CPU state). A sequence of n carets refer to  the nth
16-bit  value  on the stack. You can use this feature to set a  breakpoint on
return from a subroutine, when all that is known is that the return address is
on the stack, even though the actual value is not known. The commands

        G,^
        G,^^:^

set breakpoints on return from near and far subroutines, respectively.


2.6 Symbolic References
-----------------------

Given  that a symbol table is present during a SID-86 debugging  session, you
can reference values associated with symbols through the following three forms
of a symbol reference:

        (a) .s
        (b) @s
        (c) =s

where  "s" represents a sequence of one to thirty-one characters that match a
symbol in the table.

Form (a) produces the 16-bit value corresponding to the symbol "s" (i.e., the
value  associated with the symbol in the table). Form (b) produces the 16-bit
value  contained  in  the two memory locations given by  .s,  while  form (c)
results  in the 8-bit value at .s in memory. Note that forms (b) and  (c) use
the contents of the DS register as the segment component when fetching the 16-
bit  or 8-bit contents of memory. Suppose, for example, that the input symbol
table contains two symbols, and appears as follows:

        0100 GAMMA      0102 DELTA

Further,  suppose that memory starting at 0100 in the segment referred  to by
the DS register contains the following byte data values:

        0100: 02 3E 4D 22

Based  upon this symbol table and these memory values, the  symbol references
shown  to  the left below produce the hexadecimal values shown  to  the right
below.  Recall  that  16-bit  8086 memory values are  stored  with  the least
significant byte first, and thus the word values at 0100 and 0102 are 3E02 and
224D, respectively.

        Symbol Reference        Hexadecimal
        ----------------        -----------
            .GAMMA                 0100
            .DELTA                 0102
            @GAMMA                 3E02
            @DELTA                 224D
            =GAMMA                 0002
            =DELTA                 004D


2.7 Qualified Symbols
---------------------

Duplicate  symbols can occur in the symbol table, due to separately assembled
or  compiled  modules  that  independently use the  same  name  for different
subroutines  or data areas. Further, block structured languages  allow nested
name definitions that are identical, but non-conflicting. Thus, SID-86 allows
reference to qualified symbols that take the form:

        S1/S2/.../Sn

where  "S1"  through  "Sn" represents symbols that are present  in  the table
during a particular session.

SID-86 always searches the symbol table from the first to last symbol, in the
order  the symbols appear in the symbol file. For a qualified  symbol, SID-86
begins by matching the first S1 symbol, then scans for a match with symbol S2,
continuing  until symbol Sn is matched. If this search and match procedure 
not  successful, SID-86 prints the "?" response to the console.  Suppose, for
example, that the symbol table appears in the symbol file as follows:

        0100 A  0300 B  0200 A  3E00 C  20F0 A  0102 A

with  memory  initialized as shown in the previous section. In  the following
example,  the  unqualified and qualified symbol references shown to  the left
produce the hexadecimal values shown to the right.

        Symbol Reference        Hexadecimal
        ----------------        -----------
            .A                     0100
            @A                     3E02
            .A/A                   0200
            .C/A/A                 0102
            =C/A/A                 004D
            .B/A/A                 20F0


2.8 Operators in Expressions
----------------------------

Literal numbers, strings, and symbol references can be combined into symbolic
expressions using unary and binary "+" and "-" operators. The entire sequence
of  numbers, symbols, and operators must be written without  embedded blanks.
Further, the sequence is evaluated from left to right, producing a four-digit
hexadecimal  value at each step in the evaluation. Overflow and underflow are
ignored  as  the  evaluation proceeds. The final  value  becomes  the command
parameter,  whose  interpretation depends upon the particular  commend letter
that precedes it.

When  placed  between  two  operands, the  "+"  indicates  "addition"  to the
previously  accumulated  value. The sum becomes the new accumulated  value to
this point in the evaluation.

The  "-"  symbol  causes  SID-86 to subtract  the  literal  number  or symbol
reference  from  the  16-bit  value  accumulated  thus  far  in  the symbolic
expression.  If  the  expression begins with a minus sign,  then  the initial
accumulated value is taken as zero. That is,

        -x

is computed as

        0-x

where  "x"  is  any  valid symbolic expression.  For  example,  the following
command:

        DFF00-200,-#512

is equivalent to the simple command:

        DFD00,FE00

In  commands  that specify a range of addresses (B, D, L, F, M,  and  W), the
ending  address of the range can be indicated as an offset from  the starting
address.  To do this, precede the desired offset by a plus sign. For example,
the command

        D121,+7

displays  the memory from address 121 to 128 (121 + 7). Use of the unary plus
operator at other times is not allowed.


2.9 Sample Symbolic Expressions
-------------------------------

The  formulation of SID-86 symbolic expressions is most often closely related
to the program structures in the program under test. Suppose you want to debug
a sorting program that contains the data items listed below:

        LIST:   names  the  base of a table of byte values to  sort, assuming
                there  are  no  more than 255 elements,  denoted  by LIST(0),
                LIST(1), ..., LIST(254).

           N:   is  a byte variable that gives the actual number of  items in
                LIST, where the value of N is less than 256. The items to sort
                are stored in LIST(0) through LIST(N-1).

           I:   is the byte subscript that indicates the next item to compare
                in  the sorting process. LIST(I) is the next item to place in
                sequence, where I is in the range 0 through N-1.

Given these data areas, the command

        D.LIST,+#254

displays the entire area reserved for sorting:

        LIST(0), LIST(1), ..., LIST(254)

The command

        D.LIST,+=i

displays the LIST vector up to and including the next item to sort:

        LIST(0), LIST(1), ..., LIST(I)

The command

        D.LIST+=I,+0

displays only LIST(I). Finally, the command

        D.LIST,+=N-1

displays only the area of LIST that holds active items to sort:

        LIST(0), LIST(1), ..., LIST(N-1)


Section 3: SID-86 Commands
--------------------------

This section defines SID-86 commands and their arguments. SID-86 commands give
you  control of program execution, and allow you to display and modify system
memory and the CPU state.


3.1 The A (Assemble) Command
----------------------------

The  A command assembles Intel 8086 mnemonics directly into memory.  The form
is:

        As

where "s" is the 20-bit address where assembly starts. SID-86 responds to the
A  command  by displaying the address of the memory  location  where assembly
begins. At this point, you enter assembly language statements as described in
Section  4  on Assembly Language Syntax. When a statement is  entered, SID-86
converts it to binary, places the value(s) in memory, and displays the address
of the next available memory location. This process continues until you enter
a blank line or a line containing only a period (".").

SID-86 responds to invalid statements by displaying a question mark ("?") and
redisplaying the current assembly address.

Note  that,  wherever  a  numeric  value is  valid  in  an  assembly language
statement,  an  expression  can be entered. There is  one  difference between
expressions  in assembly language statements and those appearing elsewhere in
SID-86: under the A command, references to registers refer to the names of the
registers, while elsewhere they refer to the contents of the registers. Under
the  A command, there is no way to reference the contents of a register in an
expression.

The following are examples of the A command.

        #A213                   Assemble at offset 0213.
        nnnn:0213 mov ax,#128   Set AX register to decimal 128.
        nnnn:0216 push ax       Push AX register on stack.
        nnnn:0217 call .proc1   Call  procedure whose address is the value of
                                the symbol PROC1.

        nnnn:021A test byte [.i/i], 80

Test  the most significant bit of the byte whose address is the value  of the
second occurrence of the symbol I.

        nnnn:021E jz .done      Jump  if Zero flag set to the  location whose
                                address is the value of the symbol DONE.

        nnnn:0220 mov al,[.array+4]

Move the contents of the memory byte whose address is the value of the symbol
ARRAY plus 4 to the AL register.


3.2 The B (Block Compare) Command
---------------------------------

The B command compares two blocks of memory, and displays any discrepancies at
the screen. The form is:

        Bs1,f1,s2

where "s1" is the 20-bit address of the start of the first block; "f1" is the
offset of the final byte of the first block; and "s2" is the 20-bit address of
the start of the second block. If the segment is not specified in s2, the same
value is used that was used for s1.

Any differences in the two blocks are displayed at the screen in the form:

        a1 b1 a2 b2

where the "a1" and the "a2" are the adresses in the blocks; "b1" and "b2" are
the  values at the indicated addresses. If no differences are  displayed, the
blocks are identical.

The following are examples of the B command.

        #B40:0,1FF,60:0

Compares 200h bytes starting at 40:0 with the block starting at 60:0.

        #Bes:.array1,+ff,.array2

Compares 256 bytes starting at offset ARRAY1 in the Extra Segment with ARRAY2
in the Extra Segment.


3.3 The D (Display) Command
---------------------------

The  D command displays the contents of memory as8-bit or  16-bit hexadecimal
values and in ASCII. The forms are:

        (a) D
        (b) Ds
        (c) Ds,f
        (d) DW
        (e) DWs
        (f) DWs,f

where  "s" is the 20-bit address where the display starts, and "f" is the 16-
bit offset within the segment specified in "s" where the display finishes.
Memory is displayed on one or more display lines. Each display line shows the
values  of up to 16 memory locations. For the first three forms,  the display
line appears as follows:

        ssss:oooo bb bb ... bb cc...c

where  "ssss" is the segment being displayed, and "oooo" is the offset within
segment  "ssss".  The bb's represent the contents of the memory  locations in
hexadecimal,  and the c's represent the contents of memory in ASCII. A period
(".") represents any non-graphic ASCII character.

In  response  to  form (a), SID-86 displays memory from  the  current display
address for 12 display lines. The response to form (b) is similar to form (a),
except  that the display address is first set to the 20-bit address "s". Form
(c)  displays the memory block between locations "s" and "f". The  next three
forms are analogous to the first three, except that the contents of memory are
displayed as 16-bit values, rather than 8-bit values, as shown below:

        ssss:oooo wwww wwww ... wwww cccc...cc

During a long display, you can abort the D command by typing any character at
the console.

The following are examples of the D command.

        #DF00,F23               Display memory bytes from offset 0F00h through
                                0F23h in the current Data Segment.

        #D.array+=i,+#10        Display  11 bytes starting at the location of
                                ARRAY(I).

        #DW#128,#255            Displays   memory  words  from  offset 0080h
                                through 00FFh.


3.4 The E (Load Program, Symbols for Execution) Command
-------------------------------------------------------

The E command loads a file into memory so that a subsequent G, T, or U command
can  begin program execution, and allows one or more symbol table files to be
loaded. The E command takes the forms:

        (a) E <filename>
        (b) E <filename> <symbol filename> {,<symbol filename>...}
        (c) E * <symbol filename> {,<symbol filename>...}
        (d) E

Form  (a) loads the file by the name <filename> using the BDOS load function.
The file is assumed to be in the CMD file format, as described in the "CP/M-86
System  Guide". If no filetype is specified, CMD is assumed. The  contents of
the  CS, DS, ES, and IP registers are altered according to the information in
the  header record of the CMD file loaded. When the load is  complete, SID-86
displays  the start and end addresses of each segment in the file loaded. Use
the V command to redisplay this information at a later time.

Form  (b) loads the file <filename> as described above, and then loads one or
more  symbol table files. If the filetype is omitted from a  symbol filename,
SYM is assumed. SID-86 displays the message:

        SYMBOLS

when  it begins loading the symbol file(s). If SID-86 detects an  invalid hex
digit  or  an  invalid symbol name, it displays an  error  message  and stops
loading the symbol file. The symbols loaded up to the time the error occurred
can  be displayed with the H command, to determine the exact location  of the
error  in the SYM file. A maximum of 64K bytes is available for  symbol table
storage.

While SID-86 allows symbol files to be loaded with separate E commands, each E
command  requests  another  memory  allocation  from  the  operating system.
Therefore, if you are loading more than one symbol table file, you should load
all the files with a single E command, using form (b) or (c).

Form (c) does not load a program, but simply loads the indicated symbol table
file(s).

Form (d) releases all memory allocations made from SID-86, without loading any
files.

When loading a program file with the E command, SID-86 releases any blocks of
memory allocated by any previous E or R commands or by programs executed under
SID-86.  Thus, only one file at a time can be loaded for execution,  and that
file should be loaded before any symbol tables are read.

SID-86  issues  an  error  message if a file does  not  exists  or  cannot be
successfully loaded in the available memory.

The format of the symbol table file is that produced by ASM-86, as follows:

        nnnn symbol1    nnnn symbol2    ...
        ...
        ...

where  "nnnn" is a four-digit hexadecimal number, and spaces,  tabs, carriage
returns, and line feeds can serve as delimiters between hex values and symbol
names. Symbol names can be up to thirty-one characters in length.

The following are examples of the E command.

        #Etest                  Load file TEST.CMD.

        #Etest.cmd test.sym     Load  file  TEST.CMD  and  symbol  table file
                                TEST.SYM.

        #Etest test io format   Load  file  TEST.CMD and  symbol  table files
                                TEST.SYM, IO.SYM, and FORMAT.SYM.

        #E* test1               Load only the symbol table file TEST1.SYM.


3.5 The F (Fill) Command
------------------------

The F command fills an area of memory with a byte or word constant. The forms
are:

        (a) Fs,f,b
        (b) FWs,f,w

where "s" is a 20-bit starting address of the block to be filled, and "f" is a
16-bit  offset of the final byte of the block within the segment specified in
"s".

In  response to form (a), SID-86 stores the 8-bit value "b" in  locations "s"
through  "f".  In  form (b), the 16-bit value "w" is stored  in  location "s"
through "f" in standard form, low 8-bits first followed by high 8-bits.

If  "s"  is  greater than "f" or the value "b" is  greater  than  255, SID-86
responds  with  a question mark ("?"). SID-86 issues an error message  if the
value stored in memory cannot be read back successfully, indicating faulty or
non-existant RAM at the location indicated.

The following are examples of the F command.

        #F100,13F,0             Fill memory from 0100h to 013Fh with 00h.

        #F.array,+255,ff        Fill the 256-byte block starting at ARRAY with
                                the constant 0FFh.


3.6 The G (Go) Command
----------------------

The  G command transfers control to the program being tested,  and optionally
sets one or two breakpoints. The forms are:

        (a) G
        (b) G,b1
        (c) G,b1,b2
        (d) Gs
        (e) Gs,b1
        (f) Gs,b1,b2
        (g) -G (with forms "a" through "f")

where  "s" is a 20-bit address where program execution is to start,  and "b1"
and "b2" are 20-bit addresses of breakpoints. If no segment value is supplied
for  any of these three addresses, the segment value defaults to the contents
of the CS register.

In forms (a), (b), and (c), no starting address is supplied, so SID-86 derives
the 20-bit address from the CS and IP registers. Form (a) transfers control to
your program without setting any breakpoints. Form (b) and (c) set one and two
breakpoints, respectively, before passing control to your program. Forms (d),
(e),  and  (f) are analogous to (a), (b), and (c), except that the CS  and IP
registers are first set to "s".

The  forms  in  (g)  are  analogous to forms  (a)  through  (f),  except that
intermediate pass points displays are suppressed.

Once  control has been transferred to the program under test, it  executes in
real-time  until  a breakpoint is encountered. At this point,  SID-86 regains
control,  clears  the  breakpoints set by the G  command,  and  indicates 
address  at  which  execution of the program under  test  was  interrupted as
follows:

        *ssss:oooo .symbol

"ssss"  corresponds  to the CS, "oooo" corresponds to the IP where  the break
occurred, and ".symbol" is the symbol whose value is equal to "oooo", if such
a symbol exists. When a breakpoint returns control to SID-86, the instruction
at the breakpoint address has not yet been executed.

The following are examples of the G command.

        #G              Begin program execution at address given by CS and IP
                        registers, with no breakpoints set.

        #G.start,.error Begin  program  execution at label START in  the code
                        segment, setting a breakpoint at label ERROR.

        #G,.error,^     Continue program execution at address given by CS and
                        IP  registers, with breakpoints at label ERROR and at
                        the  address  at  the top of  the  stack  (the return
                        address of the procedure being executed).

        #-G,34F         Begin   execution   with  a   breakpoint   at 034Fh,
                        suppressing intermediate pass point display.


3.7 The H (Hexadecimal Math) Command
------------------------------------

The H command provides several useful arithmetic functions. The forms are:

        (a) Ha,b
        (b) Ha
        (c) H

Form  (a) computes the sum (ssss), difference (ddd), product  (pppppppp), and
quotient  (qqqq) with the remainder (rrrr) of two 16-bit values.  The results
are displayed in hexadecimal as follows:

        + ssss - dddd * pppppppp / qqqq (rrrr)

Underflow and overflow are ignored in addition and subtraction.

Form  (b)  displays the value of the expression "a" in  hexadecimal, decimal,
ASCII (if the value has a graphic ASCII equivalent), and symbolic (if a symbol
exists with a value equal to the value of the expression) form as shown:

        hhhh #ddddd 'c' .s

Form  (c)  displays the symbols currently loaded in the SID-86  symbol table.
Each symbol is displayed in the form:

        nnnn <symbol name>

You can abort the display by pressing any key at the console.

The following are examples of the H command.

        #H              List all symbols and values loaded with E command(s).

        #H.open         Show the value of the symbol OPEN in hex and decimal.

        #H@index        Show the word contents of the memory location at INDEX
                        in hex and decimal.

        #H5C28,80       Show  sum, difference, product, and quotient of 5C28h
                        and 0080h.


3.8 The I (Input Command Tail) Command
--------------------------------------

The  I command prepares a file control block (FCB) and command tail buffer in
SID-86's base page, and copies this information into the base page of the last
file loaded with the E command. The command takes the following form:

        I<command tail>

where  <command tail> is a character string that usually contains one or more
filenames. The first filename is parsed into the default file control block at
005Ch.  The  optional second filename is parsed into the second  part  of the
default  file  control block beginning at 006Ch. The  characters  in <command
tail> are also copied into the default command buffer at 0080h. The length of
<command tail> is stored at 0080h, followed by the character string 
terminated
with a binary zero.

If  a file has been loaded with the E command, SID-86 copies the file control
block and command buffer from the base page of SID-86 to the base page of the
program  loaded. The location of SID-86's base page can be obtained  from the
16-bit  value  at  location 0:6. The location of the base page  of  a program
loaded with the E command is the value displayed for DS upon completion of the
program load.

The following are examples of the I command.

        #Ifile1.cmd

Set  up  a  file control block at 005Ch for the file FILE1.CMD,  and  put the
string  "FILE1.CMD"  in the buffer at 0080h (in the Data Segment of  the last
file loaded with an E command).

        #Ia:file1 b:file2 c:file3 $px

Set  up  file  control blocks at 005Ch and 006Ch for  the  files  A:FILE1 and
B:FILE2, and copy the string following the "I" into the buffer at 0080h.


3.9 The L (List) Command
------------------------

The  L  command lists the contents of memory in assembly language.  The forms
are:

        (a) L
        (b) Ls
        (c) Ls,f
        (d) -L
        (e) -Ls
        (f) -Ls,f

where  "s"  is  a 20-bit address where the list starts, and "f"  is  a 16-bit
offset within the segment specified in "s" where the list finishes.

Each disassembled instruction is in the following form:

        label:
        ssss:oooo <prefixes> opcode <operands> <.symbol> <=memory value>

where "label" is the symbol whose value is equal to the offset "oooo", if such
a  symbol exists; <prefixes> are segment override, lock and  repeat prefixes;
"opcode" is the mnemonic for the instruction, <operands> field contains 0, 1,
or  2  operands, as required by the instruction, and <symbol>  is  the symbol
whose value is equal to the numeric operand, if there is one and such a symbol
exists.  If the instruction references a memory location, the contents of the
location are displayed in the <memory value> field as a byte, word, or double
word, as indicated by the instruction.

Form (a) lists twelve disassembled instructions from the current list address.
Form (b) sets the list address to "s" and then lists twelve instructions. Form
(c)  lists  disassembled code from "s" through "f". The last three  forms are
analogous to the first three, except that no symbolic information is displayed
(the labels and <symbol> fields are omitted).

In  all  cases,  the list address is set to the  next  unlisted  location, in
preparation  for  a subsequent L command. When SID-86 regains control  from a
program  being tested (see G, T, and U commands), the list address is  set to
the current value of the CS and IP registers.

You  can  abort long displays by typing any key during the list  process. Or,
enter Ctrl-S to halt the display temporarily.

The  syntax of the assembly language statements produced by the L  command is
described in Section 5, "Assembly Language Syntax for A and L Commands".

If  the  memory location being disassembled is not a valid  8086 instruction,
SID-86 displays it in the form:

        ??= nn

where "nn" is the hexadecimal value of the contents of the memory location.

The following are examples of the L command.

        #L243C,244E    Disassemble instructions from 243Ch through 244Eh.

        #L.find,+20    Disassemble 20h bytes from the label FIND.

        #L.err+3       Disassemble 12 lines of code from the label ERR plus 
3.


3.10 The M (Move) Command
-------------------------

The M command moves a block of data values from one area of memory to another.
The form is:

        Ms,f,d

where "s" is the 20-bit starting address of the block to be moved; "f" is the
offset of the final byte to be moved within the segment described by "s", and
 "d"  is the 20-bit address of the first byte of the area to receive the data.
If  the segment is not specified in "d", the same value is used that was used
for "s".

Note  that,  if "d" is between "s" and "f", part of the block being  moved is
overwritten  before  it is moved, because data is  transferred  starting from
location "s".

The following are examples of the M command.

        #M20:2400,+9,30:100     Move 10 bytes from 20:2400 to 30:100.

        #M.array,+#63,.array2   Move 64 bytes from ARRAY to ARRAY2.


3.11 The P (Pass Point) Command
-------------------------------

The P command sets, clears, and displays pass points. The forms are:

        (a) Pa,n
        (b) Pa
        (c) -Pa
        (d) -P
        (e) P

A  pass  point is a permanent breakpoint that remains in effect  until  it is
explicitly  removed,  as opposed to breakpoints set with the G  command, that
must  be  re-entered  with each G command. Pass points  have  associated pass
counts, ranging from 1 to 0FFFFh. The pass count indicates how many times the
instruction  at  the  pass point executes before the control  returns  to the
console. Up to sixteen pass points can be set at a time.

An  important  distinction between breakpoints and pass points is  that, when
execution stops at a breakpoint, the instruction at the breakpoint has not yet
been  executed. When execution stops due to a pass point whose pass count has
reached 1, the instruction at the pass point has been executed. This makes it
simple  to  proceed from a pass point with a G  command,  without immediately
encountering the same pass point.

Forms  (a) and (b) are used to set pass points. Form (a) sets a pass point at
address  "a" with a pass count of "n", where "a" is the 20-bit address of the
pass  point,  and "n" is the pass count, in the range 1 to 0FFFFh. If  a pass
point is already active at "a", the pass count is simply changed to "n". SID-
86 responds with a question mark if there are already 16 active pass points.

Form  (b) sets a pass point at "a" with a pass count of 1. If a pass point is
already active at "a", the pass count is simply changed to 1. SID-86 responds
with a question mark if there are already 16 active pass points.

Forms  (c)  and (d) are used to clear pass points. Form (c)  clears  the pass
point  at  location "a". SID-86 responds with a question mark if there  is no
pass point set at "a". Form (d) clears all the pass points.

Form (e) displays all the active pass points in the form:

        nnnn ssss:oooo .symbol

where "nnnn" is the current pass count for the pass point, "ssss:oooo" is the
segment  and offset of the pass point location, and ".symbol" is the symbolic
name of the offset of the pass point, if such a symbol exists.

When  a pass point is encountered, SID-86 displays the pass point information
in the form:

        nnnn PASS ssss:oooo .symbol

where "nnnn", "ssss:oooo", and ".symbol" are as described above. Next, SID-86
displays  the CPU state before the instruction at the pass point is executed.
SID-86  then executes the instruction at the pass point. If the pass point is
greater than 1, SID-86 decrements the pass count and transfers control back to
the program under test.

When the pass count reaches 1, SID-86 displays the break address (that of the
next instruction to be excuted) in the following form:

        *ssss:oooo .symbol

Once the pass count reaches 1, it remains at 1 until the pass point is cleared
or the pass count is changed with another P command.

Use pass points in conjunction with the G, T, and U commands. When you use the
G or U commands, you can suppress the intermediate pass point display with the
-G  or  -U forms (see Section 3.6, "The G Command", and Section 3.17,  "The U
Command"). In this case, only the final pass points (when the pass count = 1)
are  displayed.  You  can  interrupt the G or  U  command  before  its normal
termination  by  pressing  any key at the console. SID-86 aborts the  G  or U
command  when  the  next pass point is encountered and prompts  for  the next
command.

You  can also use pass points in conjunction with breakpoints set with  the G
command.  If  a pass point and a breakpoint are set at the same  address, the
breakpoint  is encountered first. Otherwise, pass points behave in  the usual
manner,  decrementing  the pass count until it reaches 1  and  then returning
control to SID-86.

Normally, the segment registers are not displayed at pass points. You can use
the  S/-S command to enable/disable the segment register display (See Section
3.14, "The S Command").

The following are examples of the P command.

        #P              Display active pass points.

        #P.error        Set pass point at label ERROR.

        #P.print,17     Set pass point at label PRINT with count of 17h.

        #-P             Clear all pass points.

        #-P.error       Clear pass point at label ERROR


3.12 The QI, QO (Query I/O) Command
-----------------------------------

The  QI and QO commands allow access to any of the 65,536 Input/Output ports.
The QI command reads data from a port; the QO command writes data to a port.

The forms of the QI command are:

        (a) QIn
        (b) QIWn

where "n" is the 16-bit port number. In the case of form (a), SID-86 displays
the  8-bit value read from port "n". In the case of form (b), SID-86 displays
a 16-bit value from port "n".

The forms of the QO command are:

        (a) QOn,v
        (b) QOWn,v

where  "n" is the 16-bit port number, and "v" is the value to output.  In the
case  of  form  (a), the 8-bit value "v" is written to port  "n".  If  "v" is
greater  than 255, SID-86 responds with a question mark. In the case  of form
(b), the 16-bit value "v" is written to port "n".


3.13 The R (Read) Command
-------------------------

The R command reads a file into a contiguous block of memory. The forms are:

        (a) R<filename>
        (b) R<filename>,s

where  <filename> is the name and type of the file to be read, and "s" is the
location to which the file is read. Form (a) lets SID-86 determine the memory
location into which the file is read. Form (b) causes SID-86 to read the file
into  the memory segment beginning at "s". This address can have the standard
form (ssss:oooo) as in the following example:

        #Rcpm.sys,1000:0

The  low-order four bits of "s" are assumed to be zero, so SID-86 reads files
on a paragraph boundary. If the memory at "s" is not available, SID-86 issues
the message:

        MEMORY REQUEST DENIED

SID-86 reads the file into memory, computes, allocates, and displays the start
and end addresses of the block of memory occupied by the file. A V command can
redisplay  this information at a later time. The default display pointer (for
subsequent D commands) is set to the start of the block occupied by the file.

The R command does not free any memory previously allocated by another R or E
command. Thus, a number of files can be read into memory without overlapping.
The  number  of files that can be loaded is limited to  seven  under CP/M-86,
which  is the number of memory allocations allowed by the BDOS, minus one for
SID-86 itself.

SID-86  issues  an error message if the file does not exist or  there  is not
enough memory to load the file.

The following are examples of the R command.

        #Rsid86.cmd     Read file SID86.CMD into memory.

        #Rtest          Read file TEST into memory.

        #Rtest,1000:0   Read  file  TEST  into memory,  starting  at 
location
                        1000:0.


3.14 The S (Set) Command
------------------------

The S command changes the contents of bytes or words of memory. The forms are:

        (a) Ss
        (b) SWs
        (c) S
        (d) -S

where "s" is the 20-bit address where the change occurs.

SID-86  displays the memory address and its current contents on the following
line. In response to form (a), the display is:

        ssss:oooo bb

and, in response to form (b); the display is:

        ssss:oooo wwww

where  "bb"  and "wwww" are the contents of memory in byte and  word formats,
respectively.

In  response to one of the above displays, you can choose to alter the memory
location  or  to  leave it unchanged. If you enter  a  valid  expression, the
contents  of  the byte (or word) in memory is replaced with the value  of the
expression. If you do not enter a value, the contents of memory are unaffected
and  the  contents of the next address are displayed. In either  case, SID-86
continues to display successive memory addresses and values until you enter a
period  (".")  on  a  line  by itself  or  until  SID-86  detects  an invalid
expression.

In response to form (a), you can enter a string of ASCII characters, beginning
with  a quotation mark (') and ending with a carriage return.  The characters
between  the  quotation  mark and the carriage return  are  placed  in memory
starting  at the address displayed. No case conversion takes place.  The next
address displayed is the address following the character string.

SID-86  issues an error message if the value stored in memory cannot  be read
back  successfully,  indicating  faulty or non-existant RAM  at  the location
indicated.

The  forms (c) and (d) control the display of the segment registers  when the
CPU  state is displayed with the trance command and at pass points.  Form (c)
turns on the segment register display, and form (d) turns it off. It is often
convenient to turn off the segment register display while debugging, to allow
the CPU state display to fit on one line.

The following are examples of the S command.

        #S.array+3              Begin set at ARRAY(3).
        nnnn:1234  55  0        Set byte to 0.
        nnnn:1235  55  'abc'    Set 3 bytes to 'a', 'b', 'c'.
        nnnn:1238  55  #75      Set byte to decimal 75.
        nnnn:1239  55  .        Terminate set command.
        #S                      Enable  segment register display in CPU state
                                display.
        #-S                     Disable segment register display in CPU state
                                display.


3.15 The SR (Search) Command
----------------------------

The  SR  (SeaRch) command searches a block of memory for a  given  pattern of
numeric or ASCII values, and lists the addresses where the pattern occurs. The
form is:

        SRs,f,pattern

where  "s" is the 20-bit starting address of the block to be searched, "f" is
the  offset of the final address of the block, and "pattern" is a list of one
or more hexadecimal values and/or ASCII strings. ASCII strings are enclosed in
double quotes (") and can be any length. For example,

        SR200,300,"The form",0D,0A

For  each occurrence of "pattern", SID-86 displays the 20-bit address  of the
first byte of the pattern, in the form:

        ssss:oooo

If no addresses are listed, "pattern" was not found.


3.16 The T (Trace) Command
--------------------------

The  T  command  traces  program execution for  1  to  0FFFFh  program steps,
displaying the CPU state before each step. The forms are:

        (a) T
        (b) Tn
        (c) TW
        (d) TWn
        (e) -T (with forms "a" through "d")

where  "n" is the number of program steps to execute before returning control
to the console. If "n" is omitted, a single program step is executed.

A  program  step  is  generally  a  single  instruction,  with  the following
exceptions:

*  If  a  BDOS interrupt instruction is traced, the entire  BDOS  function is
treated as one program step, and executes in real-time. This is because SID-86
itself makes BDOS calls, and the BDOS is not re-entrant.

*  If  the traced instruction is a MOV or POP whose destination is  a segment
register, the CPU executes the next instruction immediately. This is due to a
feature  of the 8086 that disables interrupts (including the Trace interrupt)
for one instruction after a MOV or POP loads a segment register. This allows a
sequence such as:

        MOV SS,StackSegment
        MOV SP,StackOffset

to  be  executed  with no chance of an interrupt  occurring  between  the two
instructions, at which time the stack is undefined. A sequence of such MOV or
POP instructions, plus one instruction after the sequence, is considered a one
program step.

* If any of the TW forms are used and the traced instruction is a CALL, CALLF,
or INT, the entire called subroutine or interrupt handler (and any subroutines
called therein) is treated as a one program step and executes in real-time.

Before  each  program  step is executed, SID-86 displays the  CPU  state, the
disassembled instruction to be executed, the symbolic name of the instruction
operand (if any), and the contents of the memory location(s) referenced by the
instruction  (if  appropriate).  (See Section 3.20, "The  X  Command",  for a
detailed  description  of the CPU state display.) If there is a  symbol whose
value  is  equal  to  the IP, the symbol name followed by  a  colon  (":") is
displayed  on the line preceding the CPU state display. The segment registers
are  not  normally displayed with the T command, which allows the  entire CPU
state to be displayed on one line. To enable the segment register display, use
the  S command (see Section 3.14, "The S Command"). With the segment register
display  enabled, the display of the CPU state is identical to that of  the X
command.

In  all  of  the forms, control transfers to the program  under  test  at the
address  indicated by the CS and IP registers. If "n" is not specified, as in
forms  (a),  one  program step is executed.  Otherwise,  SID-86  executes "n"
program steps and displays the CPU state before each step, as in form (b). You
can  abort  a  long trace before "n" steps have been executed  by  typing any
character at the console.

When  "n"  steps have been executed, SID-86 displays the address of  the next
instruction to be executed, along with the symbolic value of the IP, if there
is such a symbol, in the form:

        *ssss:oooo .symbol

Forms  (c)  and  (d) are analogous to forms (a) and (b),  except  in  the way
subroutine  calls are treated. In the TW forms, the entire  subroutine called
from  the program level being traced is treated as a single program step, and
executes  in  real-time. This allows tracing at a high-level of  the program,
ignoring subroutines that have already been debugged, or for other reasons are
not currently of interest.

If  the command is preceded by a minus sign, as in form (e),  symbolic labels
and  symbolic operands are omitted from the CPU state display. This can speed
up  the  display when large symbol tables are loaded, by skipping  the symbol
table lookup.

When  a  single instruction is being traced, interrupts are disabled  for the
duration  of  the  instruction.  This prevents  SID-86  from  tracing through
interrupt  handlers  when  debugging  on systems  in  which  interrupts occur
frequently.

After  a  T  command, the list address used in the L command  is  set  to the
address of the next instruction to be executed, and the default segment values
are set to the CS and DS register values.

The following are examples of the T command.

        #T              Trace one program step.

        #Tffff          Trace 65535 steps.

        #-T#500         Trace 500 program steps with symbolic lookup disabled.


3.17 The U (Untrace) Command
----------------------------

The  U  command  is similar to the T command, except that  the  CPU  state is
displayed  only before the first instruction is executed, rather  than before
every step. The forms are:

        (a) U
        (b) Un
        (c) UW
        (d) UWn
        (e) -U (with forms "a" through "d")

where "n" is the number of instructions to execute before returning control to
the  console. You can abort the U command before "n" steps have been executed
by striking any key at the console.

Form  (e)  differs from the analogous T command in that  SID-86  disables the
display of intermediate pass points (while the pass count is greater than 1).
In  this  case,  only when the pass count reaches 1 is  the  pass information
displayed (see Section 3.11, "The P Command").

The following are examples of the U command.

        #U200

Trace without display 200h steps.

        #-U200

Trace  without  display 200h steps, suppressing the  intermediate  pass point
display.


3.18 The V (Value) Command
--------------------------

The V command displays information about the last file loaded with the E or R
commands, excluding symbol tables loaded with the E command. The form is:

        V

If  the  last file was loaded with the E command, the V command  displays the
start and end addresses of each of the segments contained in the file. If the
last  file was read with the R command, the V command displays the  start and
end addresses of the block of memory where the file was read. SID-86 responds
to the V command with a question mark if neither the R or E commands have been
used.


3.19 The W (Write) Command
--------------------------

The W command writes the contents of a contiguous block of memory to disk. The
forms are:

        (a) W<filename>
        (b) W<filename>,s,f

where <filename> is the filename and filetype of the disk file to receive the
data, and "s" and "f" are the 20-bit first and last addresses of the block to
be written. If the segment is not specified in "f", SID-86 uses the same value
that was used for "s".

With  form (a), SID-86 assumes the "s" and "f" values from the last file read
with a R command. If no file was read with an R command, SID-86 responds with
a question mark ("?"). This form is useful for writing out files after patches
have been installed, assuming the overall length of the file is unchanged.

With  form (b), where "s" and "f" are specified as 20-bit addresses,  the low
four  bits  of  "s" are assumed to be 0. Thus, the block  being  written must
always start on a paragraph boundary.

If  a  file with the name specified in the W command  already  exists, SID-86
deletes it before writing a new file.

The following are examples of the W command.

        #Wtest.cmd              Write to the file TEST.CMD the contents of the
                                memory  block read into by the most  recent R
                                command.

        #Wb:test.cmd,40:0,3FF   Write  the contents of the memory  block 40:0
                                through  40:3FF to the file TEST.CMD on drive
                                B.


3.20 The X (Examine CPU State) Command
--------------------------------------

The  X  command allows you to examine and alter the CPU state of  the program
under test. The forms are:

        (a) X
        (b) Xr
        (c) Xf

where  "r"  is  the  name of one of the 8086 CPU  registers  and  "f"  is the
abbreviation  of one of the CPU flags. Form (a) displays the CPU state in the
form:

                    AX    BX    CX   ...   SS    ES    IP
        ---------  xxxx  xxxx  xxxx  ...  xxxx  xxxx  xxxx
         <instruction>   <symbol name>    <memory value>

The  nine hyphens at the beginning of the line indicate the state of the nine
CPU  flags.  Each  position  can  be either  a  hyphen,  indicating  that the
corresponding  flag is not set (0), or a 1-character abbreviation of the flag
name, indicating that the flag is set (1). The abbreviation of the flag names
are shown in Table 3-1.

        Table 3-1. Flag Name Abbreviations

        Character       Name
        ---------       --------
            O           Overflow
            D           Direction
            I           Interrupt Enable
            T           Trap
            S           Sign
            Z           Zero
            A           Auxiliary Carry
            P           Parity
            C           Carry

<instruction>  is  the  disassembled instruction at the next  location  to be
executed,  which is indicated by the CS and IP registers. If the symbol table
contains   a  symbol  whose  value  is  equal  to  one  of  the  operands in
<instruction>,  the  symbol  name is displayed in  the  <symbol  name> field,
preceded  by a period ("."). If <instruction> references memory, the contents
of  the  referenced  location(s) are displayed in the  <memory  value> field,
preceded by an equal sign. Either a byte, word, or double word value is shown,
depending on the instruction. In addition to displaying the machine state, the
first  form changes the values of the default segments back to the CS  and DS
register  values, and the default offset for the L command to the IP register
value.

Form  (b)  allows you to alter the registers in the CPU state of  the program
being  tested.  The "r" following the X is the name of one of the  16-bit CPU
registers. SID-86 responds by displaying the name of the register, followed by
its current value. If you type a carriage return, the value of the register is
not changed. If you type a valid expression, the contents of the register are
changed  to the value of the expression. In either case, the next register is
then  displayed. This process continues until you enter a period (".")  or an
invalid expression, or the last register is displayed.

Form (c) allows you to alter one of the flags in the CPU state of the program
being tested. SID-86 responds by displaying the name of the flag, followed by
its current state. If you type a carriage return, the state of the flag is not
changed.  If you type a valid value, the state of the flag is changed to that
value.  Only one flag can be examined or altered with each Xf command. Set or
reset flags by entering a value of 1 or 0.

The following are examples of the X command.

        #Xbp            Change registers, starting with BP.
        BP=1000 2B64    Change BP to hex 2B64.
        SI=2000 #12345  Change SI to decimal 12345.
        DI=0020 .var+6  Change DI to value of symbol VAR plus 6.
        CS=0040 .       Terminate X command.


3.21 The Z (Display 8087 Math Co-processor Registers) Command
-------------------------------------------------------------

(Not documented... Due to Richard Plinston.)

         CW   SW   TW      IP        OP
        037F 0000 FFFF 0000 0000 0000 0000

        0  0000 0000 0000 0000 0000
        1  0000 0000 0000 0000 0000
        2  0000 0000 0000 0000 0000
        3  0000 0000 0000 0000 0000
        4  0000 0000 0000 0000 0000
        5  0000 0000 0000 0000 0000
        6  0000 0000 0000 0000 0000
        7  0000 0000 0000 0000 0000


Section 4: Default Segment Values
---------------------------------

SID-86  has  an  internal mechanism that keeps track of  the  current segment
value, making segment specification an optional part of a SID-86 command. SID-
86  divides  the  command set into two types of  commands,  according  to the
segment  a command defaults to, if you do not specify a segment value  in the
command line.

The  first  type of command, pertaining to the code segment,  includes  the A
(Assemble), L (List Mnemonics), P (Pass Points), and W (Write) commands. These
commands  use  the  internal  type-1 segment value  if  no  segment  value is
specified in the command.

When  invoked, SID-86 sets the type-1 segment value to 0, and changes it when
one of the following actions is taken:

* When an E command loads a file, SID-86 sets the type-1 segment value to the
value of the CS register.

* When an R command reads a file, SID-86 sets the type-1 segment value to the
base segment where the file was read.

*  When an X command changes the value of the CS register, SID-86 changes the
type-1 segment value to the new value of the CS register.

* When SID-86 regains control from a user program after a G, T, or U command,
it sets the type-1 segment value to the value of the CS register.

* When an A or L command explicitly specifies a segment value, SID-86 sets the
type-1 segment value to the segment value specified.


The  second  type of command, pertaining to the data segment, includes  the D
(Display),  F (Fill), M (Move), and S (Set) commands. These commands  use the
internal type-2 segment value if no segment value is specified in the command.

When  invoked, SID-86 sets the type-2 segment value to 0, and changes it when
one of the following actions is taken:

* When an E command loads a file, SID-86 sets the type-2 segment value to the
value of the DS register.

* When an R command reads a file, SID-86 sets the type-2 segment value to the
base segment where the file was read.

*  When an X command changes the value of the DS register, SID-86 changes the
type-2 segment value to the new value of the DS register.

* When SID-86 regains control from a user program after a G, T, or U command,
it sets the type-2 segment value to the value of the DS register.

*  When a D, F, M, or S command explicitly specifies a segment  value, SID-86
sets the type-2 segment value to the segment value specified.


When  evaluating  programs  that  have  identical values  in  the  CS  and DS
registers,  all  SID-86 commands defaults to the same  segment  value, unless
explicitly overridden.

Table  4-1  summarizes SID-86's default segment values. Note that the  G (Go)
command  does  not  fall  into either group, because it  defaults  to  the CS
register.

        Table 4-1. SID-86 Default Segment Values

        Command Type-1  Type-2
        ------- ------  ------
           A      *
           B              *
           D
           E      @       @
           F              *
           G      @       @
           H
           I
           L      *
           M              *
           P      %
           Q
           R      *       @
           S              *
           SR
           T      @       @
           U      @       @
           V
           W      *
           X      @       @
           Z

Abbreviations Used:
* = Use this segment default if none specified;
    change default if specified explicitly.
@ = Change this segment default.
% = Use this segment default if none specified.


Section 5: Assembly Language Syntax for A and L commands
--------------------------------------------------------

In  general,  the syntax of the assembly language statements in the  A  and L
commands  is standard Intel 8086 assembly language. Several  minor exceptions
are listed below.

*  Up  to three prefixes (LOCK, repeat, segment override) can  appear  in one
statement, but they all must precede the opcode of the statement. Alternately,
a prefix can be entered on a line by itself.

*  The  distinction  between  byte and word string  instructions  is  made as
follows:

        Byte    Word
        ----    ----
        LODSB   LODSW
        STOSB   STOSW
        SCASB   SCASW
        MOVSB   MOVSW
        CMPSB   CMPSW

* The mnemonics for near and far control transfer instructions are as follows:

        Short   Normal  Far
        -----   ------  ---
        JMPS    JMP     JMPF
                CALL    CALLF
                RET     RETF

* If the operand of a CALLF or JMPF instruction is a 20-bit absolute address,
it is entered in the form:

        ssss:oooo

where "ssss" is the segment and "oooo" is the offset of the address.

* Operands that can refer to either a byte or word are ambiguous, and must be
preceded either by the prefix BYTE or WORD. These prefixes can be abbreviated
to BY and WO. For example:

        INC BYTE[BP]
        NOT WORD[1234]

Failure to supply a prefix when needed results in an error message.

*  Operands that address memory directly are enclosed in square  brackets, to
distinguish them from immediate values. For example:

        ADD AX,5        ; Add 5 to register AX
        ADD AX,[5]      ; Add the contents of location 5 to AX

* The forms of register indirect memory operands are:

        [pointer register]
        [index register]
        [pointer register + index register]

where the pointer registers are BX and BP, and the index registers are SI and
DI. Any of these forms can be preceded by a numeric offset. For example:

        ADD BX,[BP+SI]
        ADD BX,3[BP+SI]
        ADD BX,1D47[BP+SI]


Section 6: SID-86 Sample Session
--------------------------------

In  the  following  sample session, the user  interactively  debugs  a simple
program.  User  input  is shown in Italic print; remarks  in  square brackets
explain the steps involved.

[Type source file of program to test.]

A>type typ.a86
; Display the contents of an
; ASCII file at the console.
;--------------------------------
; Base Page locations used.
;
fcb     EQU     005Ch           ; File Control Block
;
; ASCII characters used.
;
eof     EQU     1Ah             ; CP/M End-Of-File character
;
; Interrupts used.
;
bdosi   EQU     224             ; BDOS Interrupt Number
;
; BDOS functions used.
;
ConOutC EQU      2              ; Console Output
OpenC   EQU     15              ; Open File
ReadC   EQU     20              ; Read File
SetDMAc EQU     26              ; Set DMA Address
;

;--------------------------------
; Main.
;
start:  MOV     DX,fcb          ; Points to FCB
        CALL    open            ; Open file
loop:   CALL    GetChr          ; Get one char
        CMP     AL,eof          ; Is it the EOF char?
        JZ      done            ; Yes: the end
        CALL    ConOut          ; No: display it
        JMPS    loop            ;     and loop.
;
; The end. Back to CP/M.
;
done:   MOV     DL,0            ; = ?
        MOV     CL,0            ; = Reset function
        JMP     bdos            ; Ditto
;
;--------------------------------
; Get a char from DMA buffer.
;
GetChr: CMP     bPtr,bSize      ; See if we need a new buffer fill
        JC      Get1            ;
        CALL    FilBuf          ; Yes: Refill buffer from file
Get1:   MOV     BX,OFFSET buffer  ;

        MOV     AL,buffer[BX]   ; Get next character from buffer
        INC     bPtr            ; Increment buffer pointer
        RET                     ;
;
;--------------------------------
; Fill DMA buffer from file.
;
FilBuf: MOV     DX,OFFSET buffer  ;
        CALL    SetDMA          ;
        MOV     DX,5Ch          ;
        CALL    read            ;
        MOV     bPtr,00h        ;
        RET                     ;
;
;--------------------------------
; Open a file.
;
Open:   MOV     CL,openc        ;
        CALL    bdos            ; Do it the old fashioned way
        CMP     AL,0FFh         ;
        JNZ     err             ;
        RET                     ;
;
;--------------------------------

; Set DMA Address.
;
SetDMA: MOV     CL,SetDMAc      ;
        JMPS    bdos            ;
;
;--------------------------------
; Read one record from file.
;
Read:   MOV     CL,ReadC        ;
        CALL    bdos            ;
        CMP     AL,00h          ;
        JNZ     err             ;
        RET                     ;
;
;--------------------------------
; Console Output.
;
ConOut: MOV     CL,ConOutC      ;
        JMPS    bdos            ;
;
;--------------------------------
; Print a string.
;
PrintM: MOV     CL,9            ;
        JMPS    bdos            ;
;
;--------------------------------
; Provides Old fashioned BDOS call.
;
bdos:   INT     bdosi           ; IBM PC
        RET                     ;
;
;--------------------------------
; Print error message and abort.
;
Err:    MOV     DX,OFFSET ErrorM  ;
        CALL    printm          ;
        JMP     done            ;
;
;--------------------------------
        DSEG
;--------------------------------
        ORG     100h            ; Reserve Base Page
;
ErrorM  DB      'ERROR',0Dh,0Ah,'$'
bSize   EQU     80h             ; Buffer Size = 128 characters
buffer  RS      bSize           ; Reserve them
bPtr    DB      bSize           ; Buffer Pointer = 1st char

;
;--------------------------------
;
        END

[Assemble TYP.A86 file.]

A>asm typ

CP/M 8086 ASSEMBLER VER 1.1
END OF PASS 1
END OF PASS 2
END OF ASSEMBLY.  NUMBER OF ERRORS:   0.  USE FACTOR:  0%

[Type list file created by ASM-86.]

A>type typ.lst

CP/M ASM86 1.1  SOURCE: TYP.A86 
PAGE   1


                        ; Display the contents of an
                        ; ASCII file at the console.
                        ;--------------------------------
                        ; Base Page locations used.
                        ;
   005C                 fcb     EQU     005Ch           ; File Control Block
                        ;
                        ; ASCII characters used.
                        ;
   001A                 eof     EQU     1Ah             ; CP/M End-Of-File character
                        ;
                        ; Interrupts used.
                        ;
   00E0                 bdosi   EQU     224             ; BDOS Interrupt Number
                        ;
                        ; BDOS functions used.
                        ;
   0002                 ConOutC EQU      2              ; Console Output
   000F                 OpenC   EQU     15              ; Open File

   0014                 ReadC   EQU     20              ; Read File
   001A                 SetDMAc EQU     26              ; Set DMA Address
                        ;
                        ;--------------------------------
                        ; Main.
                        ;
 0000 BA5C00            start:  MOV     DX,fcb          ; Points to FCB
 0003 E83B00       0041         CALL    open            ; Open file
 0006 E81000       0019 loop:   CALL    GetChr          ; Get one char
 0009 3C1A                      CMP     AL,eof          ; Is it the EOF char?
 000B 7405         0012         JZ      done            ; Yes: the end
 000D E84900       0059         CALL    ConOut          ; No: display it
 0010 EBF4         0006         JMPS    loop            ;     and loop.
                        ;
                        ; The end. Back to CP/M.
                        ;
 0012 B200              done:   MOV     DL,0            ; = ?
 0014 B100                      MOV     CL,0            ; = Reset function
 0016 E94800       0061         JMP     bdos            ; Ditto
                        ;
                        ;--------------------------------
                        ; Get a char from DMA buffer.
                        ;
 0019 803E880180        GetChr: CMP     bPtr,bSize      ; See if we need a new buffer fill

 001E 7203         0023         JC      Get1            ;
 0020 E80C00       002F         CALL    FilBuf          ; Yes: Refill buffer from file
 0023 BB0801            Get1:   MOV     BX,OFFSET buffer  ;
 0026 8A870801                  MOV     AL,buffer[BX]   ; Get next character from buffer
 002A FE068801                  INC     bPtr            ; Increment buffer pointer
 002E C3                        RET                     ;
                        ;
                        ;--------------------------------
                        ; Fill DMA buffer from file.

CP/M ASM86 1.1  SOURCE: TYP.A86 
PAGE   2


                        ;
 002F BA0801            FilBuf: MOV     DX,OFFSET buffer  ;
 0032 E81600       004B         CALL    SetDMA          ;
 0035 BA5C00                    MOV     DX,5Ch          ;
 0038 E81400       004F         CALL    read            ;
 003B C606880100                MOV     bPtr,00h        ;
 0040 C3                        RET                     ;
                        ;
                        ;--------------------------------
                        ; Open a file.
                        ;
 0041 B10F              Open:   MOV     CL,openc        ;

 0043 E81B00       0061         CALL    bdos            ; Do it the old fashioned way
 0046 3CFF                      CMP     AL,0FFh         ;
 0048 751A         0064         JNZ     err             ;
 004A C3                        RET                     ;
                        ;
                        ;--------------------------------
                        ; Set DMA Address.
                        ;
 004B B11A              SetDMA: MOV     CL,SetDMAc      ;
 004D EB12         0061         JMPS    bdos            ;
                        ;
                        ;--------------------------------
                        ; Read one record from file.
                        ;
 004F B114              Read:   MOV     CL,ReadC        ;
 0051 E80D00       0061         CALL    bdos            ;
 0054 3C00                      CMP     AL,00h          ;
 0056 750C         0064         JNZ     err             ;
 0058 C3                        RET                     ;
                        ;
                        ;--------------------------------
                        ; Console Output.
                        ;
 0059 B102              ConOut: MOV     CL,ConOutC      ;
 005B EB04         0061         JMPS    bdos            ;
                        ;
                        ;--------------------------------
                        ; Print a string.
                        ;
 005D B109              PrintM: MOV     CL,9            ;
 005F EB00         0061         JMPS    bdos            ;
                        ;
                        ;--------------------------------
                        ; Provides Old fashioned BDOS call.
                        ;
 0061 CDE0              bdos:   INT     bdosi           ; IBM PC
 0063 C3                        RET                     ;
                        ;
                        ;--------------------------------
                        ; Print error message and abort.

CP/M ASM86 1.1  SOURCE: TYP.A86 
PAGE   3


                        ;
 0064 BA0001            Err:    MOV     DX,OFFSET ErrorM  ;
 0067 E8F3FF       005D         CALL    printm          ;
 006A E9A5FF       0012         JMP     done            ;
                        ;

                        ;--------------------------------
                                DSEG
                        ;--------------------------------
                                ORG     100h            ; Reserve Base Page
                        ;
 0100 4552524F520D      ErrorM  DB      'ERROR',0Dh,0Ah,'$'
      0A24
   0080                 bSize   EQU     80h             ; Buffer Size = 128 characters
 0108                   buffer  RS      bSize           ; Reserve them
 0188 80                bPtr    DB      bSize           ; Buffer Pointer = 1st char
                        ;
                        ;--------------------------------
                        ;
                                END


END OF ASSEMBLY.  NUMBER OF ERRORS:   0.  USE FACTOR:  0%

[Type hex file produced by ASM-86.]

A>type typ.h86
:0400000300000000F9
:1B000081BA5C00E83B00E810003C1A7405E84900EBF4B200B100E94800803E02
:1B001B818801807203E80C00BB08018A870801FE068801C3BA0801E81600BA2E
:1B0036815C00E81400C606880100C3B10FE81B003CFF751AC3B11AEB12B114E1
:1B005181E80D003C00750CC3B102EB04B109EB00CDE0C3BA0001E8F3FFE9A5C4
:01006C81FF13
:080100824552524F520D0A24B0
:010188828074
:00000001FF

[Type symbol table file produced by ASM-86.]

A>type typ.sym

0000 VARIABLES
0188 BPTR       0108 BUFFER     0100 ERRORM

0000 NUMBERS
00E0 BDOSI      0080 BSIZE      0002 CONOUTC    001A EOF        005C FCB
000F OPENC      0014 READC      001A SETDMAC

0000 LABELS
0061 BDOS       0059 CONOUT     0012 DONE       0064 ERR        002F FILBUF
0023 GET1       0019 GETCHR     0006 LOOP       0041 OPEN       005D PRINTM
004F READ       004B SETDMA     0000 START

[Create command file from hex file.]

A>gencmd typ

BYTES READ    007A
RECORDS WRITTEN 05

[Try executing the program with the file TYP.A86 as data.]

A>typ typ.a86
ERROR

[The program did not work correctly, so load the command file and symbol table
file to find out why.]

A>sid typ.cmd typ.sym
SID86 1.01   1/4/83

[SID-86 shows the start and end addresses of each segment from the file.]

     START      END
CS 1CC1:0000 1CC1:006F
DS 1CC8:0000 1CC8:018F
SYMBOLS

[Display all the symbols that SID-86 loaded.]

#h
0000 VARIABLES
0188 BPTR
0108 BUFFER
0100 ERRORM
0000 NUMBERS
00E0 BDOSI
0080 BSIZE
0002 CONOUTC
001A EOF
005C FCB
000F OPENC
0014 READC
001A SETDMAC
0000 LABELS
0061 BDOS
0059 CONOUT
0012 DONE
0064 ERR
002F FILBUF
0023 GET1
0019 GETCHR
0006 LOOP
0041 OPEN
005D PRINTM
004F READ
004B SETDMA
0000 START

[Disassemble the beginning of the code segment.]

#l
START:
  1CC1:0000 MOV    DX,005C .FCB
  1CC1:0003 CALL   0041 .OPEN
LOOP:
  1CC1:0006 CALL   0019 .GETCHR
  1CC1:0009 CMP    AL,1A .EOF
  1CC1:000B JZ     0012 .DONE
  1CC1:000D CALL   0059 .CONOUT
  1CC1:0010 JMPS   0006 .LOOP
DONE:
  1CC1:0012 MOV    DL,00 .VARIABLES
  1CC1:0014 MOV    CL,00 .VARIABLES
  1CC1:0016 JMP    0061 .BDOS
GETCHR:
  1CC1:0019 CMP    BYTE [0188],80 .BPTR
  1CC1:001E JB     0023 .GET1

[Set  up the default file control block at 005Ch with the name of the file to
process.]

#ityp.a86

[Trace the first two instructions of the program.]

#t2
           AX   BX   CX   DX   SP   BP   SI   DI   IP
--I------ 0000 0000 0000 0000 015C 0000 0000 0000 0000 MOV    DX,005C .FCB
--I------ 0000 0000 0000 005C 015C 0000 0000 0000 0003 CALL   0041 .OPEN

[SID-86 stops execution after two instructions, at the label OPEN.]

*1CC1:0041 .OPEN

[Display the contents of the default FCB, to make sure it is set up right.]

#d.fcb,+#35
1CC8:005C 00 54 59 50 20 20 20 20 20 41 38 36 00 00 00 00 .TYP     A86....
1CC8:006C 00 20 20 20 20 20 20 20 20 20 20 20 00 00 00 00 .           ....
1CC8:007C 00 00 00 00 ....

[The FCB looks Ok. Disassemble the next few instructions.]

#l
OPEN:
  1CC1:0041 MOV    CL,0F .OPENC
  1CC1:0043 CALL   0061 .BDOS
  1CC1:0046 CMP    AL,FF
  1CC1:0048 JNZ    0064 .ERR
  1CC1:004A RET
SETDMA:
  1CC1:004B MOV    CL,1A .EOF
  1CC1:004D JMPS   0061 .BDOS
READ:
  1CC1:004F MOV    CL,14 .READC
  1CC1:0051 CALL   0061 .BDOS
  1CC1:0054 CMP    AL,00 .VARIABLES
  1CC1:0056 JNZ    0064 .ERR
  1CC1:0058 RET

[Continue program execution with a break point after the open function.]

#g,46
*1CC1:0046

[Display the CPU registers.]

#x
           AX   BX   CX   DX   SP   BP   SI   DI   CS   DS   SS   ES   IP
--I------ 0000 0000 0000 0000 015A 0000 0000 0000 1CC1 1CC8 0AFB 1CC8 0046
CMP    AL,FF

[Registers look Ok; trace a few more instructions.]

#t2
           AX   BX   CX   DX   SP   BP   SI   DI   IP
--I------ 0000 0000 0000 0000 015A 0000 0000 0000 0046 CMP    AL,FF
--I---A-C 0000 0000 0000 0000 015A 0000 0000 0000 0048 JNZ    0064 .ERR
*1CC1:0064 .ERR

[Shouldn't be getting to the ERR label -- the jump instruction seems to be of
the  wrong  flavor. It should be a JZ. Rather than editing the  source, let's
install a patch. Since the new instruction is the same length as the old one,
it will be easy. Read the file into memory (including the header record).]

#rtyp.cmd
  START      END
1CEF:0000 1CEF:027F

[The  file was read into memory starting at paragraph 1CEF. That is where the
header record is -- the code will start 8 paragraphs later.]

#h1CEF,8
+ 1CF7   - 1CE7   * 0000E778   / 039D (0007)

[The  code  starts  in paragraph 1CF7. If we use that as the base  for  the L
command, all the symbol values will be correct.]

#l1CF7:0
START:
  1CF7:0000 MOV    DX,005C .FCB
  1CF7:0003 CALL   0041 .OPEN
LOOP:
  1CF7:0006 CALL   0019 .GETCHR
  1CF7:0009 CMP    AL,1A .EOF
  1CF7:000B JZ     0012 .DONE
  1CF7:000D CALL   0059 .CONOUT
  1CF7:0010 JMPS   0006 .LOOP
DONE:
  1CF7:0012 MOV    DL,00 .VARIABLES
  1CF7:0014 MOV    CL,00 .VARIABLES
  1CF7:0016 JMP    0061 .BDOS
GETCHR:
  1CF7:0019 CMP    BYTE [0188],80 .BPTR
  1CF7:001E JB     0023 .GET1

[Disassemble the OPEN routine.]

#l.open,.setdma-1
OPEN:
  1CF7:0041 MOV    CL,0F .OPENC
  1CF7:0043 CALL   0061 .BDOS
  1CF7:0046 CMP    AL,FF
  1CF7:0048 JNZ    0064 .ERR
  1CF7:004A RET

[Assemble patch instruction.]

#a48

[Note that symbolic values may be used in the A command.]

1CF7:0048 jz .err
1CF7:004A .

[Write the patched file back to disk. The start and end addresses need not be
included  in  the  W command, since the overall length of  the  file  did not
change.]

#wtyp.cmd

[Reload  the  patched file and symbols. This is needed, since  the  R command
doesn't set up registers.]

#etyp.cmd typ.sym
     START      END
CS 1CC1:0000 1CC1:006F
DS 1CC8:0000 1CC8:018F
SYMBOLS
#ityp.a86

[Execute the program with a break point at DONE.]

#g,.done
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffff

[This  doesn't  look quite right. Invoke SID-86 again, leaving  off  the file
types, since SID-86 uses the appropriate defaults.]

A>sid typ typ
SID86 1.01   1/4/83
     START      END
CS 1CC1:0000 1CC1:006F
DS 1CC8:0000 1CC8:018F
SYMBOLS

[Set up default file control block.]

#ityp.a86

[Disassemble start of code segment.]

#l
START:
  1CC1:0000 MOV    DX,005C .FCB
  1CC1:0003 CALL   0041 .OPEN
LOOP:
  1CC1:0006 CALL   0019 .GETCHR
  1CC1:0009 CMP    AL,1A .EOF
  1CC1:000B JZ     0012 .DONE
  1CC1:000D CALL   0059 .CONOUT
  1CC1:0010 JMPS   0006 .LOOP
DONE:
  1CC1:0012 MOV    DL,00 .VARIABLES
  1CC1:0014 MOV    CL,00 .VARIABLES
  1CC1:0016 JMP    0061 .BDOS
GETCHR:
  1CC1:0019 CMP    BYTE [0188],80 .BPTR
  1CC1:001E JB     0023 .GET1

[Trace without call, so SID-86 doesn't trace the OPEN routine, which should be
fixed.]

#tw2
           AX   BX   CX   DX   SP   BP   SI   DI   IP
--I------ 0000 0000 0000 0000 015C 0000 0000 0000 0000 MOV    DX,005C .FCB
--I------ 0000 0000 0000 005C 015C 0000 0000 0000 0003 CALL   0041 .OPEN
*1CC1:0006 .LOOP

[Disassemble next few instructions.]

#l
LOOP:
  1CC1:0006 CALL   0019 .GETCHR
  1CC1:0009 CMP    AL,1A .EOF
  1CC1:000B JZ     0012 .DONE
  1CC1:000D CALL   0059 .CONOUT
  1CC1:0010 JMPS   0006 .LOOP
DONE:
  1CC1:0012 MOV    DL,00 .VARIABLES
  1CC1:0014 MOV    CL,00 .VARIABLES
  1CC1:0016 JMP    0061 .BDOS
GETCHR:
  1CC1:0019 CMP    BYTE [0188],80 .BPTR
  1CC1:001E JB     0023 .GET1
  1CC1:0020 CALL   002F .FILBUF
GET1:
  1CC1:0023 MOV    BX,0108 .BUFFER

[Trace  without  call  next three instructions, to see  if  this  sequence is
working.]

#tw3
           AX   BX   CX   DX   SP   BP   SI   DI   IP
--I---A-C 0000 0000 0000 0000 015C 0000 0000 0000 0006 CALL   0019 .GETCHR
--I------ 0059 0108 0000 0000 015C 0000 0000 0000 0009 CMP    AL,1A .EOF
--I---AP- 0059 0108 0000 0000 015C 0000 0000 0000 000B JZ     0012 .DONE
*1CC1:000D

[GETCHR is returning a 59h -- something must be wrong there. Use the E command
to bring in a fresh copy of the program.]

#etyp typ
     START      END
CS 1CC1:0000 1CC1:006F
DS 1CC8:0000 1CC8:018F
SYMBOLS

[Disassemble code segment.]

#l
START:
  1CC1:0000 MOV    DX,005C .FCB
  1CC1:0003 CALL   0041 .OPEN
LOOP:
  1CC1:0006 CALL   0019 .GETCHR
  1CC1:0009 CMP    AL,1A .EOF
  1CC1:000B JZ     0012 .DONE
  1CC1:000D CALL   0059 .CONOUT
  1CC1:0010 JMPS   0006 .LOOP
DONE:
  1CC1:0012 MOV    DL,00 .VARIABLES
  1CC1:0014 MOV    CL,00 .VARIABLES
  1CC1:0016 JMP    0061 .BDOS
GETCHR:
  1CC1:0019 CMP    BYTE [0188],80 .BPTR
  1CC1:001E JB     0023 .GET1

[Trace without call, since we know the open works.]

#tw2
           AX   BX   CX   DX   SP   BP   SI   DI   IP
--I---AP- 0059 0108 0000 0000 015C 0000 0000 0000 0000 MOV    DX,005C .FCB
--I---AP- 0059 0108 0000 005C 015C 0000 0000 0000 0003 CALL   0041 
.OPENERROR

[Oops! Forgot to set up the file control block... Try again.]

A>sid typ typ
SID86 1.01   1/4/83
     START      END
CS 1CC1:0000 1CC1:006F
DS 1CC8:0000 1CC8:018F
SYMBOLS

[This should work better.]

#ityp.a86
#g,.getchr
*1CC1:0019 .GETCHR

[Disassemble GETCHR routine.]

#l
GETCHR:
  1CC1:0019 CMP    BYTE [0188],80 .BPTR
  1CC1:001E JB     0023 .GET1
  1CC1:0020 CALL   002F .FILBUF
GET1:
  1CC1:0023 MOV    BX,0108 .BUFFER
  1CC1:0026 MOV    AL,0108[BX] .BUFFER
  1CC1:002A INC    BYTE [0188] .BPTR
  1CC1:002E RET
FILBUF:
  1CC1:002F MOV    DX,0108 .BUFFER
  1CC1:0032 CALL   004B .SETDMA
  1CC1:0035 MOV    DX,005C .FCB
  1CC1:0038 CALL   004F .READ
  1CC1:003B MOV    BYTE [0188],00 .BPTR

[Trace first few instructions. Note that SID-86 shows the contents of BPTR as
it is being compared.]

#t2
           AX   BX   CX   DX   SP   BP   SI   DI   IP
--I---A-C 0000 0000 0000 0000 015A 0000 0000 0000 0019 CMP    BYTE [0188],80 
.BPTR =80
--I--Z-P- 0000 0000 0000 0000 015A 0000 0000 0000 001E JB     0023 .GET1
*1CC1:0020

[The compare worked Ok; keep going.]

#t
           AX   BX   CX   DX   SP   BP   SI   DI   IP
--I--Z-P- 0000 0000 0000 0000 015A 0000 0000 0000 0020 CALL   002F .FILBUF
*1CC1:002F .FILBUF

[See what FILBUF looks like.]

#l
FILBUF:
  1CC1:002F MOV    DX,0108 .BUFFER
  1CC1:0032 CALL   004B .SETDMA
  1CC1:0035 MOV    DX,005C .FCB
  1CC1:0038 CALL   004F .READ
  1CC1:003B MOV    BYTE [0188],00 .BPTR
  1CC1:0040 RET
OPEN:
  1CC1:0041 MOV    CL,0F .OPENC
  1CC1:0043 CALL   0061 .BDOS
  1CC1:0046 CMP    AL,FF
  1CC1:0048 JZ     0064 .ERR
  1CC1:004A RET
SETDMA:
  1CC1:004B MOV    CL,1A .EOF

[See what is in the buffer before the disk read takes place.]

#d.buffer,+2F
1CC8:0108 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
1CC8:0118 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
1CC8:0128 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

[Trace the FILBUF routine.]

#tw6
           AX   BX   CX   DX   SP   BP   SI   DI   IP
--I--Z-P- 0000 0000 0000 0000 0158 0000 0000 0000 002F MOV    DX,0108 
.BUFFER
--I--Z-P- 0000 0000 0000 0108 0158 0000 0000 0000 0032 CALL   004B .SETDMA
--I--Z-P- 00C3 00C3 0000 0108 0158 0000 0000 0000 0035 MOV    DX,005C .FCB
--I--Z-P- 00C3 00C3 0000 005C 0158 0000 0000 0000 0038 CALL   004F .READ
--I--Z-P- 0000 0000 0000 0000 0158 0000 0000 0000 003B MOV    BYTE [0188],00 
.BPTR =80
--I--Z-P- 0000 0000 0000 0000 0158 0000 0000 0000 0040 RET
*1CC1:0023 .GET1

[See what is in the buffer after the read.]

#d.buffer,+4F
1CC8:0108 3B 20 44 69 73 70 6C 61 79 20 74 68 65 20 63 6F ; Display the co
1CC8:0118 6E 74 65 6E 74 73 20 6F 66 20 61 6E 0D 0A 3B 20 ntents of an..;
1CC8:0128 41 53 43 49 49 20 66 69 6C 65 20 61 74 20 74 68 ASCII file at th
1CC8:0138 65 20 63 6F 6E 73 6F 6C 65 2E 0D 0A 3B 2D 2D 2D e console...;---
1CC8:0148 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D ----------------

[Looks like good data in the buffer. See what's next.]

#l
GET1:
  1CC1:0023 MOV    BX,0108 .BUFFER
  1CC1:0026 MOV    AL,0108[BX] .BUFFER
  1CC1:002A INC    BYTE [0188] .BPTR
  1CC1:002E RET
FILBUF:
  1CC1:002F MOV    DX,0108 .BUFFER
  1CC1:0032 CALL   004B .SETDMA
  1CC1:0035 MOV    DX,005C .FCB
  1CC1:0038 CALL   004F .READ
  1CC1:003B MOV    BYTE [0188],00 .BPTR
  1CC1:0040 RET
OPEN:
  1CC1:0041 MOV    CL,0F .OPENC
  1CC1:0043 CALL   0061 .BDOS

[Trace the code getting the next character from the buffer.]

#t4
           AX   BX   CX   DX   SP   BP   SI   DI   IP
--I--Z-P- 0000 0000 0000 0000 015A 0000 0000 0000 0023 MOV    BX,0108 
.BUFFER
--I--Z-P- 0000 0108 0000 0000 015A 0000 0000 0000 0026 MOV    AL,0108[BX] 
.BUFFER =59
--I--Z-P- 0059 0108 0000 0000 015A 0000 0000 0000 002A INC    BYTE [0188] 
.BPTR =00
--I------ 0059 0108 0000 0000 015A 0000 0000 0000 002E RET
*1CC1:0009

[It is getting the wrong data, because BX should have the contents of BPTR in
it, rather than the address of the buffer. Need to edit, and also install fix
that we patched earlier.]

#^C
A>ed typ.a86
     : *#afOpen:
   65: *
   66:          CALL    bdos            ; Do it the old fashioned way
   66: *
   67:          CMP     AL,0FFh         ;
   67: *
   68:          JNZ     err             ;
   68: *sJNZ^ZJZ^Z0lt
   68:          JZ     err              ;
   68: *bfGet1:
   46: *0lt
   46:  Get1:   MOV     BX,OFFSET buffer ;
   46: *sOFFSET buffer^ZbPtr^Z0lt
   46:  Get1:   MOV     BX,bPtr         ;
   46: *sBX^ZBL^Z0lt
   46:  Get1:   MOV     BL,bPtr         ;
   46: *
   47:          MOV     AL,buffer[BX]   ; Get next character from buffer
   47: *i
   47:         MOV     BH,00h          ;
   48: ^Z
   48: *e

A>asm typ

CP/M 8086 ASSEMBLER VER 1.1
END OF PASS 1
END OF PASS 2
END OF ASSEMBLY.  NUMBER OF ERRORS:   0.  USE FACTOR:  0%

A>gencmd typ

BYTES READ    007D
RECORDS WRITTEN 05

[Try it again.]

A>typ typ.a86
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffff

[Still no good. I thought this was supposed to be a simple project!]

A>sid typ typ
SID86 1.01   1/4/83
     START      END
CS 1CC1:0000 1CC1:006F
DS 1CC8:0000 1CC8:018F
SYMBOLS
#ityp.a86
#l
START:
  1CC1:0000 MOV    DX,005C .FCB
  1CC1:0003 CALL   0044 .OPEN
LOOP:
  1CC1:0006 CALL   0019 .GETCHR
  1CC1:0009 CMP    AL,1A .EOF
  1CC1:000B JZ     0012 .DONE
  1CC1:000D CALL   005C .CONOUT
  1CC1:0010 JMPS   0006 .LOOP
DONE:
  1CC1:0012 MOV    DL,00 .VARIABLES
  1CC1:0014 MOV    CL,00 .VARIABLES
  1CC1:0016 JMP    0064 .BDOS
GETCHR:
  1CC1:0019 CMP    BYTE [0188],80 .BPTR
  1CC1:001E JB     0023 .GET1

[Trace at the top level.]

#tw5
           AX   BX   CX   DX   SP   BP   SI   DI   IP
--I------ 0000 0000 0000 0000 015C 0000 0000 0000 0000 MOV    DX,005C .FCB
--I------ 0000 0000 0000 005C 015C 0000 0000 0000 0003 CALL   0044 .OPEN
LOOP:
--I---A-C 0000 0000 0000 0000 015C 0000 0000 0000 0006 CALL   0019 .GETCHR
--I------ 003B 0000 0000 0000 015C 0000 0000 0000 0009 CMP    AL,1A .EOF
--I----P- 003B 0000 0000 0000 015C 0000 0000 0000 000B JZ     0012 .DONE
*1CC1:000D

[Got the right data from GETCHR.]

#l
  1CC1:000D CALL   005C .CONOUT
  1CC1:0010 JMPS   0006 .LOOP
DONE:
  1CC1:0012 MOV    DL,00 .VARIABLES
  1CC1:0014 MOV    CL,00 .VARIABLES
  1CC1:0016 JMP    0064 .BDOS
GETCHR:
  1CC1:0019 CMP    BYTE [0188],80 .BPTR
  1CC1:001E JB     0023 .GET1
  1CC1:0020 CALL   0032 .FILBUF
GET1:
  1CC1:0023 MOV    BL,[0188] .BPTR
  1CC1:0027 MOV    BH,00 .VARIABLES
  1CC1:0029 MOV    AL,0108[BX] .BUFFER
  1CC1:002D INC    BYTE [0188] .BPTR
#t
           AX   BX   CX   DX   SP   BP   SI   DI   IP
--I----P- 003B 0000 0000 0000 015C 0000 0000 0000 000D CALL   005C .CONOUT
*1CC1:005C .CONOUT
#l
CONOUT:
  1CC1:005C MOV    CL,02 .CONOUTC
  1CC1:005E JMPS   0064 .BDOS
PRINTM:
  1CC1:0060 MOV    CL,09
  1CC1:0062 JMPS   0064 .BDOS
BDOS:
  1CC1:0064 INT    E0 .BDOSI
  1CC1:0066 RET
ERR:
  1CC1:0067 MOV    DX,0100 .ERRORM
  1CC1:006A CALL   0060 .PRINTM
  1CC1:006D JMP    0012 .DONE
  1CC1:0070 ??=    6F
  1CC1:0071 ADD    [BX+SI],AL
  1CC1:0073 ??=    C1

[At  this point, the data to output to the console should be in DL, but it 
is
not... Another edit.]

#^C
A>ed typ.a86
     : *#afConOut
   18: *0lt
   18:  ConOutC EQU      2              ; Console Output
   18: *1fConOut
   31: *0lt
   31:          CALL    ConOut          ; No: display it
   31: *i
   31:         MOV     DL,AL           ; Prepare for ConOut
   32: ^Z
   32: *e

A>asm typ

CP/M 8086 ASSEMBLER VER 1.1
END OF PASS 1
END OF PASS 2
END OF ASSEMBLY.  NUMBER OF ERRORS:   0.  USE FACTOR:  0%

A>gencmd typ

BYTES READ    007F
RECORDS WRITTEN 06

[One more time!]

A>typ typ.a86
; Display the contents of an
; ASCII file at the console.
;--------------------------------
; Base Page locations used.
;
fcb     EQU     005Ch           ; File Control Block
;
; ASCII characters used.
;
eof     EQU     1Ah             ; CP/M End-Of-File character
;
; Interrupts used.
;
bdosi   EQU     224             ; BDOS Interrupt Number
;
; BDOS functions used.
;
ConOutC EQU      2              ; Console Output
OpenC   EQU     15              ; Open File
ReadC   EQU     20              ; Read File
SetDMAc EQU     26              ; Set DMA Address
;
;--------------------------------
; Main.
;
start:  MOV     DX,fcb          ; Points to FCB
        CALL    open            ; Open file
loop:   CALL    GetChr          ; Get one char
        CMP     AL,eof          ; Is it the EOF char?
        JZ      done            ; Yes: the end
        MOV     DL,AL           ; Prepare for ConOut
        CALL    ConOut          ; No: display it
        JMPS    loop            ;     and loop.
;
; The end. Back to CP/M.
;
done:   MOV     DL,0            ; = ?
        MOV     CL,0            ; = Reset function
        JMP     bdos            ; Ditto
;
;--------------------------------
; Get a char from DMA buffer.
;
GetChr: CMP     bPtr,bSize      ; See if we need a new buffer fill
        JC      Get1            ;
        CALL    FilBuf          ; Yes: Refill buffer from file
Get1:   MOV     BL,bPtr  ;
        MOV     BH,00h          ;
        MOV     AL,buffer[BX]   ; Get next character from buffer
        INC     bPtr            ; Increment buffer pointer
        RET                     ;
;
;--------------------------------
; Fill DMA buffer from file.
;
FilBuf: MOV     DX,OFFSET buffer  ;
        CALL    SetDMA          ;
        MOV     DX,5Ch          ;
        CALL    read            ;
        MOV     bPtr,0          ;
        RET                     ;
;
;--------------------------------
; Open a file.
;
Open:   MOV     CL,openc        ;
        CALL    bdos            ; Do it the old fashioned way
        CMP     AL,0FFh         ;
        JZ      err             ;
        RET                     ;
;
;--------------------------------
; Set DMA Address.
;
SetDMA: MOV     CL,SetDMAc      ;
        JMPS    bdos            ;
;
;--------------------------------
; Read one record from file.
;
Read:   MOV     CL,ReadC        ;
        CALL    bdos            ;
        CMP     AL,00h          ;
        JNZ     err             ;
        RET                     ;
;
;--------------------------------
; Console Output.
;
ConOut: MOV     CL,ConOutC      ;
        JMPS    bdos            ;
;
;--------------------------------
; Print a string.
;
PrintM: MOV     CL,9            ;
        JMPS    bdos            ;
;
;--------------------------------
; Provides Old fashioned BDOS call.
;
bdos:   INT     bdosi           ; IBM PC
        RET                     ;
;
;--------------------------------
; Print error message and abort.
;
Err:    MOV     DX,OFFSET ErrorM  ;
        CALL    printm          ;
        JMP     done            ;
;
;--------------------------------
        DSEG
;--------------------------------
        ORG     100h            ; Reserve Base Page
;
ErrorM  DB      'ERROR',0Dh,0Ah,'$'
bSize   EQU     80h             ; Buffer Size = 128 characters
buffer  RS      bSize           ; Reserve them
bPtr    DB      bSize           ; Buffer Pointer = 1st char
;
;--------------------------------
;
        END

[Done  at last. Just out of curiosity, let's find out how many characters are
in the file by setting a pass point with a high count at CONOUT.]

A>sid typ typ
SID86 1.01   1/4/83
     START      END
CS 1CC1:0000 1CC1:007F
DS 1CC9:0000 1CC9:018F
SYMBOLS
#ityp.a86

[Hopefully, there are fewer than 65535 characters!]

#p.conout,ffff

[Begin execution, with a break point at DONE.]

#g,.done
FFFF PASS 1CC1:005E .CONOUT
--I----P- 003B 0000 0000 003B 015A 0000 0000 0000 005E MOV    CL,02 
.CONOUTC;
FFFE PASS 1CC1:005E .CONOUT
--I---AP- 0220 0001 0000 1820 015A 0000 0000 0000 005E MOV    CL,02 .CONOUTC
FFFD PASS 1CC1:005E .CONOUT
--I---A-- 0244 0002 0000 1844 015A 0000 0000 0000 005E MOV    CL,02 
.CONOUTCD
FFFC PASS 1CC1:005E .CONOUT
--I---A-- 0269 0003 0000 1869 015A 0000 0000 0000 005E MOV    CL,02 
.CONOUTCi
FFFB PASS 1CC1:005E .CONOUT
--I---AP- 0273 0004 0000 1873 015A 0000 0000 0000 005E MOV    CL,02 
.CONOUTCs
FFFA PASS 1CC1:005E .CONOUT
--I---AP- 0270 0005 0000 1870 015A 0000 0000 0000 005E MOV    CL,02 
.CONOUTCp
FFF9 PASS 1CC1:005E .CONOUT
--I------ 026C 0006 0000 186C 015A 0000 0000 0000 005E MOV    CL,02 
.CONOUTCl
FFF8 PASS 1CC1:005E .CONOUT
--I---AP- 0261 0007 0000 1861 015A 0000 0000 0000 005E MOV    CL,02 
.CONOUTCa
FFF7 PASS 1CC1:005E .CONOUT
--I---AP- 0279 0008 0000 1879 015A 0000 0000 0000 005E MOV    CL,02 
.CONOUTCy
FFF6 PASS 1CC1:005E .CONOUT
--I---AP- 0220 0009 0000 1820 015A 0000 0000 0000 005E MOV    CL,02 .CONOUTC
FFF5 PASS 1CC1:005E .CONOUT

[This is too messy. Using the -G command will suppress the display of the CPU
registers until the pass count is 1.]

#-g,.done
the contents of an
; ASCII file at the console.
;--------------------------------
; Base Page locations used.
;
fcb     EQU     005Ch           ; File Control Block
;
; ASCII characters used.
;
eof     EQU     1Ah             ; CP/M End-Of-File character
;
; Interrupts used.
;
bdosi   EQU     224             ; BDOS Interrupt Number
;
; BDOS functions used.
;
ConOutC EQU      2              ; Console Output
OpenC   EQU     15              ; Open File
ReadC   EQU     20              ; Read File
SetDMAc EQU     26              ; Set DMA Address
;
;--------------------------------
; Main.
;
start:  MOV     DX,fcb          ; Points to FCB
        CALL    open            ; Open file
loop:   CALL    GetChr          ; Get one char
        CMP     AL,eof          ; Is it the EOF char?
        JZ      done            ; Yes: the end
        MOV     DL,AL           ; Prepare for ConOut
        CALL    ConOut          ; No: display it
        JMPS    loop            ;     and loop.
;
; The end. Back to CP/M.
;
done:   MOV     DL,0            ; = ?
        MOV     CL,0            ; = Reset function
        JMP     bdos            ; Ditto
;
;--------------------------------
; Get a char from DMA buffer.
;
GetChr: CMP     bPtr,bSize      ; See if we need a new buffer fill
        JC      Get1            ;
        CALL    FilBuf          ; Yes: Refill buffer from file
Get1:   MOV     BL,bPtr         ;
        MOV     BH,00h          ;
        MOV     AL,buffer[BX]   ; Get next character from buffer
        INC     bPtr            ; Increment buffer pointer
        RET                     ;
;
;--------------------------------
; Fill DMA buffer from file.
;
FilBuf: MOV     DX,OFFSET buffer  ;
        CALL    SetDMA          ;
        MOV     DX,5Ch          ;
        CALL    read            ;
        MOV     bPtr,00h        ;
        RET                     ;
;
;--------------------------------
; Open a file.
;
Open:   MOV     CL,openc        ;
        CALL    bdos            ; Do it the old fashioned way
        CMP     AL,0FFh         ;
        JZ     err              ;
        RET                     ;
;
;--------------------------------
; Set DMA Address.
;
SetDMA: MOV     CL,SetDMAc      ;
        JMPS    bdos            ;
;
;--------------------------------
; Read one record from file.
;
Read:   MOV     CL,ReadC        ;
        CALL    bdos            ;
        CMP     AL,0            ;
        JNZ     err             ;
        RET                     ;
;
;--------------------------------
; Console Output.
;
ConOut: MOV     CL,ConOutC      ;
        JMPS    bdos            ;
;
;--------------------------------
; Print a string.
;
PrintM: MOV     CL,9            ;
        JMPS    bdos            ;
;
;--------------------------------
; Provides Old fashioned BDOS call.
;
bdos:   INT     bdosi           ; IBM PC
        RET                     ;
;
;--------------------------------
; Print error message and abort.
;
Err:    MOV     DX,OFFSET ErrorM  ;
        CALL    printm          ;
        JMP     done            ;
;
;--------------------------------
        DSEG
;--------------------------------
        ORG     100h            ; Reserve Base Page
;
ErrorM  DB      'ERROR',0Dh,0Ah,'$'
bSize   EQU     80h             ; Buffer Size = 128 characters
buffer  RS      bSize           ; Reserve them
bPtr    DB      bSize           ; Buffer Pointer = 1st char
;
;--------------------------------
;
        END

[Reached the break point at DONE.]

*1CC1:0014 .DONE

[Display the currently active pass points.]

#p
F229 1CC1:005E .CONOUT

[The  pass  count went from FFFF to F229, so the difference is the  number of
times  CONOUT  was  called, or the number of characters in  the  file.  The H
command will perform the subtraction, and display the result in decimal.]

#hffff-F229
0DD6 #3542

[3542 characters in the file.]

#^C
A>


Appendix A: SID-86 Error Messages
---------------------------------

Table A-1. SID-86 Error Messages

Error Message           Meaning
-------------           -------
AMBIGUOUS  OPERAND      An  attempt  was made to assemble a  command  with an
                        ambiguous operand. Precede the operand with the prefix
                        "BYTE" or "WORD".

BAD  FILE  NAME         A  filename  in an E, R, or W command  is incorrectly
                        specified.

BAD  HEX  DIGIT         A  SYM  file  being loaded with an E  command  has an
                        invalid hexadecimal digit.

CANNOT CLOSE            The disk file written by a W command cannot be closed.

DISK READ ERROR         The  disk file specified in an R command could not be
                        read properly.

DISK WRITE ERROR        A  disk  write  operation could  not  be successfully
                        performed  during a W command, probably due to a full
                        disk.

INSUFFICIENT MEMORY     There is not enough memory to load the file specified
                        in an R or E command.

MEMORY REQUEST DENIED   A request for memory during an R command could not be
                        fulfilled either because the maximum number of memory
                        allocations  has already been made, or the  memory at
                        the  specified address is not available. Up  to eight
                        blocks  of  memory can be allocated at  a  given time
                        under CP/M-86.

NO FILE                 The  file specified in an R or E command could not be
                        found on the disk.

NO SPACE                There is no space in the directory for the file being
                        written by a W command.

SYMBOL LENGTH ERROR     A symbol in a SYM file being loaded with an E command
                        has more than thirty-one characters.

SYMBOL TABLE FULL       There is no more space in SID-86's symbol table.

VERIFY ERROR AT s:o     The  value placed in memory by a Fill, Set,  Move, or
                        Assemble  command  could not be read  back correctly,
                        indicating  bad RAM or attempting to write to  ROM or
                        non-existent memory at the indicated location.


Index
-----

(To be done...)


EOF