  % -*- Mode:TeX -*-
\chapter{The assembler}\label{asm}

A complete assembler for the full 8086 instruction set is included in
the F83 package.\index{Forth/assembler} The source code is in the file \iprog{CPU8086.4TH}.

This assembler is written in Forth (the original version is by Michael
Perry).  The instructions are organized in different classes, and a
defining word is created for each class.  Each Intel mnemonic
corresponds to a Forth word which, when interpreted, will assemble
machine-language code in the dictionary.  If the mnemonic appears in a
{\sc colon} definition, it will assemble code every time that definition
is executed.  Thus {\sc colon} words can act as assembler macros.

Structured conditionals are supported by this assembler.  Structures
such as \id|BEGIN|\ldots\id|WHILE|\ldots\id|REPEAT|,
\id|IF|\ldots\id|ELSE|\ldots\id|THEN|, and
\id|DO|\ldots\id|LOOP| are provided; they compile appropriate
branches which test processor flags.  In our experience, the use of
these words simplifies one of the most error-prone aspects of
assembler-language programming.  Note that these words belong to the
\iprog{ASSEMBLER} vocabulary (Section \ref{dictionary}), and are quite
distinct from their synonyms in the main \iprog{FORTH} vocabulary.  The
latter may still be used during assembly (for example, in macros that
create repetitive portions of assembly code)---but explicit vocabulary
switching is then mandatory.

By recoding into assembly language just a few words that appear in
frequently executed inner loops of a Forth program, execution speed is
often dramatically improved.

\section{Symbols and syntax}

The Forth assembler uses the same mnemonics as the Intel assembler (you
can use a conventional programmer's reference card for the 8086, such as
that printed by {\sc micro logic}, Hackensack, NJ, for a complete list
of mnemonics, opcodes, operands, and meaning of machine instructions);
however, the reverse-Polish notation of Forth suggests a different order
for the operands. Namely, the Intel order
 $$
        \langle{\rm mnemonic}\rangle \langle{\rm destination}\rangle \langle{\rm source}\rangle 
 $$
\noindent  of the instruction \id|MOV BX,AX| (move contents of the {\tt AX} register to the
{\tt BX} register) becomes, in Forth, \id|AX BX MOV| (read ``from {\tt AX} to {\tt BX} move''),
with the syntax
 $$
        \langle{\rm source}\rangle \langle{\rm destination}\rangle \langle{\rm mnemonic}\rangle .
 $$
        \noindent
The only exception to this rule is the \id|OUT| instruction, which takes
its arguments in the same order as the \id|IN| instruction.  

For reference, a complete synopsis of legal instruction formats for the
Forth assembler is given in Section \ref{templates}.


\medskip

Single-operand instructions do the obvious thing. For example, \id|AX POP|
assembles an instruction to pop the top item of the stack into the {\tt AX}
register. Allowed operands are:
        \begin{verbatim}
 AL CL DL BL AH CH DH BH SP BP
 AX CX DX BX ES CS SS DS SI DI

 [BX+SI]  [SI+BX]  [SI]   #
 [BX+DI]  [DI+BX]  [DI]   #)
 [BP+SI]  [SI+BP]  [BX]  S#)
 [BP+DI]  [DI+BP]  [BP]\end{verbatim}
        The operands in the first group are complete by themselves, while
those in the second group expect a parameter on the stack, as in the following
examples

        \begin{tabular}{lp{7cm}}
        \id|3 # AX MOV| & Move the immediate number 3 into the {\tt AX} register. \\
        \id|AX 0 [DI] MOV| & Move the contents of {\tt AX} into the
location pointed to by the {\tt DI} register, with a displacement of 0
added to the address; use the default {\tt DS} segment. \\
        \id|ES: AX 0 [DI] MOV| & Same as above, but addressing relative to
the {\tt ES} segment. \\
        \id|3 # 300 #) MOV| & Move the immediate number 3 into location
{\tt 0300} relative to the {\tt DS} register. \\
        \id|300 #) JMP| & Jump to location {\tt 0300} relative to the {\tt CS}
register. 
        \end{tabular}

Note that \id|#| signals a number, \id|#)| an address, and \id|S#)| a
segment address.  The only instructions that can use a segment address
are \id|JMP| and \id|CALL|.

Each of the allowed operands leaves a 16-bit word on the stack during
assembly as an argument for the mnemonic, which comes last.  This is
the operand's only effect.  For instance, in the last example above,
\id|#)| leaves a flag on the top of the stack which tells the assembler
word \id|JMP| that the next item on the stack is an address.

\medskip
\noindent {\bf Special Cases}
\smallskip

The ``shift'' mnemonics each assemble a shift by one position unless {\tt CL} is
on the top of the stack:

        \begin{tabular}{lp{9cm}}
        \id|AX SHL| & Shift {\tt AX} left by 1. \\
        \id|AX CL SHL| & Shift {\tt AX} by {\tt CL} positions.
        \end{tabular}

The ``string'' mnemonics \id|CMPS|, \id|MOVS| and \id|SCAS| each
assemble an operation on 16-bit words unless preceded by \id|BYTE|, in
which case they operate on bytes.

The ``string'' mnemonics \id|STOS| and \id|LODS| expect either {\tt AX}
or {\tt AL} on the stack, to tell them whether to perform a word or
byte operation, as in \id|AX LODS|, \id|AL LODS|, \id|AX STOS|, and \id|AL STOS|.

Note that the word \id|BYTE| used above, as well as \id|FAR| used
with the jumps and calls below, set flags rather than leave anything
on the stack.

\section{Exotic jumps, calls, and returns}

The 8086 machine language includes a variety of exotic intersegment
hops (supported by the Intel assembler) that will probably not be
used by those writing {\sc code} words for Forth. However, for
completeness the corresponding Forth assembler constructs are
described here.

Subroutines have to know whether they are returning to a point 
within the same segment or in a different segment. A \id|FAR| return
expects both a segment and an offset on the stack, while a
normal return expects only an offset (don't blame us!).

\begin{tabular}{lp{9cm}}
\verb@RET@ & Normal return. \\
\verb@FAR RET@ & Intersegment return. \\
\verb@3 +RET@ & Return and then pop 3 values off of the stack. \\
\verb@2 FAR +RET@ & Intersegment return, and pop 2 values.
\end{tabular}

The \id|CALL| and \id|JMP| instructions have normal and \id|FAR|
forms, and some choices about how to get the destination address.
 $$ \begin{tabular}{lp{7cm}} 
        \verb@1234 #) CALL@ & Assembles unconditional call to address
{\tt 1234}, with the address stored as a relative displacement.  \\
        \verb@1234 S#) CALL@ & Same as above, but the address is stored
as an absolute offset from beginning of segment (useful in relocatable
code, I assume).  \\
        \verb@AX CALL@ & The address is in {\tt AX}.  \\
        \verb@0 [BX] CALL@ & {\tt BX} points to the address \\
        \verb@1234 400 #) FAR CALL@ & Direct intersegment call to segment
{\tt 400}, offset {\tt 1234}.  \\
        \verb@1234 S#) FAR CALL@ & The four bytes starting at location
1234 contains the segment/offset for a \id|FAR| call.  \\
        \verb@0 [BX] FAR CALL@ & {\tt BX} points to the segment/offset
double word.  \end{tabular}
 $$
\noindent Similar considerations apply to \id|JMP| (same addressing modes).


\section{Using machine language routines in Forth}

Some the of resources of the 8086 microprocessor are used in running the Forth
{\sl virtual machine}, and the assembler has been complemented by words
that make reference to these resources convenient.

In particular, Forth uses the {\tt SI} register for its {\sl Instruction
Pointer} and the {\tt BP} register for its {\sl Return-stack Pointer\/};
the words \id|IP| and \id|RP| have been introduced as synonyms
for, respectively {\tt SI} and {\tt BP}.  These registers (as well as
{\tt CS}, {\tt SS}, {\tt DS}, and the data direction flag) must be
maintained across Forth words (i.e., any {\sc code} word that changes
them must restore them before returning control to the inner
interpreter (see below).  All other registers (including
{\tt ES}) may be used freely by Forth {\sc code} words.

We shall discuss later on the mechanism of the Forth inner
interpreter\index{Forth/inner interpreter}, which constitutes the Forth
virtual machine.  For the moment, it will be more useful to give some
examples of typical {\sc code} words,\index{Forth/code{\sc code}} taken from the file
\iprog{KERNEL86.4TH}.


        \begin{verbatim}
\ Drop the top element of the stack

  CODE DROP ( n) 
   AX POP     \ Pop one element off data stack (8086 stack)
     NEXT     \ Return control to the inner interpreter.
   END-CODE   \ Exit the assembler mode of interpretation\end{verbatim}
        Note that \id|NEXT| is a macro. It assembles a jump to a piece of machine
code---the actual inner interpreter---located at an address which we
shall symbolically call \id|>NEXT|.

        \begin{verbatim}
\ Fetch a 16-bit value from addr

             CODE @ ( addr -- n) 
         BX POP   
    0 [BX] PUSH  
   NEXT  END-CODE\end{verbatim}

        \begin{verbatim}
\ Store a 16-bit value at addr

             CODE ! ( n addr) 
         BX POP   
     0 [BX] POP   
   NEXT  END-CODE\end{verbatim}
        Note that {\tt [BX]} needs a displacement as an argument, even though
we only wanted a displacement of zero.

\begin{verbatim}
\ Duplicate top of stack

             CODE DUP ( n -- n n) 
         AX POP
        AX PUSH  
          1PUSH     \ Push AX, return to inner interpreter
         END-CODE\end{verbatim}
        The macro \id|1PUSH| compiles a jump to location \id|APUSH|---which is located just
before \id|>NEXT| and contains the instruction \id|AX PUSH|.

        \begin{verbatim}
\ Exchange top two elements of stack 

             CODE SWAP ( n n' -- n' n)  
         DX POP   
         AX POP
          2PUSH     \ Push DX and AX, return to inn. interpr.
         END-CODE\end{verbatim}
        The macro \id|2PUSH| compiles a jump to location \id|DPUSH|---which is located
just before \id|APUSH| and contains the instruction \id|DX PUSH|.

        \begin{verbatim}
\ Copy second element from top 

             CODE OVER ( n n' -- n n' n)  
         DX POP   
         AX POP
        AX PUSH
          2PUSH
         END-CODE\end{verbatim}

        \begin{verbatim}
\ Replace top two elements by their sum

             CODE + ( n n' -- n+n') 
         BX POP
         AX POP
      BX AX ADD
          1PUSH
         END-CODE\end{verbatim}

        \begin{verbatim}
\ Replace top 2 elements by their difference

             CODE - ( n n' -- n-n') 
         BX POP
         AX POP
      BX AX SUB
          1PUSH
         END-CODE\end{verbatim}
        Note that \id|BX AX SUB| means ``subtract {\tt BX} from {\tt AX}
and leave the result in {\tt AX}.''  This is a bit awkward, since the
order of the arguments in the assembler code is the inverse of the usual
one, but is a consequence of interchanging the order that Intel uses in
their menmonics.  Attention should be paid to this notational quirk.

The same problem arises with the compare instruction, \id|CMP|. Let's
define two pieces of code that return on the stack the quantities \id|TRUE|
and \id|FALSE|:
        \begin{verbatim}
            LABEL YES
    -1 # AX MOV
          1PUSH
            LABEL NO
     0 # AX MOV
          1PUSH\end{verbatim}
        We then define the Forth words \id|<| and \id|>|:
        \begin{verbatim}
\ Return TRUE if n<n'

             CODE <  ( n n' -- flag) 
         AX POP
         BX POP
      AX BX CMP
         YES JL     
      NO #) JMP     
         END-CODE\end{verbatim}

        \begin{verbatim}
\ Return TRUE if n>n'

             CODE >  ( n n' -- flag) 
         AX POP
         BX POP
      AX BX CMP
         YES JG 
      NO #) JMP     
         END-CODE\end{verbatim}
After the instruction \id|AX BX CMP| in the code for \id|<| , the conditional jump
\id|YES JL| will occur only if {\tt BX} is less than {\tt AX}, which
is the opposite of what one might expect. But by assigning {\tt AX} to
{\tt n'} and {\tt BX} to {\tt n} we interchanged the order of the arguments, and
the overall test for ``less than'' works fine.

Note that conditional jumps do not take a usual argument, but just
an address on the stack.

\section{The inner interpreter}\label{inner-interp}

And now we come to the machine code which makes up the inner interpreter.\index{Forth/inner interpreter}
Of course this code was not produced by the Forth assembler (which
wouldn't be able to run if the inner interpreter weren't already in
place), but by the {\sl meta-assembler\/}---a tool
available to the metacompiler during system
generation (see Section \ref{meta}). However, you might want to write your own customized
version of the inner interpreter (for instance, for debugging purposes)
and switch to it when desired. For this reason, in the version that
follows we have avoided using meta-assembler constructs.
        \begin{verbatim}
            LABEL DPUSH \ Label for jump in 2PUSH macro
        DX PUSH
          ( LABEL APUSH) \ Target location for jump
                         \   in 1PUSH macro
        AX PUSH
          ( LABEL >NEXT) \ Target location for jump
                         \   in >NEXT macro
        AX LODS          \ These three lines are the inner interpreter
       AX W MOV          \   A detailed explanation
      0 [W] JMP          \   is given below\end{verbatim}
        The word \id|W| which appears above is a synonym for {\tt BX}; in the
Forth virtual machine, this register is used as the {\sl Word pointer}.
The appropriateness of this appellation will become apparent.

Note that we didn't insert actual labels to mark locations \id|APUSH|
and \id|>NEXT|, since we wanted contiguous machine code. We make that
up with the following:
        \begin{verbatim}
    DPUSH 1+ CONSTANT APUSH  \ to mimic LABEL APUSH
    DPUSH 2+ CONSTANT >NEXT  \ to mimic LABEL >NEXT\end{verbatim}
        
And then we define the macros that we use all the time:
        \begin{verbatim}
                  : 2PUSH
     DPUSH #) JMP ;
                  : 1PUSH
     APUSH #) JMP ;
                  : NEXT
     >NEXT #) JMP ;\end{verbatim}
If we replace by brute force the contents of locations \id|>NEXT| and
following by a jump to our own custom inner interpreter,
we can make a Forth program do all sorts of strange things!
This is in fact how the Forth \id|DEBUG| utility works.

\medskip

The actual code for the inner interpreter is in the three lines
following the comment \id|( LABEL >NEXT)|. It begins by picking up a
word at the location pointed to by the Forth \id|IP| (instruction
pointer) register (i.e., the 8086's {\tt SI} register).

A Forth {\sc colon} word (i.e., one compiled using \id|:|) is essentially a list of
pointers to other Forth words.\index{Forth/compiler} The {\tt IP} normally sits pointing to
the word in the list after the one that is currently being executed.
By entering \id|>NEXT|, we turn our attention to this next word. Its
address is copied into {\tt AX} by an \id|AX LODS| instruction.  This
instruction also increments the {\tt IP} by 2, so that it is left
pointing to the ``new'' next word in our list.

As a first approximation, Forth replaces a series of machine-language
subroutine calls with a list of addresses to branch to, and an
inner-interpreter which gets the next address on the list and branches
to it.  When this routine is done, it returns to the inner interpreter.
If this were the whole story, we would simply be saving a little space
(the missing \id|CALL| instructions) at the expense of a little time
(the overhead in performing the \id|CALL| simulation).

What is actually done is only slightly more complicated than this.
Instead of getting the next address and jumping to it, we jump
indirectly via it (\id|AX W MOV  0 [W] JMP|).  What this means is
that instead of a list of addresses to be branched to, we have a list
of pointers to Forth words.  Each of these Forth words in turn
contains the actual address to branch to in order to execute that
word, as well as some parameter information of interest to the
execution routine.  For instance, suppose \id|SCR| is a Forth {\sc variable}.
Then our list might contain a pointer to \id|SCR|'s first cell
(called the {\sl code field}\index{Forth/code field}), which in turn
points to the code which is shared by all {\sc variable}'s.\index{Forth/variable{\sc variable}}  This code uses
the contents of the {\tt W} register, which still points to
\id|SCR|'s code field which is being executed, to construct a pointer to
\id|SCR|'s data cell; it is this pointer that is then left on the stack,
as the result of calling \id|SCR|.

\medskip

In a {\sc code} word,
the code field is followed by  executable machine code and points
directly to the first instruction of it.

In a {\sc colon} word, the code field is followed by a list of data
cells containing addresses of other words. Many of these words were
produced by another {\sc colon} definition, and thus contain in turn
list of addresses of other words: the definition was
recursive, and the execution must be recursive as well.\footnote
        {\label{foot.recursive}`Recursive' here means that at each level of the calling
hierarchy a new copy of the defining or executing mechanism is created
and activated, so that many copies of this mechanism may be active at
the same time---each having progressed a certain way through its task.
In the Forth word {\tt RECURSE} and {\tt RECURSIVE}, explained in the
Glossary, the term `recursive' is used in a more limited sense, i.e., it
refers to words that call {\em themselves} rather than some other word;
since Forth temporarily masks out the name of the word that is undergoing definition,
if one want to refer to just that word one must ``unmask'' it.}
        To achieve this purpose, as soon as activated the {\sc colon}
interpreter\index{Forth/interpreter} (i.e., the code pointed to by a {\sc colon} word's code
field) parks in the return stack the currently active value of {\tt IP}
(which was pointing to the next cell in the list being processed by its
caller), loads {\tt IP} with the address of the first cell of its own list,
and jumps to \id|>NEXT| (the inner interpreter).  Eventually we will
arrive at a {\sc CODE} word\index{Forth/code{\sc code}}, which we can execute directly.  At the end
of each {\sc colon} list we will usually find an ``end of list'' word,
called \id|UNNEST|, which will pop the return stack into the {\tt IP}
and make us climb up one recursion level.

In conclusion, all that the inner interpreter does is ``find the
next word and execute it.''


\section{Structured programming}

In conventional assemblers, program-flow control is achieved by means of
jumps or calls to suitably labeled locations.  Forth-style assemblers
prefer structured control constructs (such as \id|IF|\ldots\id|ELSE|\ldots\id|THEN|).
Structuring leads to clearer code and fewer errors; what is more,
structured style lends itself quite naturally to the incremental,
one-pass compilation approach of Forth. 

The control constructs used in the Forth assembler are analogous to
those used in Forth itself. However, the machine-language conditional
jumps compiled by the assembler will, at run time, test the processor
status register rather than the Forth data stack (as is done by Forth
\id|IF|) or some other registers of the Forth virtual machine (as
is done by Forth \id|LOOP|).

For example, the following assembler excerpt
        \begin{verbatim}
\ Wait for ready flag 

                  382 CONSTANT PORTC
                          CODE ?OK
        PORTC # DX MOV BEGIN
                  DX AL IN
     80 # AL TEST  0<> UNTIL
                        NEXT 
                    END-CODE\end{verbatim}
should produce the same code as (in Intel style)
        \begin{verbatim}
         MOV  DX,#382
  START: IN   AL,DX
         TEST AL,#80
         JZ   START
         JMP  >NEXT\end{verbatim}
        where \id|>NEXT| is a label.

\medskip

The following conditions can be tested
        \begin{equation}
\begin{tabular}[t]{|r|l|} \hline
\id|<| & less \\ \hline
\id|>| & greater \\ \hline
\id|<=| & less/equal \\ \hline
\id|>=| & greater/equal \\ \hline \hline
\id|0=| & zero \\ \hline
\id|0<>| & nonzero \\ \hline
\id|0<| & negative \\ \hline
\id|0>=| & nonnegative \\ \hline
\id|=| & synonym for \id|0=| \\ \hline
\id|<>| & synonym for \id|0<>| \\ \hline 
\end{tabular}\quad
\begin{tabular}[t]{|r|l|} \hline
\id|U<| & unsigned \id|<| \\ \hline
\id|U>| & unsigned \id|>| \\ \hline
\id|U<=| & unsigned \id|<=| \\ \hline
\id|U>=| & unsigned \id|>=| \\ \hline \hline
\id|OV| & overflow \\ \hline
\id|NOV| & no overflow \\ \hline
\id|CARRY| & carry set \\ \hline
\id|NCARRY| & carry clear \\ \hline
\id|EVENL| & low byte is even \\ \hline
\id|ODDL| & low byte is odd \\ \hline
\id|CXNZ| & {\tt CX} register $\neq$ zero \\ \hline
\end{tabular}
\label{app-cond}
        \end{equation}
(note that \id|EVENL| and \id|ODDL| sense whether there is an even or odd {\em number of 1s}
in the byte, not just whether the byte is evenly divisible by 2).

In a similar way one could have, say,
        \begin{verbatim}
    BEGIN ... U< WHILE ... REPEAT\end{verbatim}
        or
        \begin{verbatim}
    OV IF ... ELSE ... THEN\end{verbatim}
        These conditionals can be arbitrarily nested.

The construct
        \begin{verbatim}
   234 DO ... LOOP\end{verbatim}
can be used to execute some piece of code 234 times---the
index is in the {\tt CX} register, starting off at 234 and being
decremented by 1 each time \id|LOOP| is executed.  If the count is
already in {\tt CX}, the construct
        \begin{verbatim}
    HERE ... LOOP\end{verbatim}
        can be used.  Since there is only one {\tt CX} register, it
must be pushed on the stack or otherwise saved in order to perform
nested \id|DO| loops:
        \begin{verbatim}
            234 DO 
             ...
         CX PUSH
           40 DO
           ...
            LOOP
          CX POP
           ... 
              LOOP\end{verbatim}

\section{Simple examples}

{\sc Example} 1:\quad {\sl Count the number of \id|1| bits in some range of
memory locations}.

\smallskip

Assume that \id|BIT-COUNT-TABLE| is a Forth word that returns the
starting address of a table 256 bytes long, already initialized to contain the
number of \id|1|s in the binary numbers from 0 to 255 (thus, its entries are 0 1 1
2 ... 6 7 7 8).

The following Forth {\sc code} word makes use of this table to count the
number of \id|1|s in a given area of memory:
        \begin{verbatim}
                        CODE COUNT-BITS 
    CX POP  DI POP  ES POP     ( segm offs len -- count)
      DX DX XOR  AH AH XOR
  BIT-COUNT-TABLE # BX MOV
                      HERE
  ES: 0 [DI] AL MOV XLAT
               AX DX ADD
               DI INC LOOP
             DX PUSH  NEXT  
                    END-CODE\end{verbatim}
        We begin by putting the length in {\tt CX}, which will be decremented
by \id|LOOP| in order to keep track of how many times the loop has
been executed (\id|LOOP| keeps looping until it decrements {\tt CX}
to zero).  We use {\tt DI} to point to the next byte to be examined
(we initialize it to point to the first byte to be examined).  We
allow the section of memory to be examined to lie in any segment, and
use the {\tt ES} segment register to hold the segment specified.  {\tt DX} will contain
our running total of \id|1| bits, and is initialized to zero.  {\tt AH}
is initialized to zero, and will remain zero since the \id|XLAT|
instruction will only affect {\tt AL}.  {\tt BX} is initialized to point to the
\id|BIT-COUNT-TABLE| for the benefit of the \id|XLAT| instruction.

The body of the loop consists of four instructions: (a) Pick up the byte
pointed to by {\tt ES:DI} (note the use of a segment override prefix
to make the data access relative to the {\tt ES} segment, rather than
the default {\tt DS} segment);  (b) Look up the bit-count using the
\id|XLAT| instruction (replace {\tt AL} with the byte from the table
pointed to by {\tt BX} that corresponds to {\tt AL}'s original value);
(c) Add the bit-count to the running total being kept in {\tt DX};
and (d) Make {\tt DI} point to the next byte to be examined.

When the loop is done, the result contained in {\tt DX} is pushed onto
the stack, and we return to the inner interpreter.

\medskip

\noindent {\sc Example} 2: {\sl Call a BIOS function to send a character to
a communications port}.

\smallskip

The fact that the machine stack is the same as the Forth parameter
stack makes it very easy to build machine-language words
which make BIOS or DOS functions immediately available as part of
Forth. 
\begin{verbatim}
    HEX
                   CODE COM-EMIT
       DX POP  AX POP     ( char port# -- status flag)
           1 # AH MOV
               14 INT
                  CWD
           AX DX XCHG
                2PUSH
             END-CODE\end{verbatim}
        Look at the \pc\ {\sl Technical Reference} manual for details about BIOS
functions.  The parameter information for the call is arranged in the
appropriate registers, and then we call the BIOS function by issuing a
soft interrupt.  After exiting this function, the high-order bit of
{\tt AX} is set if the routine was unable to transmit the byte of data
over the line; the rest of {\tt AH} contains the status of the port,
and {\tt AL} still contains the character.

The order of the arguments to our word is conventional: source
followed by destination.  The \id|CWD| instruction converts a 16-bit
word in the {\tt AX} register into a double word by extending its sign
bit throughout {\tt DX}---thus {\tt DX} becomes a Forth logical flag.  We exchange
{\tt AX} and {\tt DX} so that we can use \id|2PUSH| to put the flag
and status information on the stack with the flag on top, which will
be the most useful order for subsequent use.  Notice that the low byte
of our status word still contains the byte we were trying to send, while
our \id|COM-EMIT| word ignores the high byte of its character
argument, so that it's very easy to use this word in a loop that retries
the operation.

\medskip

For further examples, look at the source code in the files
\iprog{KERNEL86.4TH}, \iprog{CAM-IO.4TH}, and \iprog{CAM-BUF.4TH}.  The file
\iprog{CAM-INT.4TH} contains the source code for a long interrupt routine
(the one that interacts with \cam\ every 60-th of a second to
control its operation).  This source provides a good example of how to
use Forth as a macro assembler.

\section{Notes and thoughts on the F83 Assembler}

        \begin{enumerate} 
        \item Some additional constants have been defined to
complete the set of condition codes used as branch conditions in the
July 1984 version of F83, namely \id|NOV| (={\tt 70}), \id|CARRY| ({\tt =73}),
\id|NCARRY| (={\tt 72}), \id|EVENL| (={\tt 7B}), \id|ODDL| (={\tt 7A}), and
\id|CXNZ| (={\tt E3}); moreover, \id|=| and \id|<>| have been added as synonyms for
\id|0=| and \id|0<>| respectively.
        \item Reversing the roles of \id|#)| and \id|S#)| in {\tt FAR CALL}'s
would lead to a more regular mnemonic interpretation of \id|#)| across
the entire instruction set. The current assignment of meaning to these two words
has been acknowledged as awkward by the authors of F83, and may be revised
in a later version of F83.
        \item We have added a defining word \id|SUBR| which makes
self-compiling subroutines.
        \begin{verbatim}
                               : SUBR  
        CREATE ASSEMBLER DOES>
                       #) CALL ;\end{verbatim}
        In this way, after the definition
        \begin{verbatim}
                            SUBR GET1
                       1 AL IN
                   2 # AL TEST
                           RET\end{verbatim}
        any occurrence of \id|GET1| compiles a subroutine call to the
above code whenever it appears in a {\tt CODE} word.
        \item The meaning of the condition-code words in the
\id|ASSEMBLER| vocabulary used in comparisons could be exchanged between
elements of a pair such as \id|>| and \id|<|, so that one could write
the two compared quantities in the traditional Forth order.  For example
\id|AX BX CMP < IF|$\langle{\rm action}\rangle$\id|THEN| would execute
$\langle{\rm action}\rangle$ if {\tt AX} is less than {\tt BX}.  (The
meaning of condition codes after a \id|SUB| works fine; the effect of
\id|CMPS| and \id|SCAS| on comparisons changes correspondingly.)
        \end{enumerate}

\section{Instruction templates}\label{templates}

{\def\gap{\qquad}
 \def\dent{\quad}


Here we give templates for all legal 8086 Forth assembler instructions.

\medskip

Pairs of lower-case letters are used to stand for appropriate arguments,
according to the following table (for example, {\tt rx} stands for any
of the four general-purpose word registers {\tt AX}, {\tt BX}, {\tt CX},
or {\tt DX}):

\medskip
\par\noindent
\par$\null$\verb|rx| $\to$ \verb|AX BX CX DX|\quad (general register, restricted choice)
\par$\null$\verb|sr| $\to$ \verb|CS DS ES SS| \quad (segment register)
\par$\null$\verb|rr| $\to$ \verb|AX BX CX DX AH AL BH BL CH CL DH DL|\quad (general register)
\par$\null$\verb|xx| $\to$ \verb|SI DI BP BX BX+SI BX+DI BP+SI BP+DI|\quad (index register)
\par$\null$\verb|mm| $\to$ a one-word address
\par$\null$\verb|ss| $\to$ a one-word segment number
\par$\null$\verb|dd| $\to$ a one-word displacement
\par$\null$\verb|ii| $\to$ a one-word value
\par$\null$\verb|bb| $\to$ a one-byte value

\medskip
\par\noindent
As an example, the instruction \prog{SS 20 [BX+SI] MOV} follows the template

\par\prog{sr dd [xx] MOV}.

\bigskip

With these conventions, we now list all legal instructions:

\medskip
{\small
\par$\null$\verb|              AAA| \gap ASCII adjust for add
\par$\null$\verb|              AAD| \gap ASCII adjust for division
\par$\null$\verb|              AAM| \gap ASCII adjust for multiplication
\par$\null$\verb|              AAS| \gap ASCII adjust for subtraction

\par$\null$\verb|        rr rr ADC| \gap Add with carry
\par$\null$\verb|     rr mm #) ADC|
\par$\null$\verb|     mm #) rr ADC|
\par$\null$\verb|   rr dd [xx] ADC|
\par$\null$\verb|   dd [xx] rr ADC|
\par$\null$\verb|      ii # rr ADC|
\par$\null$\verb|   ii # mm #) ADC|
\par$\null$\verb| ii # dd [xx] ADC|

\par$\null$\verb|        rr rr ADD| \gap Add
\par$\null$\verb|     rr mm #) ADD|
\par$\null$\verb|     mm #) rr ADD|
\par$\null$\verb|   rr dd [xx] ADD|
\par$\null$\verb|   dd [xx] rr ADD|
\par$\null$\verb|      ii # rr ADD|
\par$\null$\verb|   ii # mm #) ADD|
\par$\null$\verb| ii # dd [xx] ADD|

\par$\null$\verb|        rr rr AND| \gap Logical {\sc and} (clears carry flag, overflow flag)
\par$\null$\verb|     rr mm #) AND|
\par$\null$\verb|     mm #) rr ADD|
\par$\null$\verb|   rr dd [xx] AND|
\par$\null$\verb|   dd [xx] rr ADD|
\par$\null$\verb|      ii # rr AND|
\par$\null$\verb|   ii # mm #) AND|
\par$\null$\verb| ii # dd [xx] AND|

\par$\null$\verb|       mm #) CALL| \gap Call procedure (pushes return addr) 
\par$\null$\verb|      dd S#) CALL|
\par$\null$\verb|          rx CALL|
\par$\null$\verb|     dd [xx] CALL|
\par$\null$\verb| dd [xx] FAR CALL|
\par$\null$\verb|mm ss #) FAR CALL|
\par$\null$\verb|  mm S#) FAR CALL|

\par$\null$\verb|              CBW| \gap Convert byte to word (extend sign bit of {\tt AL} thru {\tt AH})
\par$\null$\verb|              CLC| \gap Clear carry flag
\par$\null$\verb|              CLD| \gap Clear direction flag
\par$\null$\verb|              CLI| \gap Clear interrupt enable flag (turns off interrupts)
\par$\null$\verb|              CMC| \gap Complement carry flag

\par$\null$\verb|        rr rr CMP| \gap Compare dest with source (used with conditional jumps
\par$\null$\verb|     rr mm #) CMP| \gap\dent such as {\tt JG}, and with structured conditionals
\par$\null$\verb|     mm #) rr CMP| \gap\dent such as {\tt IF}, {\tt WHILE}, etc.)
\par$\null$\verb|   rr dd [xx] CMP| \gap\dent Note that the order of arguments is the opposite
\par$\null$\verb|   dd [xx] rr CMP| \gap\dent of what you might expect from Forth:
\par$\null$\verb|      ii # rr CMP| \gap\dent after {\tt AX BX CMP}, a {\tt JG} (jump if greater-than)
\par$\null$\verb|   ii # mm #) CMP| \gap\dent would be executed if {\tt BX} is greater than {\tt AX}.
\par$\null$\verb| ii # dd [xx] CMP|

\par$\null$\verb|        BYTE CMPS| \gap Compare bytes; {\tt DS:SI}=src, {\tt ES:DI}=dest, 
\par$\null$\verb|             CMPS| \gap Compare words; postincrement {\tt SI} and {\tt DI}.
\par$\null$\verb|              CWD| \gap Convert word to double word (extend {\tt AX} sign thru {\tt DX})

\par$\null$\verb|              DAA| \gap Decimal adjust for addition
\par$\null$\verb|              DAS| \gap Decimal adjust for subtraction

\par$\null$\verb|        mm #) DEC| \gap Decrement by one
\par$\null$\verb|      dd [xx] DEC|
\par$\null$\verb|           rr DEC|
\par$\null$\verb|           SP DEC|
\par$\null$\verb|           BP DEC|
\par$\null$\verb|           SI DEC|
\par$\null$\verb|           DI DEC|

\par$\null$\verb|           rr DIV| \gap Divide unsigned: if divisor is a byte operand,
\par$\null$\verb|   BYTE mm #) DIV| \gap\dent then {\tt AL}={\tt AX}/source, {\tt AH}=remainder.  If word op,
\par$\null$\verb|        mm #) DIV| \gap\dent then {\tt AX}={\tt DX:AX}/source, {\tt DX}=remainder.
\par$\null$\verb| BYTE dd [xx] DIV|
\par$\null$\verb|      dd [xx] DIV|

\par$\null$\verb|         rx 0 ESC| \gap Escape for instruction to coprocessor
\par$\null$\verb|         rx 1 ESC|
\par$\null$\verb|         rx 2 ESC|
\par$\null$\verb|         rx 3 ESC|
\par$\null$\verb|         rx 4 ESC|
\par$\null$\verb|         rx 5 ESC|
\par$\null$\verb|         rx 6 ESC|
\par$\null$\verb|         rx 7 ESC|
\par$\null$\verb|      mm #) 0 ESC|
\par$\null$\verb|      mm #) 1 ESC|
\par$\null$\verb|      mm #) 2 ESC|
\par$\null$\verb|      mm #) 3 ESC|
\par$\null$\verb|      mm #) 4 ESC|
\par$\null$\verb|      mm #) 5 ESC|
\par$\null$\verb|      mm #) 6 ESC|
\par$\null$\verb|      mm #) 7 ESC|
\par$\null$\verb|    dd [xx] 0 ESC|
\par$\null$\verb|    dd [xx] 1 ESC|
\par$\null$\verb|    dd [xx] 2 ESC|
\par$\null$\verb|    dd [xx] 3 ESC|
\par$\null$\verb|    dd [xx] 4 ESC|
\par$\null$\verb|    dd [xx] 5 ESC|
\par$\null$\verb|    dd [xx] 6 ESC|
\par$\null$\verb|    dd [xx] 7 ESC|

\par$\null$\verb|              HLT| \gap Halt and wait for interrupt

\par$\null$\verb|          rr IDIV| \gap Signed divide: see {\tt DIV}
\par$\null$\verb|  BYTE mm #) IDIV|
\par$\null$\verb|       mm #) IDIV|
\par$\null$\verb|BYTE dd [xx] IDIV|
\par$\null$\verb|     dd [xx] IDIV|

\par$\null$\verb|          rr IMUL| \gap Multiply signed.  For byte operand, 
\par$\null$\verb|  BYTE mm #) IMUL| \gap\dent {\tt AX}={\tt AL}\by{}source.   For word operand,
\par$\null$\verb|       mm #) IMUL| \gap\dent {\tt DX:AX}={\tt AX}\by{}source.
\par$\null$\verb|BYTE dd [xx] IMUL|
\par$\null$\verb|     dd [xx] IMUL|

\par$\null$\verb|         bb AL IN| \gap Input from port
\par$\null$\verb|         bb AX IN|
\par$\null$\verb|         DX AL IN|
\par$\null$\verb|         DX AX IN|

\par$\null$\verb|   BYTE mm #) INC| \gap Increment by one
\par$\null$\verb|        mm #) INC|
\par$\null$\verb| BYTE dd [xx] INC|
\par$\null$\verb|      dd [xx] INC|
\par$\null$\verb|           rr INC|
\par$\null$\verb|           SP INC|
\par$\null$\verb|           BP INC|
\par$\null$\verb|           SI INC|
\par$\null$\verb|           DI INC|

\par$\null$\verb|           bb INT| \gap Interrupt
\par$\null$\verb|             INTO| \gap Interrupt (4) if overflow
\par$\null$\verb|             IRET| \gap Return from interrupt (restores flags from stk)

\par$\null$\verb|            dd JA| \gap Jump if above (unsigned)
\par$\null$\verb|           dd JAE| \gap Jump if above or equal (unsigned)
\par$\null$\verb|            dd JB| \gap Jump if below (unsigned)
\par$\null$\verb|           dd JBE| \gap Jump if below or equal (unsigned)
\par$\null$\verb|          dd JCXZ| \gap Jump if {\tt CX} register is zero
\par$\null$\verb|            dd JE| \gap Jump if equal (zero flag = 1)
\par$\null$\verb|            dd JG| \gap Jump if greater (signed)
\par$\null$\verb|           dd JGE| \gap Jump if greater or equal (signed)
\par$\null$\verb|            dd JL| \gap Jump if less (signed)
\par$\null$\verb|           dd JLE| \gap Jump if less or equal (signed)
\par$\null$\verb|        mm #) JMP| \gap Jump unconditionally
\par$\null$\verb|       dd S#) JMP|
\par$\null$\verb|           rr JMP|
\par$\null$\verb|      dd [xx] JMP|
\par$\null$\verb|  dd [xx] FAR JMP|
\par$\null$\verb| mm ss #) FAR JMP|
\par$\null$\verb|   mm S#) FAR JMP|
\par$\null$\verb|           dd JNE| \gap Jump if not equal (zero flag = 0)
\par$\null$\verb|           dd JNO| \gap Jump if no overflow (ovrflw flag = 0)
\par$\null$\verb|           dd JNS| \gap Jump if not sign (sign flag = 0)
\par$\null$\verb|            dd JO| \gap Jump if overflow (overflow flag = 1)
\par$\null$\verb|           dd JPE| \gap Jump if parity even (parity flag = 1)
\par$\null$\verb|           dd JPO| \gap Jump if parity odd (parity flag = 0)
\par$\null$\verb|            dd JS| \gap Jump if sign (sign flag = 1)

\par$\null$\verb|             LAHF| \gap Load {\tt AH} from low byte of flags
\par$\null$\verb|    mm S#) rx LDS| \gap Load double-word pointer from memory into {\tt DS}:rx
\par$\null$\verb|     mm #) rx LEA| \gap Load effective address
\par$\null$\verb|   dd [xx] rx LEA|
\par$\null$\verb|    mm S#) rx LES| \gap Load double-word pointer from memory into {\tt ES}:{\tt rx}
\par$\null$\verb|        BYTE LODS| \gap Load string byte at {\tt DS:SI} into {\tt AL} (postincr.)
\par$\null$\verb|             LODS| \gap Load string word at {\tt DS:SI} into {\tt AX} (postincr.)
\par$\null$\verb|          dd LOOP| \gap Decrement {\tt CX} by 1 and jump if not zero
\par$\null$\verb|         dd LOOPE| \gap Loop while equal (zero flag = 1, {\tt CX} $\neq$ 0)
\par$\null$\verb|        dd LOOPNE| \gap Loop while not equal

\par$\null$\verb|        rr rr MOV| \gap Move from source to destination
\par$\null$\verb|     rr mm #) MOV|
\par$\null$\verb|     mm #) rr MOV|
\par$\null$\verb|   ii # mm #) MOV|
\par$\null$\verb|   rr dd [xx] MOV|
\par$\null$\verb|   dd [xx] rr MOV|
\par$\null$\verb| ii # dd [xx] MOV|
\par$\null$\verb|      ii # SP MOV|
\par$\null$\verb|      ii # BP MOV|
\par$\null$\verb|      ii # SI MOV|
\par$\null$\verb|      ii # DI MOV|
\par$\null$\verb|    dd S#) AL MOV| \gap (byte to {\tt AL}, address rel to seg start)
\par$\null$\verb|    dd S#) AX MOV| \gap (word to {\tt AX}, address rel to seg start)
\par$\null$\verb|    AL dd S#) MOV| \gap ({\tt AL}, address rel to seg start)
\par$\null$\verb|    AX dd S#) MOV| \gap ({\tt AX}, address rel to seg start)
\par$\null$\verb|        rr sr MOV|
\par$\null$\verb|     mm #) sr MOV|
\par$\null$\verb|   dd [xx] sr MOV|
\par$\null$\verb|        sr rr MOV|
\par$\null$\verb|     sr mm #) MOV|
\par$\null$\verb|   sr dd [xx] MOV|

\par$\null$\verb|        BYTE MOVS| \gap Move string byte; {\tt DS:SI}=src, {\tt ES:DI}=dest
\par$\null$\verb|             MOVS| \gap Move string word (postincrement {\tt SI} and {\tt DI})

\par$\null$\verb|           rr MUL| \gap see {\tt IMUL}
\par$\null$\verb|   BYTE mm #) MUL|
\par$\null$\verb|        mm #) MUL|
\par$\null$\verb| BYTE dd [xx] MUL|
\par$\null$\verb|      dd [xx] MUL|

\par$\null$\verb|           rr NEG| \gap Negate (subtract from zero)
\par$\null$\verb|   BYTE mm #) NEG|
\par$\null$\verb|        mm #) NEG|
\par$\null$\verb| BYTE dd [xx] NEG|
\par$\null$\verb|      dd [xx] NEG|

\par$\null$\verb|              NOP| \gap No operation

\par$\null$\verb|           rr NOT| \gap Logical {\sc not} (ones' complement)
\par$\null$\verb|   BYTE mm #) NOT|
\par$\null$\verb|        mm #) NOT|
\par$\null$\verb| BYTE dd [xx] NOT|
\par$\null$\verb|      dd [xx] NOT|

\par$\null$\verb|         rr rr OR| \gap Logical {\sc or} (clears carry, overflow flags)
\par$\null$\verb|      rr mm #) OR|
\par$\null$\verb|      mm #) rr OR|
\par$\null$\verb|    rr dd [xx] OR|
\par$\null$\verb|    dd [xx] rr OR|
\par$\null$\verb|       ii # rr OR|
\par$\null$\verb|    ii # mm #) OR|
\par$\null$\verb|  ii # dd [xx] OR|

\par$\null$\verb|        bb AL OUT| \gap Output to port
\par$\null$\verb|        bb AX OUT|
\par$\null$\verb|        DX AL OUT|
\par$\null$\verb|        DX AX OUT|

\par$\null$\verb|        mm #) POP| \gap Pop word from stack (postincrement {\tt SP})
\par$\null$\verb|      dd [xx] POP|
\par$\null$\verb|           rr POP|
\par$\null$\verb|           sr POP|
\par$\null$\verb|           SP POP|
\par$\null$\verb|           BP POP|
\par$\null$\verb|           SI POP|
\par$\null$\verb|           DI POP|

\par$\null$\verb|             POPF| \gap Pop flags from stack

\par$\null$\verb|       mm #) PUSH| \gap Push word onto stack (predecrement {\tt SP})
\par$\null$\verb|     dd [xx] PUSH|
\par$\null$\verb|          rr PUSH|
\par$\null$\verb|          sr PUSH|
\par$\null$\verb|          SP PUSH|
\par$\null$\verb|          BP PUSH|
\par$\null$\verb|          SI PUSH|
\par$\null$\verb|          DI PUSH|

\par$\null$\verb|            PUSHF| \gap Push flags onto stack

\par$\null$\verb|           rr RCL| \gap Rotate thru carry left by one position
\par$\null$\verb|        mm #) RCL|
\par$\null$\verb|      dd [xx] RCL|
\par$\null$\verb|        rr CL RCL| \gap Rotate thru carry left by CL positions
\par$\null$\verb|     mm #) CL RCL|
\par$\null$\verb|   dd [xx] CL RCL|

\par$\null$\verb|           rr RCR| \gap Rotate thru carry right by one position
\par$\null$\verb|        mm #) RCR|
\par$\null$\verb|      dd [xx] RCR|
\par$\null$\verb|        rr CL RCR| \gap Rotate thru carry right by {\tt CL} positions
\par$\null$\verb|     mm #) CL RCR|
\par$\null$\verb|   dd [xx] CL RCR|

\par$\null$\verb|              RET| \gap Return from proceedure
\par$\null$\verb|          FAR RET| \gap Return from {\tt FAR} proceedure
\par$\null$\verb|          ii +RET| \gap Return and pop ii items off stack
\par$\null$\verb|     ii  FAR +RET| \gap Return {\tt FAR} and pop items

\par$\null$\verb|           rr ROL| \gap Rotate left by 1 position
\par$\null$\verb|        mm #) ROL|
\par$\null$\verb|      dd [xx] ROL|
\par$\null$\verb|        rr CL ROL| \gap Rotate left by {\tt CL} positions
\par$\null$\verb|     mm #) CL ROL|
\par$\null$\verb|   dd [xx] CL ROL|

\par$\null$\verb|           rr ROR| \gap Rotate right by 1 position
\par$\null$\verb|        mm #) ROR|
\par$\null$\verb|      dd [xx] ROR|
\par$\null$\verb|        rr CL ROR| \gap Rotate right by {\tt CL} positions
\par$\null$\verb|     mm #) CL ROR|
\par$\null$\verb|   dd [xx] CL ROR|

\par$\null$\verb|             SAHF| \gap Store {\tt AH} into low byte of flags

\par$\null$\verb|           rr SAL| \gap Shift arithmetic left by one (zero fill)
\par$\null$\verb|        mm #) SAL|
\par$\null$\verb|      dd [xx] SAL|
\par$\null$\verb|        rr CL SAL| \gap Shift arithmetic left by {\tt CL}  (zero fill)
\par$\null$\verb|     mm #) CL SAL|
\par$\null$\verb|   dd [xx] CL SAL|

\par$\null$\verb|           rr SAR| \gap Shift arithmetic right by one (sign fill)
\par$\null$\verb|        mm #) SAR|
\par$\null$\verb|      dd [xx] SAR|
\par$\null$\verb|        rr CL SAR| \gap Shift arithmetic right by {\tt CL} (sign fill)
\par$\null$\verb|     mm #) CL SAR|
\par$\null$\verb|   dd [xx] CL SAR|

\par$\null$\verb|        rr rr SBB| \gap (destination minus source)
\par$\null$\verb|     rr mm #) SBB|
\par$\null$\verb|   rr dd [xx] SBB|
\par$\null$\verb|     mm #) rr SBB|
\par$\null$\verb|   dd [xx] rr SBB|
\par$\null$\verb|      ii # rr SBB|
\par$\null$\verb|   ii # mm #) SBB|
\par$\null$\verb| ii # dd [xx] SBB|

\par$\null$\verb|        BYTE SCAS| \gap Scan string byte: {\tt CMP}s {\tt ES:DI} with {\tt AL} (dest)
\par$\null$\verb|             SCAS| \gap Scan string word. {\tt AX} acts as {\tt CMP} dest.

\par$\null$\verb|           rr SHL| \gap Same as {\tt SAL}
\par$\null$\verb|        mm #) SHL|
\par$\null$\verb|      dd [xx] SHL|
\par$\null$\verb|        rr CL SHL|
\par$\null$\verb|     mm #) CL SHL|
\par$\null$\verb|   dd [xx] CL SHL|

\par$\null$\verb|           rr SHR| \gap Shift logical right one position (zero fill)
\par$\null$\verb|        mm #) SHR|
\par$\null$\verb|      dd [xx] SHR|
\par$\null$\verb|        rr CL SHR| \gap Shift logical right {\tt CL} positions (zero fill)
\par$\null$\verb|     mm #) CL SHR|
\par$\null$\verb|   dd [xx] CL SHR|

\par$\null$\verb|              STC| \gap Set carry flag
\par$\null$\verb|              STD| \gap Set direction flag (string ops will decr)
\par$\null$\verb|              STI| \gap Set interrup enable flag (allow interrupts)
\par$\null$\verb|        BYTE STOS| \gap Store {\tt AL} in string byte at {\tt ES:DI} (postincr.)
\par$\null$\verb|             STOS| \gap Store {\tt AX} in string word at {\tt ES:DI} (postincr.)

\par$\null$\verb|        rr rr SUB| \gap (destination minus source)
\par$\null$\verb|     rr mm #) SUB|
\par$\null$\verb|     mm #) rr SUB|
\par$\null$\verb|   rr dd [xx] SUB|
\par$\null$\verb|   dd [xx] rr SUB|
\par$\null$\verb|      ii # rr SUB|
\par$\null$\verb|   ii # mm #) SUB|
\par$\null$\verb| ii # dd [xx] SUB|

\par$\null$\verb|       rr rr TEST| \gap (affects only flags)
\par$\null$\verb|    mm #) rr TEST|
\par$\null$\verb|  dd [xx] rr TEST|
\par$\null$\verb|     ii # rr TEST|
\par$\null$\verb|  ii # mm #) TEST|
\par$\null$\verb|ii # dd [xx] TEST|

\par$\null$\verb|             WAIT| \gap {\tt CPU} enters {\tt WAIT} state

\par$\null$\verb|       rr rr XCHG| \gap Exchange contents of dest and source
\par$\null$\verb|    mm #) rr XCHG|
\par$\null$\verb|  dd [xx] rr XCHG|
\par$\null$\verb|       SP AX XCHG|
\par$\null$\verb|       BP AX XCHG|
\par$\null$\verb|       SI AX XCHG|
\par$\null$\verb|       DI AX XCHG|

\par$\null$\verb|             XLAT| \gap Translate: {\tt AL+BX} points to new value for {\tt AL}

\par$\null$\verb|        rr rr XOR| \gap Logical {\sc xor}
\par$\null$\verb|     rr mm #) XOR|
\par$\null$\verb|     mm #) rr XOR|
\par$\null$\verb|   rr dd [xx] XOR|
\par$\null$\verb|   dd [xx] rr XOR|
\par$\null$\verb|      ii # rr XOR|
\par$\null$\verb|   ii # mm #) XOR|
\par$\null$\verb| ii # dd [xx] XOR|
\par}


\subsection{Prefixes}

Prefixes are instructions that modify the action of the following
instruction. They comprise the lock prefix,

\medskip
{\small
\par$\null$\verb|LOCK | \gap Lock bus during execution of next instruction
\par}
\medskip

\noindent the repeat prefixes, and the segment-overrride prefixes.

\medskip
The repeat prefixes are used with \verb|LODS|,
\verb|MOVS|, \verb|STOS|, \verb|CMPS|, and \verb|SCAS|.  After each
repetition, the {\tt CX} register is decremented: execution continues
until either {\tt CX} reaches zero, or the repeat test (equal or not
equal) fails.  Source and destination pointers ({\tt SI} and
{\tt DI}) end up pointing one position past the end of string(s), or
else one position past the first point of match/mismatch.

\medskip
{\small
\par$\null$\verb|REP  | \gap Repeat next instruction
\par$\null$\verb|REPZ | \gap Repeat while zero flag on (equal)
\par$\null$\verb|REPNZ| \gap Repeat while zero flag off (unequal)
\par}

\medskip
The segment-override prefixes are used to override the 8086 default
assumptions concerning which segment register to use with the next
instruction.  The normal default is the {\tt DS} segment, and this
can always be overridden.  Memory references using the {\tt BP}
pointer take the stack segment ({\tt SS}) as their default, but this
can also be overridden.  The only defaults which can't be overridden
are: string destinations ({\tt ES}), stack operations ({\tt SS}), and
instruction fetches ({\tt CS}).

\medskip
{\small
\par$\null$\verb|CS:  | \gap Use code segment register with next instruction
\par$\null$\verb|DS:  | \gap Use data segment register with next instruction
\par$\null$\verb|ES:  | \gap Use extra segment register with next instruction
\par$\null$\verb|SS:  | \gap Use stack segment register with next instruction
\par}
}


\section{Interface with {\tt DEBUG}}\label{debug}

\index{Machine-language debugger}One of the programs which is supplied as part of DOS is an 8088/86
assembly language programming aid called \prog{DEBUG}\index{Machine-language debugger} (this should not
be confused with the word-debugging utility of F83---also called \id|DEBUG|).
This program provides facilities for tracing and disassembling machine
language programs, which may be used in conjunction with Forth if you
are having difficulty getting a machine language routine to work
within \id|F83| or \id|CAM|.
The \id|DEBUG| program is extensively documented in the DOS
manual, but we will provide here a brief illustration of how to use it
with Forth.

\medskip

To invoke \id|DEBUG| for use with a version of the Forth system,
say, \id|CAM.EXE|, you would simply type from DOS
        \begin{verbatim}
    C>debug cam.exe\end{verbatim}
        You will find yourself at the \id|DEBUG| command level, with a
\id|-| (``dash'') as a prompt.  (In the following examples, this dash has
been indicated for clarity, but should not be typed by you.)

The most useful commands will be \id|G| (Go), \id|D| (Dump), \id|R|
(show/modify Registers), \id|T| (Trace), and \id|U| (Unassemble).

To begin executing the Forth program, simply type
        \begin{verbatim}
    -G\end{verbatim}
        This will cause execution to begin at location {\tt 0100} (hex) within the
segment containing the \id|CAM.EXE| program, which is the normal
point where a \id|EXE| file begins execution.  Execution will proceed
normally (with about 20K of the \pc's RAM taken up by \id|DEBUG|)
until you type \id|G| at the Forth level (or execute \id|G| as
part of another Forth word).  At this point you will find yourself back
in \id|DEBUG|.

\subsection{Unassembling code}

To unassemble code starting at location {\tt 0567} (hex) type
        \begin{verbatim}
    -U 567\end{verbatim}
        This will unassemble a screenful of code; to continue to unassemble
following lines, just type
        \begin{verbatim}
    -U\end{verbatim}
        for another screenful.  

To dump values from memory starting
at location {\tt 07A2}, type
        \begin{verbatim}
    -D 7A2\end{verbatim}

You can return to Forth by typing
        \begin{verbatim}
    -G\end{verbatim}
        This will cause you to continue where you left off.  Thus,  you can
unassemble code with \id|DEBUG| almost as if this were a Forth utility.

\subsection{Tracing}

If you want to trace program execution, you should set a breakpoint
while in \id|DEBUG|.  If you want to start tracing at location {\tt 7A9C},
restart Forth using
        \begin{verbatim}
    -G 7A9C\end{verbatim}
        When the execution of Forth reaches this location you will exit to
\id|DEBUG|.  The status of all registers and the next instruction to be
executed will be displayed.  All the \id|DEBUG| commands are available;
in particular, typing
        \begin{verbatim}
    -T\end{verbatim}
        will cause the next instruction to be executed in {\sl
trace mode}.  This means that we will return to \id|DEBUG| after the
instruction has been completed, and the status of all registers and
the instruction to be executed next will be shown.  You can
single-step through the execution with more \id|T|'s, or you can
type, say,
        \begin{verbatim}
    -T 20\end{verbatim}
        to trace {\tt 20} (hex) instructions.  At any time you can
continue with Forth, by typing
        \begin{verbatim}
    -G\end{verbatim}
or continue executing until another breakpoint occurs (at location
{\tt 82D7}, say) by typing
        \begin{verbatim}
    -G 82D7\end{verbatim}


You can end a trace by cold-starting Forth with
        \begin{verbatim}
    -G =100\end{verbatim}
        (execution resumes at location {\tt 0100}) or with
        \begin{verbatim}
    -G =100 7AD3\end{verbatim}
        (cold-start, and leave a breakpoint at {\tt 7AD3}). 

Before cold-starting Forth, the code-segment register must have the
correct value.  If you are tracing a DOS interrupt or some other
routine located outside of Forth, you should restore the \id|CS|
register using the \id|R| command to its normal value.  The command
would be
        \begin{verbatim}
    -R CS\end{verbatim}
        The program will respond with its current value, and give you an
opportunity to enter a new value, e.g.
        \begin{verbatim}
    CS 917
    :\end{verbatim}
        You can respond after the \id|:| prompt with a new value, or press
{\sc return} to leave the register unchanged.

\subsection{Leaving {\tt DEBUG}}

Forth normally takes over interrupt vectors that it uses, saving their
initial values during cold-start, and restoring them when you execute
\id|BYE|.  Thus you should normally exit debug by typing \id|BYE|
from Forth and then \id|Q| (Quit) from \id|DEBUG|.  

If you have cold-started Forth from \id|DEBUG| more than once since the
beginning of the session, incorrect information may be saved about the
original values of these vectors.  In this case you should exit by
rebooting the \pc.

