















                                  \\\ WASM ///

                               Wolfware Assembler
                                  Version 2.11

                                  User's Manual


                        (C) Copyright 1987 by Eric Tauck
                               All rights reserved




                                Table of Contents

             Distribution Policy ................................ 1
             Introduction ....................................... 2
             Assembling Programs ................................ 4
             Basic Syntax ....................................... 6
               Symbols .......................................... 8
               Instructions ..................................... 9
               Operands ........................................ 10
               Operand Expressions ............................. 14
             Program Structure ................................. 16
             Procedures ........................................ 17
             Conditional Assembly .............................. 18
               Conditional Directives .......................... 19
               Nested Conditional Assembly ..................... 22
               Conditional Operators ........................... 24
               Conditional Operand Testing ..................... 25
             Macros ............................................ 27
               Defining Macros ................................. 28
               Invoking Macros ................................. 30
               Nested Macros ................................... 32
               Conditional Macros .............................. 33
               Listing of Macros ............................... 34
             Data .............................................. 35
             Assembly Directives ............................... 37
             Functional Operands ............................... 55
             Assembly Constants ................................ 61
             Reserved Symbols .................................. 65
             Assembly Listing .................................. 66
             Symbol Table Listing .............................. 68
             Assembly Messages ................................. 69
             Instruction Set ................................... 80
             8087 Programming .................................. 97
             External Subroutines .............................. 98
             Source Code Clarification ......................... 99
             Memory Limitations ............................... 103
             Bibliography ..................................... 104
             Index ............................................ 105


       Distribution Policy                                              1

                               Distribution Policy

       Unmodified copies of WASM may be shared and distributed.  WASM may
       be used without obligation to me, the author.  The most current
       version of WASM may be acquired on double sided / double density 5
       1/4" diskettes by sending $10 (checks payable to Eric Tauck) to
       the address below.

         Eric Tauck
         1304 Deerpass Road
         Marengo, IL  60152

       I can also be reached electronically at:

         CompuServe .... 72457,1557

                             DISCLAIMER OF WARRANTY

       THIS SOFTWARE AND MANUAL ARE DISTRIBUTED "AS IS" AND WITHOUT
       WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR ANY OTHER
       WARRANTIES WHETHER EXPRESSED OR IMPLIED.  BECAUSE OF THE VARIOUS
       HARDWARE AND SOFTWARE ENVIRONMENTS INTO WHICH THIS PROGRAM MAY BE
       PUT, NO WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE IS OFFERED.

       GOOD DATA PROCESSING PROCEDURE DICTATES THAT ANY PROGRAM BE
       THOROUGHLY TESTED WITH NON-CRITICAL DATA BEFORE RELYING ON IT.
       THE USER MUST ASSUME THE ENTIRE RISK OF USING THE PROGRAM.  ANY
       LIABILITY OF THE SELLER WILL BE LIMITED EXCLUSIVELY TO PRODUCT
       REPLACEMENT OR REFUND OF PURCHASE PRICE.


       2                                                     Introduction

                                  Introduction

       Wolfware Assembler (WASM) is an assembler for the 8086 and related
       microprocessors.  It takes a standard ASCII text file of
       instruction mnemonics for input and produces an executable COM
       file and an optional list file for output.

       - Minimum system requirements: an IBM PC or compatible computer,
         MS/PC DOS 2.00 or up, and about 100 kilobytes of free memory.

       - Features: supports full range of 8086 and 8087 instructions and
         addressing, most standard assembly directives, signed and
         unsigned numbers, operand expressions, conditional assembly,
         macros, produces executable code (does not require linking), and
         fairly fast operation.

       - Limitations: relocatable object (.OBJ) modules are not
         supported, floating point numbers cannot be initialized, and the
         source code is not MASM compatible.

       Assembly language is a programming language in which the source
       statements are translated directly into individual microprocessor
       instructions.  This direct translation allows complete control
       over the computer and the greatest possible optimization of a
       program.  Programming in assembly language has immediate and
       practical benefits:

       - Programs can be made to run hundreds, maybe thousands of times
         faster than their high level language counterparts.

       - Programs are usually much smaller and more efficient.

       - Programs can take full advantage of the system it is meant to
         run on.

       Assembly language is essential where speed, compactness, and low
       level or hardware control are the primary requirements.  WASM is
       best suited for writing smaller, stand-alone programs and
       optimized routines that are used by other programs.  WASM is ideal
       for writing machine language subroutines for BASIC or Turbo
       Pascal.

       The disadvantage of assembly language is that the writing and
       debugging of such programs are often more difficult.  Another
       consideration is that assembly language is not very portable, i.e.
       programs written in assembly language are usually restricted to
       one type of computer.

       WASM is easier to use than most commercial assemblers because of
       its simplified syntax and program structure.  Of course, by the
       same token, WASM is not necessarily compatible with other
       assemblers.


       Introduction                                                     3

       Though this documentation explains some of the basic concepts of
       assembly language, no attempt is made to to teach it.  The user
       should be familiar with the basic concepts of programming and have
       a general knowledge of the the 8086 microprocessor.  See the
       bibliography for some possible reference materials.


       4                                              Assembling Programs

                               Assembling Programs

       Programs are assembled by running the assembler and specifying the
       names of the source, object, and list files.  To run the assembler
       from any DOS prompt, you type "WASM" and then a carriage return.
       A brief opening message will be displayed and you will be prompted
       for all the required information.  Default file names will be
       provided if no name is otherwise specified.  The default name
       appears in brackets at the end of the prompt line.  An entire file
       name consists of a path, filename, and extension.  The drive
       specification is considered part of the path.

       The source file contains the list of instructions that are to be
       assembled into machine code.  It must be a standard ASCII text
       file created by the user before assembly.  If you enter a source
       file name without an extension, the default extension of ASM will
       be automatically added to it.  ASM is the standard filename
       extension for assembler source files.

       The object file contains the machine code result of the assembly.
       The object file will be created if it doesn't already exist; if
       does exist the original file will be overwritten.  The default
       name is the source path and filename with an extension COM.  You
       may enter any component(s) of the name which you want to be
       different from the default name (like only the path and extension
       for instance).  COM is reserved by DOS as the filename extension
       for executable "command" files.  The object file is not a linkable
       object file, but a binary image of the compilation.  The object
       file, assuming the source code was logically correct and that
       there were no errors during assembly, is directly executable from
       DOS.  If you use the extension COM, you can run the assembled
       program just by typing its filename.

       The list file contains the listing of the assembly.  The list file
       will be created if it doesn't already exist; if does exist the
       original file will be overwritten.  If no list file is specified,
       no listing will be produced. If you do enter a filename, the
       object path and an extension of LST will be used as the default.
       Specifying CON as the list file will send the listing to the
       screen, and specifying PRN as the list file will send the listing
       to the printer.  The listing itself is more thoroughly described
       under Assembly Listing.

       The names of the three files may be entered on the command line
       when WASM is initially executed.  To do this you must provide at
       least the name of the source file.  The other two names are
       optional.  All names should be separated from each other by a
       comma.  You can use a default name by placing a comma without a
       name, or by just leaving the name off the end.  The normal
       defaults to all names still apply.


       Assembling Programs                                              5

       Examples of command line file specifications:

         WASM TEST
           source is TEST.ASM, object is TEST.COM, and there is no list

         WASM ABC, , ABC
           source is ABC.ASM, object is ABC.COM, and list is ABC.LST

         WASM  SUBRT, .BLD
           source is SUBRT.ASM, object is SUBRT.BLD, and there is no list

         WASM TEST.TXT, STUPID.BIN, HELLO.DOC
           source is TEST.TXT, object is STUPID.BIN, and list is
           HELLO.DOC

         WASM A:\ASSM\PROG1,,B:PROG1
           source is A:\ASSM\PROG1.ASM, object is A:\ASSM\PROG1.COM, and
           the list is B:PROG1.LST

         WASM GAME.SRC, C:\GAMES\.COD, C:\LISTS\GAME
           source is GAME.SRC, object is C:\GAMES\GAME.COD, and the list
           is C:\LISTS\GAME.LST

       If there are errors detected during assembly, they will be
       displayed in the listing.  If there is no listing being generated,
       the errors will be displayed to the screen along with the line
       causing the error.  Any errors should be corrected and the program
       reassembled before running or debugging the program.

       At the end of assembly several statistics are displayed: the
       number of errors, the number of lines assembled, the number of
       bytes of code, and the number of symbols defined.  These
       statistics are sent to the list file if a listing is being
       generated, otherwise they will be displayed to the screen.  A
       message stating if any errors where detected will shown if the
       assembly statistics were not displayed to the screen.

       An error code is returned upon termination.  This error code can
       be acted upon in a batch file with ERRORLEVEL (see your DOS manual
       for details).  The error codes are as follows:

        Code  Meaning
        ----  -------
         0    no lines flagged
         1    lines were flagged for comment but no errors were detected
         2    errors were detected but the assembly was completed
         3    the assembly was prematurely terminated due to errors
         4    assembly could not begin (incorrect DOS or not enough mem.)


       6                                                     Basic Syntax

                                  Basic Syntax

       The source file must be a standard ASCII text file.  The only
       control characters given special treatment are line boundaries
       (ASCII codes 13 and 10) and end of file markers (ASCII code 26).
       All other control characters are treated as spaces.  The source
       lines may be up to 160 characters long.  If the source file does
       not have an end of file marker, the assembler will read the number
       of bytes recorded in the directory. The line editor EDLIN.COM
       provided with DOS is suitable for creating source files.

       All 8086 instructions perform an operation on zero, one, or two
       operands.  Assembly directives (commands to control the assembler
       itself) are implemented in a similar manner.  Generally each line
       will contain a single 8086 instruction, or directive, and its
       operands.  In addition to instructions and their operands, a line
       may contain a symbol declaration.

       The source file is assembled line by line.  Each line is divided
       up into fields separated by delimiters.  Delimiters consist of
       spaces and most control characters.  How the assembler tries to
       interpret each field is based on the location of the field within
       the line.  Lines are interpreted according to the following
       format:

                   Symbol    Instruction  Operands    ;Comment

       Symbols must begin on the first character of the line.  If the
       first character of a line is a delimiter, the line is assumed not
       to contain a symbol declaration.  Symbols are only required when
       the instruction is one that specifically defines some sort of
       symbol (like an equate or macro declaration).  Symbols may be any
       length as long as they fit on the line.  Symbols may consist of
       most characters as long as they are unique from each other and all
       predefined symbols.  The rule of thumb is to start symbols with a
       letter and make the rest of the symbol out of numbers, letters,
       and underscores.  Restrictions on symbol declarations are more
       thoroughly described under Reserved Symbols.  Symbols in general
       are described under Symbols.

       Instructions must be separated by at least one delimiter from the
       symbol.  If there is no symbol, at least one delimiter must
       precede the instruction (so it doesn't start on the first
       character of the line).  All instructions are predefined.  See
       Instructions.

       Operands must be separated by at least one delimiter from the
       instruction.  Since a single operand may consist of multiple
       fields, operands must be separated from each other by commas.  The
       instruction determines how many of what kind of operands are
       required.  See Operands.


       Basic Syntax                                                     7

       Comments come at the end of the line after a semi-colon.  Comments
       may consist of anything and be any length as long as they fit on
       the line.  Comments are always optional and are only there to
       assist the programmer in understanding the source code.

       Blank lines may be placed in the source code to improve
       readability.  Blank lines are ignored by the assembler.  Lines may
       also contain only a comment, in which case they are treated as
       blank lines.


       8                                                          Symbols

                                     Symbols

       Symbols are used to identify certain aspects of the source
       program.  Symbols allow those aspects to be referenced
       symbolically.  The effective use of symbols can make a program
       easier to understand.  Symbols can also simplify the modification
       of a program.  By changing the portion of the program represented
       by the symbol, you automatically change the program at every
       location the symbol is used.

       A symbol is created by declaring it.  This is done by placing the
       symbol field on the first column of a source line.  A line may
       contain only a symbol or a symbol and an instruction.  Declaring a
       symbol causes the assembler to internally store it in the symbol
       table.  An ambiguity arises if a particular field is defined more
       than once as a symbol, since if that symbol is used, the assembler
       will not be able to tell which definition is actually being
       accessed.  For this reason, all symbols must be unique from each
       other.  In addition to being unique from each other, programmer
       defined symbols must be unique from all predefined symbols.
       Restrictions on symbol declarations are more thoroughly described
       under Reserved Symbols.

       Symbols come in several different types, the most common of which
       is the label.  Labels identify a location in memory.  Labels are
       used for two purposes, branching and data access.  Labels for
       branching are called near labels.  Labels for data access are
       called memory labels.  Memory labels come in different sizes
       according to how many bits of memory are referenced.  The other
       symbol types are equates and macros.  Equates represent a single
       number.  Macros represent an entire series of instructions.

       The symbol type is determined by the instruction.  The declaration
       directives (DB, DW, and DS) create memory labels, the EQU
       directive creates an equate, the MACRO directive creates a macro,
       and the LABEL directive creates a label of a specified type.  Most
       other instructions, and symbols on lines without instructions,
       result in near labels.

       Symbols are used by the program in two different ways, as
       instructions and as operands.  Only macros are used as
       instructions.  The remaining symbol types are used as operands.  A
       symbol does not have to be declared before it is used, i.e. memory
       references, equates, and macros may be declared anywhere in the
       program.  Near labels should be placed at the location where the
       code execution should continue after the branch.


       Instructions                                                     9

                                  Instructions

       An 8086 instruction specifies the action that should be carried
       out on the operands by the microprocessor.  Assembly directives
       are special instructions to control the assembly itself.  8086
       instructions and directives are implemented in the same manner,
       there is no syntactic difference between the two.

       Over a hundred different instructions are recognized by the 8086
       microprocessor.  The two major types of instructions are those
       that manipulate bits in memory and those that transfer control
       from one location in the program to another.  A summary of all the
       legal instructions can be found under Instruction Set. For a full
       explanation of all 8086 instructions, you should acquire a book on
       the subject.

       There are assembly directives for many different purposes.
       Specific assembly directives are described in their relevant
       sections and under Assembly Directives.


       10                                                        Operands

                                    Operands

       The operands describe what is being acted upon by the instruction.
       There are many different types of operands.  The number and type
       of operands required is determined by the particular instruction.
       The operands needed for an instruction can be looked up under
       Instruction Set.  WASM figures out the type of an operand by
       looking at it and trying to match it to one of the formats it
       recognizes.  If the operand is not recognized as a standard
       predefined type, the symbol table is searched to see if has been
       defined by the programmer.

       The following is a list of the legal operand types and their
       formats:

         I. Immediate data operands.

            A. Numbers with an optional plus or minus preceding it.  All
               numbers must begin with a 0 to 9, and anything that begins
               as such is considered a number.  Numbers with a sign must
               be in the range -32768 to +32767, otherwise they must be 0
               to 65535

               1. A binary number of up to 16 digits of ones and zeros
                  followed by a "B".

               2. A decimal number from 0 to 65535.

               3. A hexadecimal number of up to 4 digits of 0 to F
                  followed by an "H".  Hexadecimal numbers that begin
                  with A to F should have a preceding 0.

            B. A character enclosed in single quotes.  The character is
               converted to an 8 bit ASCII value, so 'z' would be the
               same as the number 122.

            C. A pair of characters enclosed in single quotes.  The
               characters are converted to a 16 bit value calculated from
               their ASCII values.  If 'ab' where moved into a register,
               the high byte would receive the value of 'b' and the low
               byte would receive the value of 'a'.  'ab' is the same as
               the number (98*256)+97 = 25185 or 6261H.  The values of
               'a' and 'b' are backwards because of the way the 8086
               stores 16 bit numbers.

            D. Assembly constants.  These are special symbols that return
               a value set by the assembler.  See Assembly Constants.

        II. Register operands.

            A. One of the following 8 bit registers:

                AH  AL  BH  BL  CH  CL  DH  DL


       Operands                                                        11

            B. One of the following 16 bit registers:

                AX  BX  CX  DX  SP  BP  SI  DI

            C. One of the following segment registers:

                CS  SS  DS  ES

       III. Memory operands.

            A. Direct addressing with a value enclosed by brackets.  All
               numbers (immediate data) inside the brackets are added or
               subtracted together to form the value.

            B. Indirect addressing through the use of one of the
               following register combinations with an optional value
               added or subtracted in:

                BX  BP  DI  SI

                BX+DI  BX+SI  BP+DI  BP+SI

               All the addressing components should be surrounded by
               brackets.  The registers can appear in any order and may
               be mixed up with any numbers.  All numbers (immediate
               data) are added or subtracted together to form the value.
               The OFFSET function is assumed for any labels (i.e. OFFSET
               can be left out).

        IV. A string of any sequence of characters surrounded by single
            quotes.  Note: single quotes cannot be represented as a
            character in a string or as an immediate data character, it
            can only be represented as a numerical value.

         V. A single question mark.  This means the the programmer
            doesn't know or care what the operand is.  A question mark is
            interpreted as a zero.

        VI. Certain symbols types are used as operands, including equates
            and labels.  See Symbols.

       VII. Functional operands may be used to modify or isolate specific
            aspects of of other operands.  See Functional Operands.

       VIII. An 8087 stack operand.  These operands reference the 8087
             stack relative to the stack top in the form ST(i), where
             i is a displacement 0 to 7.  The stack top, ST(0), can also
             be specified as just ST.

       Operands always have a size associated with them (measured in
       bits).  If the instruction is one that transfers data from one
       operand to another, the sizes of the operands for the instruction
       must agree.


       12                                                        Operands

       The size of immediate data is the number bits it represents.
       Usually 8 bits of immediate data is compatible with 16 bits (i.e
       WASM is smart enough to extend 8 bits of data into 16 bits).

       Immediate data sizes:

         Immediate Data                 Size in Bits
         --------------                 ------------
         unsigned number 0 to 255         8 or 16
         signed number -128 to 127        8 or 16
         character in quotes              8 or 16
         unsigned number 0 to 65535       16
         signed number -32728 to 32727    16
         double character in quotes       16

       The size of register and memory operands are the number of bits
       that can be moved in and out of them.  The size of registers are
       predefined.  The size of memory operands must be defined in the
       declaration or with a functional operand that sets the size.  If a
       memory operand is being operating upon with a register, the memory
       operand is assumed to be the same size as the register.

       Examples of operands:

         ;*** Immediate Data ***

          Mov Dh, -100
          Mov Bl, 00101001b
          Mov Al,'W'     ;move the ASCII value of upper-case w to AL

          Mov Ax,', '    ;move a comma and space into AX,
          Stosw          ;it is stored in the same order (comma first)

         ;remember that numbers MUST start with 0 to 9, even
         ;hexadecimal numbers
          Mov Ax,0ffffh  ;move ffff hex to AX

         ;*** Registers ***

         ;8 bit examples
          Mov AL,DL
          Mov CL,0

         ;16 bit examples
          Mov Ax,Dx
          Mov Cx,0

         ;segment examples
          Mov Dx,Ss
          Mov Cx,0   ;
          Mov Es,Cx  ;cannot move immed. directly to seg


       Operands                                                        13

         ;*** Memory operands ***

         ;direct reference examples
          Mov [100],Ax           ;size is the same as AX
          Mov Byte [100], 0      ;size is set with BYTE
          Push Data              ;DATA is defined below, not ambiguous
          Mov Data,0

         ;the next three produce the same effect
          Mov CX,[Data]          ;OFFSET implied
          Mov CX,[Offset Data]
          Mov CX,Data            ;this is best

         ;indirect reference examples
          Mov [Bx],Ax
          Mov Dx,[Bx+Si+100]
          Inc Byte [Offset Data+Di-1001011b+Bp-3]
          Mov Cx, [Data+Bx]      ;BX acts as an index into DATA

         Data Dw  ?

         ;*** Near labels ***

         Label1                  ;no code, points to NOP
         Lable2  Label   Near    ;explicit label declaration, no code
         Label3  Nop             ;points to its own instruction
         ;
         ;all three of these jump to the NOP instruction above
          Jmps Label1
          Jmps Label2
          Jmps Label3

         ;*** Strings ***

          Db 'this is a string'
          Db 'it',39,'s cold'    ;this declares the string "it's cold"

         ;*** 8087 stack ***

          Fild ST, Word [Bx]
          Fmul ST(5), ST(0)


       14                                             Operand Expressions

                               Operand Expressions

       Immediate data operands may be combined into expressions.  Any
       number of operands may be combined sequentially.  Parenthesis may
       also be used within expressions to control the order of
       evaluation.  Parenthesis can be nested approximately ten deep.  A
       sign may come before parenthesis, but the range of the value
       within the parenthesis is not checked.  All operand expressions
       are evaluated during assembly.

       Near and memory labels may also be modified via expressions.  Any
       immediate data operands may be combined with a near or memory
       label.  Adding or subtracting a value to or from a label has the
       effect of an additional displacement.  The label must be the first
       component of the expression.

       The legal operators for combining operands are:

         Operator  Function
         --------  --------
            +      addition        <--)  Arithmetic
            -      subtraction        )
            *      multiplication     )
            /      division           )
            \      remainder          )
            MOD    remainder       <--)
            AND    and             <----)  Logic
            OR     or                   )
            XOR    xor             <----)
            =      equals          <------)  Conditional
            <      less than              )
            >      greater than    <------)

       The use of conditional operators are described under Conditional
       Operators, the other operators carry out the specified standard
       arithmetic and logic operations.  If some sort of error occurs
       with AND, OR, XOR, or MOD, instead of displaying the literal
       operator, only the first letter A, O, X, or \ for MOD will be
       displayed.

       Examples of operand expressions:

         ;the following lines all assemble to "move zero to AX"
          Mov Ax,0
          Mov Ax,-21 + ((20 Mod 19)+ 20)
          Mov Ax,-21 - -21
          Mov Ax,50000 * (10\10)
          Mov Ax,-6 / -3 - 2
          Mov Ax,Not (1111111111111110b Or (0feh Xor (65535 And 1)))
          Mov Ax,0ffh-128-64-32-16-8-4-2-1


       Operand Expressions                                             15

         ;here is how to load a double word
         ;of storage a word at a time
          Mov Word Location, Offset Routine   ;load first word
          Mov Ax, Ds
          Mov Word Location + 2, Ax           ;load second word

         Location Label Dword
          Ds 4

       16                                               Program Structure

                                Program Structure

       Though programs may be organized in any fashion, it is usually a
       good idea to make them "structured."  Structured programs are
       generally easier to understand and modify.  Because of their
       inherently straightforward design, structured programs are less
       likely to contain errors and usually accomplish the task with a
       minimum of code.

       Structured programming divides a program into separate routines,
       each of which is treated like a separate program.  Every routine
       encompasses a single or group of functions that make up the total
       operation of the program.  Direct transfer of control from one
       routine to another is not allowed.  Direct communication between
       routines is also not allowed.  A routine may call another routine,
       but when the other routine is finished, control must be returned
       to the caller.  Information should only be passed from a routine
       to its subroutine by parameters or by data that is explicitly
       intended as global.

       Assembly language doesn't naturally lend itself to structured
       programming the way a high-level language like Pascal does.  There
       is nothing to prevent the programmer from entering a routine and
       then jumping directly to another routine.  WASM provides two
       methods to assist in creating a structured program: procedures and
       macros.  The implementation for procedures and macros are
       described under Procedures and Macros, respectively.


       Procedures                                                      17

                                   Procedures

       A procedure is a type of programmer defined routine.  A procedure
       is accessed with the 8086 CALL instruction.  Only one copy of a
       procedure exists, unlike macros, which, in the process of
       assembly, create a copy of their routine every time they are
       invoked.  The use of procedures makes a program shorter but
       slower.  Lengthy routines should always be declared as procedures,
       especially if they are called in many different places.
       Parameters are passed to procedures through registers or by
       placing the data on the stack.

       Procedures are implemented by the PROC and ENDP directives.  PROC
       starts a procedure.  Its operand is either NEAR, for routines in
       the same segment, or FAR, for routines that may be in another
       segment.  All procedures that are called from within the program
       should be NEAR.  FAR should be used by procedures that will be
       called externally from another program, like a machine language
       BASIC subroutine, or for routines that are called indirectly, like
       an interrupt handler.  A symbol may be declared along with the
       PROC directive.  This symbol becomes the label that identifies the
       procedure and is used when calling it.  ENDP finishes a procedure.
       It has no operands.

       The last executed 8086 instruction in a procedure should be a RET.
       This instruction will return control to the code that called the
       routine in the first place.

       Procedures may be nested up to ten deep.  The nest number of a
       procedure is displayed in the listing, see Assembly Listing.
       Nesting a procedure doesn't really make it local, as is implied,
       though it still should be treated as if it were.  Procedures
       should not be called outside of the procedure that they were
       declared in.  Also data declared inside of a procedure should not
       be accessed outside of it.

       Procedural declarations create object code.  This means that the
       program must either jump around them or the declarations must be
       placed somewhere out of the way, like at the end of the program.

         ;small example of program structure and
         ;syntax using procedures

            :            ;main program
          Call Subrt     ;transfer control to the subroutine
            :            ;main program

         Subrt Proc Near ;start of subroutine declaration
            :            ;subroutine code
          Ret            ;returns control to main program
          Endp           ;end of subroutine declaration


       18                                            Conditional Assembly

                              Conditional Assembly

       Conditional assembly is to assemble or skip certain defined parts
       of the source code based on programmer defined conditions.
       Conditional assembly may be used anywhere within a program, to
       enable or disable any sections of source code.  Source code that
       is disabled (skipped) has no effect upon the assembly.

       Conditional assembly is probably most useful in macros, where the
       programmer may want a macro to assemble in a certain way based
       upon its parameters.

       Conditional assembly is controlled by special conditional
       directives. These directives themselves never show up in the
       listing.


       Conditional Directives                                          19

                             Conditional Directives

       Conditional assembly is controlled by the IF, IFN, NEXTIF, ELSEIF,
       ELSE, and ENDIF directives.  All conditional sections of code must
       start with an IF or IFN and end with an ENDIF.  The other
       directives, NEXTIF, ELSEIF, and ELSE, may optionally be used in
       the middle.

       The IF directive starts a conditional section of code.  The IF
       directive can be thought of as "if the condition is true, then
       assemble the following code."  The "condition" for conditional
       directives is a single immediate data operand.  The operand is
       true if its value is not equal to zero, false if its value is
       equal to zero.  If the condition is false, all the source code
       after the IF is skipped up until a matching ENDIF or another
       conditional statement is reached.

         ;IF is true, MOV AX,1 is assembled
          If 9283    ;value not equal to zero, true
           Mov Ax,1
          Endif

         ;IF is false, ADD DX,CX is not assembled
          If 0       ;value equal to zero, false
           Add Dx,Cx
          Endif

       The IFN directive works just like an IF directive except that the
       condition is reversed.  IFN can be thought of as "if the condition
       is not true then assemble the following code."  IFN starts a
       section of conditional code, just like IF.

         ;the IFN condition is false, so the
         ;MOV AX,1 is assembled
          Ifn 0      ;value is zero, false
           Mov Ax,1
          Endif

         ;the IFN condition is true, ADD DX,CX
         ;is not assembled
          Ifn -6     ;value not equal to zero, true
           Add Dx,Cx
          Endif

       The NEXTIF directive works like an ENDIF/IF combination.  If a
       NEXTIF is encountered, the present present conditional block of
       code is finished (like an ENDIF) and a new conditional block is
       started (like an IF).  NEXTIF, like IF, has a single conditional
       operand.  Any number of NEXTIF's may follow an IF. NEXTIF's are
       most useful for defining a sequential series of source code blocks
       in situations where none, some, or all of the blocks may be
       assembled or skipped.


       20                                          Conditional Directives

         ;the NOP and SUB DI,SI are assembled
          If 1
           Nop
          Nextif 0
           Mov Ax,Dx
          Nextif 1
           Sub Di,Si
          Endif

       The ELSEIF directive can be thought of as "if the previous IF was
       false and if the condition is true, then assemble the following
       code."  In other words, the conditional operand will only be
       tested if the previous IF was false.  ELSEIF has a single
       conditional operand.  Any number of ELSEIF's may follow an IF.
       ELSEIF's are most useful for defining a sequential series of
       source code blocks in situations where only one of the blocks will
       be assembled and the remaining blocks skipped.

         ;the DEC AL is assembled
          If 0
           Nop
          Elseif 1  ;previous IF=false and operand=true, true
           Dec Al
          Endif

         ;only the INC BP is assembled, the ELSEIF directives
         ;default to false because the first IF is true
          If 1
           Inc Bp
          Elseif 1
           Nop
          Elseif 1
           Call Near [Ax]
          Endif

         ;only the NOP is assembled
          If 0
           Inc Bp
          Elseif 1
           Nop
          Elseif 1
           Call Near [Bx]
          Endif

       The ELSE directive is just like an ELSEIF directive where the
       condition is always true.  The source code after the ELSE is
       automatically assembled if the previous IF was false, otherwise
       the source code is skipped.  Only a single ELSE should follow an
       IF.  ELSE's are used when a section of code should be assembled
       either one way or another.


       Conditional Directives                                          21

         ;the SUB WORD [DI],6 is assembled
          If 0
           Mov Word [Di],0
          Else
           Sub Word [Di],6
          Endif

       The NEXTIF, ELSEIF, and ELSE directives generally should not be
       mixed together in a single conditional structure.  The only
       exception may be using ELSEIF's or a single ELSE after a NEXTIF,
       or a single ELSE after an ELSEIF.  Remember that all conditional
       structures start with an IF and end with an ENDIF.  The ENDIF must
       come after any intermediary conditional directives (NEXTIF,
       ELSEIF, and ELSE).

         ;the SUB DI,10 and SUB SI,30 are assembled
          If 1
           Sub Di,10
          Nextif 0
           Add Si,20
          Else
           Sub Si,30
          Endif

         ;the MOV DL,AL is assembled
          If 0
           Mov Dl,Cl
          Elseif 0
           Mov Dl,Bl
          Else
           Mov Dl,Al
          Endif


       22                                     Nested Conditional Assembly

                           Nested Conditional Assembly

       Conditional statements may be nested up to ten deep.  An IF or IFN
       following an IF, IFN, NEXTIF, ELSEIF, or ELSE, but before the
       ENDIF, starts a nested conditional structure.  The NEXTIF, ELSEIF,
       ELSE, and ENDIF directives always match the last IF or IFN.  The
       nested conditional code continues until its ENDIF is reached.

         ;only the last SUB DX,DX is assembled, the
         ;remaining code is skipped because of the
         ;initial false IF; comments on conditional
         ;statements that say "true" or "false" are
         ;actually evaluated, comments that say "skipped"
         ;aren't evaluated because of a previous
         ;false conditional statement
          If 0             ;false
           Add Dx,Dx
           Ifn 0           ;skipped
            Add Ax,Ax
           Else            ;skipped
            Sub Ax,Ax
           Endif           ;end of nested code
          Else             ;true
           Sub Dx,Dx       ;line is assembled
          Endif


       Nested Conditional Assembly                                     23

         ;... and a more complicated nesting example,
         ;only the ADD AX,AX is assembled
          If 0             ;false
           Nop
          Elseif 0         ;false
           Nop
          Else             ;true
           If 0            ;false
            Nop
            Ifn 0          ;skipped
             Nop
            Nextif 0       ;skipped
             Nop
            Else           ;skipped
             Nop
            Endif
           Elseif 1        ;true
            Ifn 1          ;false
             Nop
            Nextif 0       ;false
             Nop
            Nextif 1       ;true
             If 1          ;true
              Add Ax,Ax    ;line is assembled
             Else          ;false
              Nop
             Endif
            Endif
           Elseif 1        ;false
            Nop
           Endif
          Endif


       24                                           Conditional Operators

                              Conditional Operators

       Conditional operators return a true or false value after comparing
       two immediate data operands.  Conditional operators are used for
       evaluating and comparing conditional operands.

       Conditional operators check for ranges or particular values
       through the use of: "<", ">", and "=".  They work like normal
       operators, except that they return either FFFFH for true or 0 for
       false.

         ;the SHR CX is assembled, since one is equal
         ;to one; it may seem silly to write "1=1",
         ;but maybe it was originally "Parm=1", inside
         ;of a macro, where PARM is a macro parameter that
         ;may be different each time the macro is called
          If 1=1
           Shr Cx
          Endif

         ;the SHR CX is assembled, only the 2<3 is true
          If 2 = 3
           Shr Ax
          Nextif 2 > 3
           Shr Bx
          Nextif 2 < 3
           Shr Cx
          Endif

         ;the CLC is assembled; the condition is true
         ;because (2>2) = 0, (2=2) = 0FFFFH, so the
         ;condition is the same as 0 OR 0FFFFH, which is
         ;equal to 0FFFFH, which is true; this construction
         ;creates a "greater or equal to" condition;
         ;all the various numerical comparisons can be
         ;constructed using logical operators and parenthesis
          If (2 > 2) Or (2 = 2)
           Clc
          Endif


       Conditional Operand Testing                                     25

                           Conditional Operand Testing

       The functions TYPE, VALUE, and SIZE are used to check for specific
       operand qualities.  Each of these functions return a 16 bit value
       that corresponds to a particular attribute of its argument.

       The type represents how the operand is interpreted (register,
       immediate data, near label, etc.).  The value may be a number to
       distinguish a register from another registers, the location of a
       label, or the actual value of an immediate data number.  The size
       is how many bits the register or memory location represents, or
       the number of bits that an immediate data number can represented
       by.  The type and size work on a bit by bit basis, that is, a
       particular bit represents a particular type or size.  An operand
       may be represented by more than one type or size (i.e. have
       multiple bits set).  Two operands are identical only if their
       type, value, and size are all identical.

       Operands can be tested for certain characteristics by comparing
       the bit settings to those of known operands.  It can be a bit
       tricky to test for the exact conditions you want, some
       experimentation may be necessary.  For the most part, if the any
       of the type or size bits match, the operands will be compatible in
       size or type.

       For the following examples, assume that P1 and P2 are macro
       parameters passed to the conditional statement:

         ;the following is true only if P1 and P2 are
         ;identical, the equates are used to make it
         ;fit all on one line

         P_Type Equ Type(P1) = Type(P2)
         P_Size Equ Size(P1) = Size(P2)
         P_Value Equ Value(P1) = Value(P2)
          If P_Type And P_Size And P_Value

         ;the following is true only if P1 is a non-
         ;segment register (a segment register is not
         ;not necessarily compatible with a normal
         ;register); only matching bits will make the
         ;result non-zero (true), and only
         ;non-segment registers have matching bits
          If Type(P1) And Type(Ax)

         ;the following is true only if P1 IS a
         ;segment register, the opposite of above
          If Type(P1) And Type(Ds)


       26                                     Conditional Operand Testing

         ;the following is true only if P1 is AX or
         ;AL; this statement is testing for equality,
         ;not just matching bits; a normal register
         ;wouldn't work because AX has an extra bit
         ;set (which defines it as the accumulator)
          If Type(P1) = Type(Ax)

         ;the following is true only if P1 is AL; like
         ;above, the accumulator type is tested for, but
         ;also the size must be the same as CH
          If (Type(P1) = Type(Ax)) And (Size(P1) = Size(Ch))

         ;you might think that the following is true if P1
         ;is any non-segment eight bit register, since it
         ;checks for compatible types and compatible sizes;
         ;unfortunately it doesn't necessarily work; the
         ;type and size comparisons each produce a bit
         ;pattern; those patterns individually, if
         ;compatible, are an arbitrary non-zero; there is
         ;no guarantee that these the two individually
         ;compatible bit patterns are compatible with
         ;each other
          If (Type(P1) And Type(Dx)) And (Size(P1) And Size(Dh))

         ;instead you can write the previous statement in
         ;the following manner; this statement, like the
         ;above, tests the size and type for compatibility,
         ;but then compares the result to zero; the type
         ;and size comparisons now return FFFFH if they
         ;are false (equal to zero), and 0 if they are
         ;true; now the two results can then be compared;
         ;since we want a positive result to be true,
         ;rather than a negative one, the entire
         ;expression must be placed within a NOT
          If Not((Type(P1) And Type(Dx)=0) And (Size(P1) And Size(Dh)=0))

         ;the above statement can more easily be written
         ;with the IFN directive as follows
          Ifn (Type(P1) And Type(Dx)=0) And (Size(P1) And Size(Dh)=0)

       More examples of conditional operand testing are provided under
       Conditional Macros.


       Macros                                                          27

                                     Macros

       A macro is a type of programmer defined routine.  A macro consists
       of a symbol that has some number of source lines assigned to it.
       The programmer creates a macro by assigning a section of code to a
       symbol.  Any time the assembler encounters the symbol as an
       instruction, the source code assigned to it is inserted into the
       program.  A macro may be used any number of times and at any
       location in the program.  In addition, the macro may have some
       number of "operands," which are passed as parameters to the
       inserted source code.  Macros are often used in conjunction with
       conditional assembly to create routines that adjust to different
       parameters.

       Macros are useful for inserting sections of code that are used
       several times in a single program.  Macros are also used to define
       a standard set of routines that are used by many different
       programs.  By including a file with commonly used macro
       declarations, the programmer can use only those macros that are
       needed by that particular program.  Macros only create object code
       by the source lines they insert, that is, the macro declarations
       themselves do not take up any space in the assembled program.


       28                                                 Defining Macros

                                 Defining Macros

       Macros may be defined anywhere within the program, except inside
       of other macro declarations.  The MACRO directive starts a macro
       declaration.  The required symbol declaration becomes the name of
       the macro.  Any number of operands may follow the MACRO directive.
       These operands are used to pass parameters into the macro.
       Whenever the macro is invoked, the parameter names are replaced
       (inside of the macro) by whatever corresponding operands where
       placed after the macro name.  The parameter names are local to the
       macro and need only be unique within that macro, otherwise all the
       normal restrictions to symbol declarations apply.  The parameters
       names should be single fields separated by commas (no expressions
       or functional operands).

       Any number of source lines may follow the MACRO directive.  Macro
       declarations are stored internally, and are thus limited by
       memory.  If the macro area becomes full, the assembly will
       terminate and display the appropriate error message.  The entire
       source line, including all spaces, non-standard control
       characters, and extended ASCII characters, are preserved
       throughout the macro storage and expansion.

       Symbols may be defined normally within macros.  Symbols defined
       within a macro are local and cannot be accessed outside of that
       macro.  The symbols need only be unique within that macro.  Local
       equates may be defined using the macro parameters.

       All 8086 instructions and assembly directives may be used within
       macros.  Macros may also be invoked within other macros.  You can
       even have a macro call itself recursively.  Conditional statements
       within macros apply to the overall conditional structure of the
       program, in other words, an ENDIF inside of a macro could be
       matched to an IF that appeared sometime outside and before the
       macro.  Note that macros are not expanded if they are in false
       conditional code, except for conditional macros, see Conditional
       Macros.

       A operand field inside of a macro may either be a parameter name,
       one of the predefined operand types, a local symbol, or a global
       symbol.  Parameter names take precedence over all other fields and
       are replaced before any interpretation occurs.  Local symbols take
       precedence over global symbols.  When specifying parameter names,
       if it is possible that the parameter will receive a nul string, it
       is a good idea to put parenthesis around the name.  This allows
       the line to be parsed correctly if a nul parameter is passed.

       Conditional statements can be used to test for valid parameters.
       If a parameter is not valid, it can be flagged with the ERROR
       directive.

       A macro declaration is ended by the ENDM directive.


       Defining Macros                                                 29

         ;defines a macro to move a value into segment
         ;register, especially immediate date, since
         ;immediate data cannot be moved directly into
         ;a segment register

         Mov_Seg Macro Segment_Reg, Location
          Push Ax
          Mov Ax, Location
          Mov Segment_Reg, Ax
          Pop Ax
          Endm

         ;defines a macro to execute an interrupt, also
         ;if a function number is provided, it is placed
         ;in AH; if the interrupt number is not immediate
         ;data, it is flagged.

         Interrupt Macro Int_Num, Func_Num
          If Type(Int_Num) And Type(0)
           Ifn Type(Func_Num) = Type()
            Mov Ah, Func_Num
           Endif
           Int Int_Num
          Else
           Error 'Interrupt must be immediate data'
          Endif
          Endm


       30                                                 Invoking Macros

                                 Invoking Macros

       Macros are invoked by using the macro name as an instruction.  Any
       operands will be passed as parameters.  The operands may be any
       kind, of any length, including expressions and functional
       operands.  Parameters are assigned in the order in which they were
       defined in the macro declaration.  Extra operands are ignored,
       missing parameters pass a nul string.  A parameter may be skipped
       and be assigned a nul string by placing a comma without an
       operand.

       Parameter names are blindly replaced in the macro source lines by
       their passed parameters.  Nul parameters simply remove the
       parameter name.  The resulting source line may be longer or
       shorter than the original.  Unnecessary spaces are removed from
       the parameters, so they may not look exactly the same in the
       source line as they did when they were first specified as
       operands.

       Macros are not normally expanded if the present source code is
       being skipped because of a false conditional statement.  Any
       conditional statements within that macro will be ignored.
       Conditional macros, on the other hand, are expanded under those
       circumstances, see Conditional Macros.

         ;defines a macro to declare three bytes, any
         ;missing parameters are declared as zero

         Dec_Bytes Macro Byte1, Byte2, Byte3
          Ifn Type(Byte1) = Type()
           Db Byte1
          Else
           Db 0
          Endif
          Ifn Type(Byte2) = Type()
           Db Byte2
          Else
           Db 0
          Endif
          Ifn Type(Byte3) = Type()
           Db Byte3
          Else
           Db 0
          Endif
          Endm

          Dec_Bytes         ;produces 000000

          Dec_Bytes 1       ;produces 010000
          Dec_Bytes ,2      ;produces 000200
          Dec_Bytes ,,3     ;produces 000003


       Invoking Macros                                                 31

          Dec_Bytes 1,2     ;produces 010200
          Dec_Bytes ,2,3    ;produces 000203
          Dec_Bytes 1,,3    ;produces 100003

          Dec_Bytes 1,2,3   ;produces 010203


       32                                                   Nested Macros

                                  Nested Macros

       Macros may be nested up to ten deep.  A macro invocation inside of
       another macro works no differently than any other macro
       invocation.  When the nested macros finishes, the original macro
       resumes.  A macro may even call itself recursively, though, unless
       the recursion is controlled by conditional statements, an error
       will occur when the maximum nest level is exceeded.

       Parameters may be passed to successive macro levels.  Local
       symbols within a macro cannot be accessed by any nested macros
       within it.

         ;defines a macro that uses recursion to produce
         ;a specified number of single shift right
         ;instructions, the macro calls itself as long as
         ;the count parameter is greater than zero; note
         ;that the count cannot exceed nine (assuming it is
         ;not called from within another macro), otherwise
         ;the macros will nest too deeply

         Shift_Right Macro Operand, Count
          If Count > 0
           Shr Operand
           Shift_Right Operand, Count-1
          Endif
          Endm


       Conditional Macros                                              33

                               Conditional Macros

       Conditional macros are similar to normal macros.  They are
       declared with MACROC instead of MACRO.  The purpose of conditional
       macros are to create custom conditional statements.  Conditional
       macros do three things that normal macros don't: the line invoking
       the macro is not listed (like like a conditional statement), the
       macro expansion is not listed (by an implicit EXPAND-), and the
       macros are expanded in false conditional code.  Generally one
       would declare the macro with just a single conditional line that
       expresses the relationship that is desired.

         ;defines an "if the parameter doesn't exist" statement by
         ;testing to see if the type returned for the parameter
         ;is the same as the type returned for a nul operand

         If_None Macroc Parameter
          If Type(Parameter) = Type()
          Endm

         ;defines an "if the parameter exists" statement
         ;by taking the opposite result of the declaration above

         If_Exist Macroc Parameter
          Ifn Type(Parameter) = Type()
          Endm

         ;defines an "if the parameter is a byte" statement
         ;by testing if any of the same size bits are set in the
         ;size of the parameter and the size of a byte value

         If_Byte Macroc Parameter
          If Size(Parameter) And Size(Byte 0)
          Endm

         ;defines an "if the sizes of the parameters are
         ;compatible" statement by testing for matching
         ;size bits

         If_Compatible_Size Macroc Parameter1, Parameter2
          If Size(Parameter1) And Size(Parameter2)
          Endm

         ;defines an "if the parameters are identical"
         ;statement testing if the type, value, and size
         ;are identical; equates are used to simplify and
         ;shorten the final statement

         If_Same Macroc Op1, Op2
         Stype Equ Type(Op1) = Type(Op2)
         Ssize Equ Size(Op1) = Size(Op2)
         Svalue Equ Value(Op1) = Value(Op2)
          If Stype And Ssize And Svalue
          Endm


       34                                               Listing of Macros

                                Listing of Macros

       Macro expansions are listed like any other source line.  The
       special list indicator byte is a plus (+) in inserted macros
       lines.  The present macro nest level is displayed when the macro
       is first invoked.  This number is shown in the area normally
       reserved for the object code.  There is no way to tell when a
       nested macro ends within another macro.

       The listing of inserted macro lines may be globally suppressed or
       enabled with the EXPAND- and EXPAND+ directives.  The listing of
       individual macros may also be controlled by these directives.  If
       EXPAND- and EXPAND+ directives appear in a macro, they only affect
       that macro (and any nested macros).  EXPAND- and EXPAND+ do not
       have any effect if the source code is not otherwise being listed.
       Note that EXPAND- and EXPAND+ only affect the listing of macros,
       not the actual expansion of macros.

       Errors occurring within macro expansions are treated normally,
       except that the error message shows the last real line number and,
       if in an included file, the name of the source file.  The line
       number is in parenthesis following the error message.

         ;defines a macro that adds the parameters
         ;together and puts the result in DX; this
         ;macro is never listed because of the
         ;EXPAND-

         Adder Macro Parameter1, Parameter2
          Expand-
          Mov Dx,Parameter1
          Add Dx,Parameter2
          Endm

       Data                                                            35

                                      Data

       Data that is used by the program during execution must be placed
       in the program by declaration.  Data that is declared includes
       things like numbers and strings.  This is in contrast to the
       declaration of macros and equates which are only used when the
       program is assembled.  The DB, DW, and DS directives are used to
       make data declarations.

       DB is used to declare byte values, strings, words, and
       combinations of all three.  If a symbol is declared with the DB
       directive, it becomes an eight bit memory reference label.  The
       data declared by the DB may be accessed through the label.  Values
       are declared as bytes if possible, otherwise they are declared as
       words.  The BYTE and WORD functions may be used to explicitly
       define the number of bits used in declaring the data.

       DW is used to declare word values.  If a symbol is declared with
       the DW directive, it becomes a sixteen bit memory reference label.
       The data declared by the DW may be accessed through the label.
       Values are always declared as words, even if they may be bytes.

       Though WASM can only intialize 8 or 16 bit values, you can always
       use DB and DW with a LABEL to declare other sized data.  For
       instance, this declares a double word of data:

         ;declare the double word 12345678h
         Data Label Dword              ;create the label
          Dw 5678h             ;low word of data
          Dw 1234h             ;high word of data

       DS is used to declare any number of identical bytes.  If a symbol
       is declared with the DS directive, the it becomes a memory
       reference label with no size.  The size should be specified
       whenever this label is accessed (via the size functions BYTE,
       WORD, DWORD, etc.).  The LABEL directive may be used to declare a
       label of a particular type and size immediately before the DS.

       Word values are always stored low byte first, with the exception
       of two byte strings.  Assuming '1' = 31H and 'B' = 42H, the hex
       number 3142H will be stored as 4231H, though '1B' will be stored
       as 3142H.  The reverse format is how word numbers should be
       stored.  If for some reason a word value is stored as two separate
       bytes (using DB), the low byte should always be stored first,
       otherwise the number will be backwards for arithmetic operations.

       Declarations may be made anywhere in the program.  Since
       declarations produce non-executable object code, they should not
       be placed in a location where they might be interpreted as part of
       the code.  Branch the program around declarations, or put them at
       the end of the program or routine, after the executable code.


       36                                                            Data

       Examples of data declarations:

         ;declare a byte
          Db -5

         ;declare a byte and then a word value
          Db Byte 0, Word 0
         ;... or just
          Db 0, Word 0

         ;declare a string
          Db 'This is the string'

         ;declare some words
          Dw 0, 1, 2, 3, 65533, 65534, 65535

         ;the following declaration can be accessed through VALUES
         Values Db 100,-20, 36/10, 0, 010100110b

         ;this instruction accesses the numbers
         ;in VALUES above based on an index in BX
          Mov Al, [Values + Bx]  ;load number

         ;declare storage
          Ds 10          ;ten bytes of 00
          Ds 100, 0ffh   ;a hundred bytes of FFH


       Assembly Directives                                             37

                               Assembly Directives

       Assembly directives are instructions to control the assembly, they
       do not encode into 8086 machine language instructions, though some
       of the directives do produce object code.  Assembly directives are
       implemented the same way as normal instructions.

       This section describes all the assembly directives.  Most of the
       directives are also described in sections pertinent to their
       operation.

       The major categories of assembly directives are those that are
       used to declare symbols (EQU, LABEL, ORG), those that declare data
       (DB, DS, DW), those that declare procedures and macros (PROC,
       ENDP, MACRO, MACROC, ENDM), those used to control conditional
       assembly (ELSE, ELSEIF, ENDIF, IF, IFN, NEXTIF), those that
       control the assembly listing (EXPAND+, EXPAND-, LINSIZE, LIST+,
       LIST-, PAGE, PAGE+, PAGE-, PAGESIZE, SUBTITLE, SYMDUMP+, SYMDUMP-,
       TITLE), those that control error flagging and detection (ERROR,
       ERRORMAX, FLAGALL+, FLAGALL-, JUMP+, JUMP-, UNUSED+, UNUSED-), and
       some miscellaneous ones (INCLUDE, RESETC).

       ******************************************************************

       DB value/string, ...

       Declare byte.

       Places literal bytes of data into the assembled code.

       DB may have any number of operands, as long as they fit on the
       line.  The value of each operand is placed sequentially into the
       assembled code.  The operands can be immediate data or strings.
       Immediate data operands are declared as bytes if possible,
       otherwise they are declared as words.  Strings are inserted just
       as they appear (minus the string delimiters).

       See Data.

         ;the following declares a sentence with its
         ;length preceding it, including a carriage
         ;return and linefeed at the end of the sentence;
         ;the BYTE function is needed to make the length
         ;an explicit eight bit value

         A
          Db Byte(Offset B - Offset A - 1),'The sentence.',10,13
         B

         ;this declares a byte FFH and then a word FFFFH
          Db  -1, Word -1


       38                                             Assembly Directives

       ******************************************************************

       DS bytes [, value]

       Declare storage.

       Places some number of identically initialized bytes into the
       assembled code.

       DS can have one or two operands.  The first operand is the number
       of bytes to declare and the second is the value that the storage
       should be initialized to.  The initialization value is optional,
       and, if absent, the storage is initialized to zero.  The number of
       bytes to declare must be immediate data (0 to 65535).  The
       initialization value must be eight bit immediate data.

       See Data.

         ;declare a thousand bytes of FFH
          Ds 1000, 0ffh

       ******************************************************************

       DW value, ...

       Declare word.

       Places literal words of data into the assembled code.

       DW can have any number of operands, as long as they fit on the
       line.  The value of each operand is placed sequentially into the
       assembled code.  The operands must be immediate data.  The
       operands are always declared as words, even if they could be
       bytes.

       See Data.

         ;this sort of construction can be useful
         ;for creation a table of addresses, note
         ;that this particular example would work
         ;equally well with DB
          Dw Offset Subrt1, Offset Subrt2

       ******************************************************************

       ELSE

       Conditional "else."

       Assembles the following source code only if the previous IF
       directive was false.

       Requires no operands.


       Assembly Directives                                             39

       See Conditional Assembly.

         ;the code after the ELSE is carried out
         ;if NUMBER is not greater than 10
          If Number > 10
           Mov Ax, Bx
          Else
           Mov Bx, Ax
          Endif

       ******************************************************************

       ELSEIF condition

       Conditional "else if."

       Assembles the following source code only if the previous IF
       directive was false and the condition is true.

       ELSEIF requires a single immediate data operand.  This operand is
       the condition to test.

       See Conditional Assembly.

         ;only one of the following are true:
         ;if OPTION is equal to zero, CALL SUBRT1 is
         ;assembled; if OPTION is equal to one,
         ;CALL SUBRT2 is assembled; if OPTION is equal
         ;to two, CALL SUBRT3 is assembled
          If Option=0
           Call Subrt1
          Elseif Option=1
           Call Subrt2
          Elseif Option=2
           Call Subrt3
          Endif

       ******************************************************************

       ENDIF

       End of conditional structure.

       Finishes a conditional structure started by an IF directive.

       Requires no operands.


       40                                             Assembly Directives

       See Conditional Assembly.

         ;ENDIF finishes the conditional structure,
         ;so the CLC is assembled no matter what
          If Type(Parameter)=Type(Ax)
           Sub Ax, Ax
          Endif
          Clc

       ******************************************************************

       ENDM

       End of macro.

       Finishes a macro declaration started by a MACRO or MACROC
       directive.

       Requires no operands.

       See Macros.

         ;the ENDM finishes the rather simple declaration
         ;of the macro NUL_INST

         Nul_Inst Macro
          Nop
          Endm

       ******************************************************************

       ENDP

       End of procedure.

       Finishes a procedure declaration started by a PROC directive.

       Requires no operands.

       See Procedures.

         ;the ENDP finishes the declaration of the
         ;procedure SUBRT

         Subrt Proc Near
          Xchg Ax, [Si]
          Ret
          Endp

       ******************************************************************

       EQU value

       Equate a value.


       Assembly Directives                                             41

       Defines a symbol that may be used anywhere in place of a specified
       value.

       EQU requires a single immediate data operand and the symbol to be
       equated.  The operand becomes equated to the symbol.

       EQU is useful for making the source code more readable by
       replacing arbitrary numbers with meaningful symbols.  The value of
       the equate generally should not reference any symbols that have
       not been defined yet in the source code.  This means that the
       value should not contain a forward reference to another equate, or
       use OFFSET when its argument has not yet been defined.

       See Symbols.

         ;equate the number 50 times 20, or 1000, to the
         ;symbol NUMBER, and then move NUMBER into AX

         Number Equ 50*20
          Mov Ax, Number

       ******************************************************************

       ERROR message

       Programmer defined error.

       Causes an error to occur using the specified message.

       ERROR requires a single string operand.  This operand becomes the
       error message.

       No line is displayed with the error message, the listing of the
       statement itself is suppressed.  The error is included in total
       number of errors at the end of the program.  ERROR is useful for
       flagging invalid macro parameters.

         ;defines a macro that checks for a missing operand;
         ;if the macro is invoked with the operand is missing,
         ;an error is displayed using an ERROR directive

         Mover Macro Op1
          If Type(Op1) = Type()
           Error 'Missing operand'
          Endif
          Endm

         ;this will cause the error
          Mover       ;invoked with no operands


       42                                             Assembly Directives

       ******************************************************************

       ERRORMAX number

       Maximum errors.

       Places an upper limit on the number of errors and comments
       occurring before the assembly is halted.

       ERRORMAX requires a single immediate data operand.  This operand
       becomes the new number of maximum allowed errors.

       The default is 65535.  Note that both errors and comments are
       counted.

         ;set the number of allowed errors to ten, if a tenth error
         ;or comment ever occurs, the assembly will be terminated
          Errormax 10

       ******************************************************************

       EXPAND+
       EXPAND-

       List macro expansions.

       When activated (EXPAND+), lines resulting from a macro expansion
       will be listed.  When deactivated (EXPAND-), lines resulting from
       a macro expansion will not be listed, only the line containing the
       macro invocation will be visible.

       Requires no operands.

       The default is EXPAND+.  EXPAND+ and EXPAND- directives that are
       within macros only apply to those macros.  Macros will not be
       listed regardless of the EXPAND+ and EXPAND- directives if the
       source code is not otherwise being listed.

       See Macros and Assembly Listing.

         ;macro expansions are globally listed because
         ;of the EXPAND+, except the defined macro TERMINATE
         ;explicitly suppresses only its own listing
          Expand+

         Terminate Macro
          Expand-
          Mov Ah, 4ch
          Int 21h
          Endm


       Assembly Directives                                             43

       ******************************************************************

       FLAGALL+
       FLAGALL-

       Undefined symbol flagging.

       When activated (FLAGALL+), an undefined symbol is flagged each
       time it is used, even if it has been flagged before.  When
       deactivated (FLAGALL-), an undefined symbol is only flagged the
       first time it is used.

       Requires no operands.

       The default is FLAGALL-.

         ;assuming BADSYM is undefined, it is flagged when
         ;it is moved to AX and BX, but not when it is
         ;moved to CX or DX, since it has been flagged
         ;previously and because of the FLAGALL-
          Flagall+
          Mov Ax, Badsym
          Mov Bx, Badsym
          Flagall-
          Mov Cx, Badsym
          Mov Dx, Badsym

       ******************************************************************

       IF condition

       Conditional "if."

       Assembles the following source code only if the condition is true.

       IF requires a single immediate data operand.  This operand is the
       condition to test.

       The IF directive starts a conditional structure. See Conditional
       Assembly.

         ;if COND is zero, the IN AX,DX will be assembled
          If Not(Cond)
           In Ax, Dx
          Endif

       ******************************************************************

       IFN condition

       Conditional "if not."

       Assembles the following source code only if the condition is
       false.


       44                                             Assembly Directives

       IFN requires a single immediate data operand.  This operand is the
       condition to test.

       The IFN directive starts a conditional structure.  IFN is the
       opposite of IF.  See Conditional Assembly.

         ;if COND is zero, the OUT DX,AX will be assembled
          If Cond
           Out Dx, Ax
          Endif

       ******************************************************************

       INCLUDE file

       Include source file.

       The specified file is inserted into the main source code
       immediately after the INCLUDE directive.

       INCLUDE requires a single string operand.  This operand should
       contain the name of the file to insert.  If no path is specified,
       the main source file path is used.  If no extension is specified,
       the extension of ASM is used.

       The included source code is not treated any differently than the
       rest of the program.  Included files may NOT be nested, which
       means that the file being inserted may not contain any INCLUDE
       directives.  Neither may INCLUDE's be used within macros.  INCLUDE
       is useful for inserting source code used by many different
       programs, like standard macro declarations.  INCLUDE can also be
       used to break up a source file into several smaller chunks, if,
       for instance, your text editor cannot handle the entire source
       file at once.

         ;the following directive inserts the file
         ;INCLUDE.INC, the source drive and path are
         ;used
          Include 'Source.Inc'

       ******************************************************************

       JUMP+
       JUMP-

       Short jump checking.

       When activated (JUMP+), all long near jump instructions will be
       flagged if a short near jump could be substituted.  When
       deactivated (JUMP-), long jumps that could be short jumps are not
       flagged.

       Requires no operands.


       Assembly Directives                                             45

       The default is JUMP-.  Substituting a short jump for a long jump
       does not logically change the program, but does make the assembled
       code one byte shorter.

         ;both of the following jumps could be
         ;JMPS (a short unconditional jump); the
         ;first JMP LABEL is not flagged, the
         ;second one is
          Jump-
          Jmp Label
          Jump+
          Jmp Label
         Label

       ******************************************************************

       LABEL type

       Label declaration.

       Defines a branch or memory reference label using the present
       location counter.

       LABEL requires a single operand and a symbol to be defined.  The
       operand NEAR or FAR is used for branch locations.  The operand
       BYTE, WORD, or DWORD is used for memory references of eight,
       sixteen, or thirty-two bit sizes, respectively.

       Explicitly defining a symbol as NEAR has the same effect as
       placing a symbol on an otherwise empty line or a line with some
       sort of operation (not a data declaration).  Explicitly declaring
       a symbol as BYTE or WORD has the same effect as placing a symbol
       on a byte (DB) or  word (DW) data declaration.  LABEL can be used
       in conjunction with the ORG directive to define labels independent
       of the actual code being assembled.

       See Symbols.

         ;this label ...
         Bran1 Label Near
         ;...is the same type as
         Bran2 Mov Ds, Dx

         ;and this ...
         Dat1 Label Word
         ;... produces the same sort of label as ...
         Dat2 Dw ?


       46                                             Assembly Directives

         ;the following causes MEM_SIZE to point at the word
         ;in program segment prefix that tells how many bytes
         ;are available in the segment; if you use this method
         ;to define any labels, make sure to reset the location
         ;counter back to its proper value before defining any
         ;other normal labels in the program
          Org 6
         Mem_Size Label Word

       ******************************************************************

       LINESIZE [length] [, code, ...]

       List line length.

       Sets the maximum number of characters in each list line.

       The optional first operand is the list line length.  The remaining
       optional eight bit immediate data operands are printer codes.
       These printer codes are sent directly to the printer if the list
       file is PRN.

       The default is 79.  The length must be in the range 45 to 158.
       The number of characters per line should only be set once in a
       program, though multiple LINESIZE directives may be used to send
       several bunches of printer codes.  If a list line would come out
       any longer than specified by the LINESIZE, it will be truncated.
       PAGESIZE can also be used to set the number of characters per
       line.

       See Assembly Listing.

         ;set up for IBM Graphics printer compressed font, the
         ;printer code (15) is sent if PRN is the list file
          Linesize 131, 15

       ******************************************************************

       LIST+
       LIST-

       Assembly listing.

       When activated (LIST+), a listing of the program will be
       generated.  When deactivated (LIST-), no listing will be
       generated.

       Requires no operands.


       Assembly Directives                                             47

       If a list file was specified at the start of the program, the
       default is LIST+.  If no list file was specified, no list will be
       generated (regardless of any LIST+ or LIST- directives).  LIST+
       and LIST- directives that are within included files only affect
       those files, so you could, for instance, place a LIST- at the
       start of a source file to be included and just have the listing of
       that file suppressed.  LIST+ and LIST- directives are useful for
       selectively listing isolated sections of the source code.

       See Assembly Listing.

         ;turn list off, NOP's are not listed
          List-
          Nop
          Nop
         ;turn list on, NOP's are listed
          List+
          Nop
          Nop

       ******************************************************************

       MACRO [parameter, ...]

       Macro declaration.

       Begins a macro declaration that will be finished by the ENDM
       directive.

       MACRO may have up to ten operands.  These operands must be unique
       symbols within the macro declaration.  The operands become the
       names of any parameters passed to the macro upon invocation.  A
       symbol declaration to name the macro is also required.

       See Macros.

         ;defines the macro LOAD_DS, the MACRO
         ;directive starts the declaration

         Load_DS Macro Op1
          Mov Ax, Op1
          Mov Ds, Ax
          Endm

       ******************************************************************

       MACROC [parameter, ...]

       Conditional macro declaration.

       Begins a conditional macro declaration that will be finished by
       the ENDM directive.


       48                                             Assembly Directives

       MACROC may have up to ten operands.  These operands must be unique
       symbols within the macro declaration.  The operands become the
       names of any parameters passed to the macro upon invocation.  A
       symbol declaration to name the macro is also required.

       See Conditional Macros.

         ;defines a conditional directive TOO_SMALL
         ;that is false if the operand is above ten,
         ;i.e. "if not above ten then do the following"

         Too_Small Macroc Op1
          Ifn Op1 > 10
          Endm

         ;with the above declaration, the ADD AX,AX
         ;will be assembled because 11 is above 10
          Too_Small 11
           Sub Ax, Ax
          Else
           Add Ax, Ax
          Endif

       ******************************************************************

       NEXTIF condition

       Conditional "if", same level.

       Finishes the present conditional block and starts a new one.
       Assembles the following source code only if the condition is true.

       NEXTIF requires a single immediate data operand.  This operand is
       the condition to test.

       See Conditional Assembly.

         ;any or all of the following may be true:
         ;if OPTION is equal to ten, CALL SUBRT1 is
         ;assembled; if OPTION is less than ten,
         ;CALL SUBRT2 is assembled; if OPTION is greater
         ;than ten, CALL SUBRT3 is assembled
          If Option=10
           Call Subrt1
          Nextif Option<10
           Call Subrt2
          Nextif Option>10
           Call Subrt3
          Endif


       Assembly Directives                                             49

       ******************************************************************

       ORG value

       Origin.

       Sets the location counter to the specified value.

       ORG requires a single immediate data operand.  This operand
       becomes the new location counter value.  If the operand is signed,
       the value is treated as a displacement to the present location.

       The default is 100H, which is the starting offset required for COM
       programs.  ORG affects the location assigned to labels.  ORG can
       be used to set the offset of specially defined labels.

         ;this declares three consecutive memory labels, note
         ;that these declarations only create the labels and do
         ;not allow space for them in the object code, this sort
         ;of thing could be done at the end of the program to
         ;create uninitialized data locations in memory

         Data1 Label Word
            Org $+2
         Data2 Label Word
            Org $+2
         Data3 Label Word
            Org $+2

         ;remember that signed numbers are treated as displacements

            Org 2      ;(unsigned, absolute)
         Symbol1       ;this symbol points to [0002]
            Org +2     ;(signed, displacement)
         Symbol2       ;this symbol points to [0004], two past the
                       ;location above

       ******************************************************************

       PAGE [page|subtitle]
       PAGE page [, subtitle]

       New page.

       Starts a new list page regardless of whether paging is on or off,
       or what the size of the previous page was.

       PAGE may have none, one, or two operands.  If the first operand is
       immediate data, it becomes the new page number.  If the first
       operand a string, it becomes the new page subtitle.  If both a
       page number and a subtitle are included, the page number must come
       first.


       50                                             Assembly Directives

       If the page number is not specified, the previous page number is
       incremented.  If the subtitle is not included, the subtitle from
       the previous page is used.  PAGE can be used in conjunction with
       automatic paging (PAGE+) to start a new section of the code with a
       new subtitle.

       See Assembly Listing.

         ;start a new page and set the page number
         ;to ten and the subtitle to "Page ten"
          Page 10, 'Page ten'

       ******************************************************************

       PAGE+ [page|subtitle]
       PAGE+ page [, subtitle]
       PAGE-

       Automatic paging.

       When automatic paging is activated (PAGE+), a new page is started
       after every number of lines specified by the PAGESIZE directive
       (default 60).  When automatic paging is not activated (PAGE-), no
       paging is done, except by the PAGE directive.  PAGE+ automatically
       starts a new page if there are operands (i.e. a page number,
       subtitle, or both).

       PAGE+ has operands identical to those of PAGE, see PAGE above.
       PAGE- requires no operands.

       Default is PAGE-.  Paging can make the listing of a program look
       better if a hard copy is printed out on separate pages.

       See Assembly Listing.

         ;activate auto paging, start a new page, and
         ;set the subtitle to "Start of Paging"
          Page+ 'Start of Paging'

       ******************************************************************

       PAGESIZE lines [, characters ]

       Page size.

       Sets the lines per page and the maximum number of characters per
       line.  The lines per page affect the number lines output before a
       new page is started when automatic paging (PAGE+) is active.  The
       characters per line affect the final length of each list line.

       PAGESIZE may have one or two immediate data operands.  The first
       operand becomes the number of lines per page.  The second operand
       is optional and is the number of characters per line.


       Assembly Directives                                             51

       The default lines per page is 60.  The default characters per line
       is 79.  The lines per page must be in the range 15 to 255 and the
       characters per line must be in the range 45 to 158.  The number of
       lines per page and the number of characters per line should only
       be set once in a program.  The number of characters per line can
       also be set with LINESIZE.

         ;this makes for very long pages
          Pagesize 200

         ;the following two lines would have the same effect,
          Pagesize ,50   ;note that the first operand is nul
         ;Linsize 50     ;characters per line should only be set once

       ******************************************************************

       PROC type

       Procedure declaration.

       Begin a procedure declaration that will be finished by the ENDP
       directive.

       PROC requires a single operand.  This operand is NEAR for near
       procedures and FAR for far procedures.

       Far procedures should only be used for routines that will be
       called by other programs or are called indirectly.  Far procedures
       cannot be called locally via a CALL instruction.  The type of
       procedure determines how the returns (RET instructions) within the
       procedure will be encoded.

       See Procedures.

         ;the procedure ORRER is defined, the PROC
         ;directive starts the declaration

         Orrer Proc Near
          Or Cx, 10101b
          Ret
          Endp

       ******************************************************************

       RESETC [count] [,checksum]

       Reset counter.

       Resets the counter ($COUNT) and counter checksum ($SUM).


       52                                             Assembly Directives

       RESETC may have none, one, or two immediate data operands.  Both
       operands are optional.  If the first operand is present, it
       becomes the new count value.  If the second operand is present, it
       becomes the new checksum value.  If an operand is missing, zero is
       used.

       The new values take effect on the line after the RESETC directive.
       This directive does not affect the program byte count ($SIZE) or
       checksum ($CHKSUM).

          Resetc         ;set count and checksum to zero
          Mov Ax, $Count ;will load zero to AX
          Resetc ,20     ;default (zero) for count, 20 for checksum
          Mov Ax, $Sum   ;will load 20 to AX

       ******************************************************************

       SUBTITLE subtitle

       Program subtitle.

       Defines the page subtitle for all subsequent pages.

       SUBTITLE requires a single string operand.  The operand becomes
       the subtitle.

       Note that SUBTITLE sets the subtitle for all pages following the
       present one, not the page in which the SUBTITLE directive appears.
       The PAGE, PAGE+, and TITLE directives can also be used to set the
       subtitle.

       See Assembly Listing.

         ;set the subtitle of the following pages
         ;to "Input and Output Routines"
          Subtitle 'Input and Output Routines'

       ******************************************************************

       SYMDUMP+
       SYMDUMP-

       Symbol table dump.

       When activated (SYMDUMP+), the symbol table will be displayed at
       the end of the listing.  When not activated (SYMDUMP-), the symbol
       table will not be displayed.

       Requires no operands.

       The default is SYMDUMP-.  There is only one symbol dump at the end
       of the program, i.e. there is no reason to turn the symbol table
       dump on and then turn it off later.


       Assembly Directives                                             53

       See Symbol Table Listing.

         ;enable symbol dump at the end
         ;of the program
          Symdump+

       ******************************************************************

       TITLE title [,subtitle]

       Program title.

       Defines the page title for the entire program listing.  The
       starting page subtitle may also be specified.

       TITLE requires one or two operands.  The first operand becomes the
       program title.  The optional second operand becomes the subtitle.
       Both operands must be strings.

       Only one TITLE directive is valid for the entire program.  The
       TITLE directive is the only way to set the subtitle on the first
       page header, since SUBTITLE takes effect on the next page
       following the directive and PAGE and PAGE+ automatically start a
       new page.

       See Assembly Listing.

         ;set the program title to "Holy Cow" and the
         ;initial subtitle to "Initialize"
          Title 'Holy Cow', 'Initialize'

       ******************************************************************

       UNUSED+
       UNUSED-

       Unused symbol flagging.

       When active (UNUSED+), all symbols that were never accessed will
       be flagged.  When not active (UNUSED-), unused symbols will not be
       flagged.

       Requires no operands.

       Used to inform the programmer of unnecessary labels, routines,
       etc.  Unused macro declarations are never flagged.  The default is
       UNUSED-.


       54                                             Assembly Directives

         ;assuming the near labels SYM1 and SYM2 were
         ;never accessed, SYM1 is flagged and SYM2 isn't
          Unused-
         Sym1
          Unused+
         Sym2

       ******************************************************************


       Functional Operands                                             55

                               Functional Operands

       Functional operands modify another operand passed as an argument.
       Functional operands serve two general purposes: first to change a
       characteristic of an operand but still use it in more or less the
       same way, and second to isolate a specific aspect of an operand.
       All functional operands take another operand as an argument and
       can be used anywhere in place of a normal operand.

       The major categories of functional operands are those that set the
       size of its argument (ANYSIZE, BYTE, DWORD, QWORD, TBYTE, WORD),
       those that change the type of its argument (FAR, NEAR), those that
       change the value of its argument (NEG, NOT), and those that are
       used to access specific qualities of its argument (OFFSET, SIZE,
       TYPE, VALUE).

       ******************************************************************

       ANYSIZE

       Size any.

       Set the size of its argument to all allowable sizes.

       Its argument must be a memory operand or immediate data.  Can also
       be used with the LABEL directive.

         ;the following two statements do not
         ;conflict because of the ANYSIZE below
          Mov Bx, Data   ;move 16 bits
          Add Data, Al   ;add 8 bits

         Data Label Anysize   ;data label
          Dw ?                ;declare space for data

       ******************************************************************

       BYTE

       Size byte.

       Set the size of its argument to byte size (8 bit).

       Its argument must be a memory operand or immediate data.  Can also
       be used with the LABEL directive.  Used mainly to declare the
       number of bits acted upon in an operation if the operation would
       be ambiguous otherwise.

         ;the size of [SI] would be ambiguous
          Mov Byte [Si], 0   ;perform an 8 bit move


       56                                             Functional Operands

       ******************************************************************

       DWORD

       Size double word.

       Set the size of its argument to double word size (32 bit).

       Its argument must be a memory operand or immediate data.  Can also
       be used with the LABEL directive.  Used mainly to declare the
       number of bits acted upon in an operation if the operation would
       be ambiguous otherwise.

         ;make an intersegment call
          Call Routine_Location  ;call routine

         Routine_Location Label Dword   ;the location is 367A:6374
          Dw 06374h   ;offset
          Dw 0367ah   ;segment

       ******************************************************************

       FAR

       Type far label.

       Set the type of its argument to far label.

       Its argument must be a near label, far label, or memory operand.
       If its argument is a near or far label, the label is simply
       converted to a far label.  If its argument is a memory operand,
       FAR has the same effect as the DWORD function.  This allows FAR to
       be used in specifying indirect intersegment branching.  FAR is
       mainly used to declare a far procedure.

         ;execute an intersegment call, [BX] must point to a location
         ;containing the segment and offset of the subroutine to execute
          Call Far [Bx] ;transfer control to routine

         ;declare a rather insignificant far procedure, cannot
         ;be called directly, but may be an interrupt handler

         Subrt Proc Far  ;make far procedure
          Ret            ;return, don't do anything
          Endp           ;end of declaration

       ******************************************************************

       NEAR

       Type near label.

       Set the type of its argument to near label.


       Functional Operands                                             57

       Its argument must be a near label, far label, memory operand, or
       immediate data.  If its argument is a near or far label or
       immediate data, the operand is simply converted to a near label.
       If its argument is a memory operand, NEAR has the same effect as
       the WORD function.  This allows NEAR to be used in specifying
       indirect same segment branching.  NEAR is mainly used to declare a
       near procedure.

         ;execute a same segment call, DATA must point to a location
         ;containing the offset of the subroutine to execute
          Call Near Data ;transfer control to routine

         Data Ds 2       ;two bytes of storage (offset)

         ;declare a near procedure that doubles AX

         Double Proc Near ;make near procedure
          Sal Ax          ;double AX
          Ret             ;return
          Endp            ;end of procedure

         ;NEAR can be used to jump to a literal location
          Jmp Near 100h  ;branch to start of program

       ******************************************************************

       NEG

       Negate value.

       Perform an arithmetic negate on the value of its argument.

       Its argument must be immediate data.  Acts the same as a preceding
       sign, except that the validity of the result is not checked.

         ;the following two statements produce the same code
          Mov Dx, Neg 1 ;load minus one
          Mov Dx, -1    ;load minus one

         ;the following statement is really an undetected error
          Mov Dx, Neg 40000 ;-40000 cannot be represented with 16 bits

       ******************************************************************

       NOT

       Logical not of value.

       Perform a logical not on the value of its argument.


       58                                             Functional Operands

       Its argument must be immediate data.

         ;the following two statements produce the same code
          Mov Dh, Not 10101010b  ;load 55H
          Mov Dh, 01010101b      ;load 55H

       ******************************************************************

       OFFSET

       Offset of label.

       Return the offset of its argument.

       Its argument must be a near, far, or memory label.  The offset, or
       location, is returned as 16 bit immediate data.  Is mainly used by
       sections of code or individual routines which access data that may
       be any length (like strings of characters).

         ;put message location in SI
          Mov Si, Offset Start               ;location
         ;put message length in CX
          Mov Cx, Offset End - Offset Start  ;size

         Start Db 'This is the message'      ;message data
         End                                 ;end of message marker

       ******************************************************************

       QWORD

       Size quadruple word.

       Set the size of its argument to quadruple word (64 bit).

       Its argument must be a memory operand.

       ******************************************************************

       SIZE

       Size of operand.

       Return the size of its argument.

       Its argument may be anything.  The size is returned as 16 bit
       immediate data for comparison with the size of other operands.
       See Conditional Operand Testing.

         ;the NOP is assembled if the sizes are identical
          If Size Ax = Size Symbol ;compare sizes
           Nop                ;code if true
          Endif               ;end of conditional


       Functional Operands                                             59

       ******************************************************************

       TBYTE

       Size ten byte.

       Set the size of its argument to ten bytes (80 bit).

       Its argument must be a memory operand.

       ******************************************************************

       TYPE

       Type of operand.

       Return the type of its argument.

       Its argument may be anything.  The type is returned as 16 bit
       immediate data for comparison with the type of other operands.
       See Conditional Operand Testing.

         ;the NOP is assembled if the types are identical
          If Type Ax = Type Symbol ;compare types
           Nop                ;code if true
          Endif               ;end of conditional

       ******************************************************************

       WORD

       Size word.

       Set the size of its argument to word (16 bit).

       Its argument must be a memory operand or immediate data.  Can also
       be used with the LABEL directive.  Used mainly to declare the
       number of bits acted upon in an operation if the operation would
       be ambiguous otherwise.

         ;the size of [BX+SI-10] would be ambiguous
          Mov Word [Bx+Si-10], 0   ;perform a 16 bit move

       ******************************************************************

       VALUE

       Value of operand.

       Return the value of its argument.


       60                                             Functional Operands

       Its argument may be anything.  The value is returned as 16 bit
       immediate data for comparison with the value of other operands.
       See Conditional Operand Testing.

         ;the NOP is assembled if the values are identical
          If Value Ax = Value Symbol ;compare sizes
           Nop                ;code if true
          Endif               ;end of conditional

       ******************************************************************


       Assembly Constants                                              61

                               Assembly Constants

       Assembly constants are special symbols that are interpreted into
       immediate data during assembly.  Assembly constants may be used
       anywhere in place of immediate data.  Beware that these constants
       can cause an otherwise unexplained phase errors when used with
       instructions that directly manipulate the the location counter,
       like ORG.  Care should also be taken when using assembly constants
       with assembly directives that must control the assembly based on a
       value. Assembly constants may always be safely used as operands
       for 8086 instructions and in byte and word declarations (DB and
       DW).

       All symbols starting with a dollar sign are reserved as assembly
       constants.

       ******************************************************************

       $

       Present location.

       Returns the present value of the location counter.  Same as $LOC.
       May be safely used with the ORG directive.  16 bit.

         ;declares two memory labels that are ten bytes from each other

         Data_Area1 Label Byte   ;first label
                    Org $ + 10   ;advance location counter
         Data_Area2 Label Byte   ;second label

       ******************************************************************

       $CHKSUM

       Program checksum.

       Returns the byte checksum of the object code up to and including
       the previous source line.  8 bit.

       ******************************************************************

       $COUNT

       Byte count.

       Returns the number of bytes of code since the beginning of the
       program or the last RESETC directive.  16 bit.


       62                                              Assembly Constants

         ;branch around the string and then load its size
          Jmps Continue                  ;skip string
          Resetc                         ;reset counter
          Db 'Which way did he go?'      ;string declaration
         Continue                        ;continue execution
          Mov Cx, $Count                 ;load byte count

       ******************************************************************

       $DATE1

       Month and day.

       Returns the present day and month in the system format.  The high
       byte is the month (1 to 12) and the low byte is the day (1 to 31).
       16 bit.

       ******************************************************************

       $DATE2

       Year.

       Returns the present year in the system format.  The value is 1980
       to 2099.  16 bit.

       ******************************************************************

       $END

       End of program.

       Returns the last location counter value of the program.  If no ORG
       statments have been used, it will return the same thing as $SIZE +
       100H.  Is useful in adjusting the memory allocation.

        ;reduce memory allocation to minimum, assume ES=SS=CS
          Mov Ah, 4ah          ;function number
          Mov Bx, $END         ;end of code and data
          Mov Sp, Bx           ;set stack
          Shr Bx
          Shr Bx
          Shr Bx
          Shr Bx               ;make paragraph form, BX/16
          Inc Bx               ;round up
          Int 21h              ;execute

          :                    ;all code and data

          Org +100h            ;make room for stack
         ;<-- this is the location that $END will return.


       Assembly Constants                                              63

       ******************************************************************

       $LOC

       Present location.

       Returns the present value of the location counter.  Same as $.
       May be safely used with the ORG directive.

       ******************************************************************

       $SIZE

       Program size.

       Returns the total size of the assembled program in bytes.  16 bit.

         ;load the size of the program into AX
          Mov Ax, $Size  ;load size

       ******************************************************************

       $SUM

       Counter checksum.

       Returns the byte checksum of the object code up to and including
       the previous source line since the beginning of the program or the
       last RESETC.  8 bit.

       ******************************************************************

       $TIME1

       Second and 1/100 second.

       Returns the present second and 1/100 second in the system format.
       The high byte is the second (0 to 59) and the low byte is the
       1/100 second (0 to 99).  16 bit.

       ******************************************************************

       $TIME2

       Hour and minute.

       Returns the present hour and minute in the system format.  The
       high byte is the hour (0 to 23) and the low byte is the minute (0
       to 59).  16 bit.


       64                                              Assembly Constants

       ******************************************************************

       $VERSION

       Assembler version.

       Returns the version number of the assembler.  The high byte is the
       minor version number and the low byte is the major version number.

         ;if assembling with WASM 2.14, AL get 2 and AH gets 14
          Mov Ax, $Version

       ******************************************************************


       Reserved Symbols                                                65

                                Reserved Symbols

       The following are guidelines for what not to use as symbols.  All
       of these symbols have special meaning to WASM:

         AX      AL      ES       BYTE      OR
         CX      CL      CS       WORD      AND
         DX      DL      SS       DWORD     XOR
         BX      BL      DS       QWORD     MOD
         SP      AH      NOT      TBYTE     SIZE
         BP      CH      OFFSET   ANYSIZE   TYPE
         SI      DH      NEAR     ST        VALUE
         DI      BH      FAR      NEG

       A single question mark is also a reserved symbol.  All fields
       beginning with 0 to 9 are reserved for numbers.  All fields
       starting with a dollar sign ($) are reserved for assembly
       constants.  The following characters should never be used in
       symbols: control characters (ASCII 0 to 31), spaces, commas; and
       also any of the following: ; + - * = ' / \ ( ) < > [ ]  Macros
       should be unique from all other instructions, rather than the
       special symbols above.  It is recommended that programmer defined
       symbols start with a letter and consist of only letters, numbers,
       and underscores.

       66                                                Assembly Listing

                                Assembly Listing

       The assembly listing is a comprehensive trace of the assembly and
       can be useful in debugging or making a hard copy of a program.  A
       listing is only generated if a list file is specified.  The
       assembly is speeded up if no list is generated.  A listing can be
       started or stopped with LIST+ and LIST- (these directives are
       ignored if no list file is specified).  The listing of macro
       expansion lines can be enabled with EXPAND+ (the default), or
       disabled with the EXPAND-.  Also a listing of the symbol table
       will be generated if a SYMDUMP+ is included somewhere in the
       program (see Symbol Table Listing).

       List directives within an included file only apply to the listing
       of that file, and expand directives within a macro only apply to
       the expansion of that macro.  This means you can place a LIST- at
       the start of an included file to suppress the listing of just that
       file. You can use an EXPAND- similarly to create a macro that is
       never expanded.

       The listing may be divided up into pages.  An individual page can
       be started with PAGE.  Automatic paging can be turned on with
       PAGE+ and turned off with PAGE- (the default).  The default page
       size is 60 lines (which includes a five line page header).  The
       page size can be modified with PAGESIZE.

       Each list page starts with a formfeed (ASCII 12) and a list
       header.  The formfeed is not included on the first page or on any
       pages of a listing sent to CON.  The list header consists of a
       programmer defined title and subtitle, the name of the main source
       file, the page number, the time and date, columnar headings for
       the list lines, and the assembler version.

       The title and subtitle are left justified in lines one and two
       respectively.  Only one title applies for an entire assembly
       listing.  Both the title and subtitle can be set with TITLE.  The
       subtitle can also be set with SUBTITLE, PAGE, and PAGE+.

       The source file name is displayed with the present page number,
       separated by a pair of dashes, right justified on the first line
       (opposite to the title).  Only the main source file name is
       displayed (never any included file names).  The page number starts
       at one and increments with each page.  The page number is never
       directly based on the pages within a source file (unlike list line
       numbers).  The page number can be set with PAGE and PAGE+.

       The time and date are right justified on the second line (opposite
       to the subtitle).


       Assembly Listing                                                67

       The columnar headings and the assembler version follow a blank
       line after the first two lines of the header (they are on line
       four).  In the columnar list headings: Loc stands for location
       counter, Obj stands for object code, Line stands for line number,
       and Source stands for source code.  The assembler version is
       justified to the right of the headings.

       The listing starts after another blank line (i.e. the sixth line
       of the page).  Each list line contains the location counter value
       (in hex), the object code for that line (also in hex), the source
       line number, a special indicator byte, and the source line itself.

       The location counter is not displayed if the line is blank or the
       location is not relevant to the instruction contained in that
       source line.

       No object code will be displayed if, of course, none is generated
       by the source line.  Some instructions (DS) never display their
       object code.  Procedure (PROC) and End-Procedure (ENDP) directives
       display the present procedure nest level instead.  Macros display
       the present macro nest level.

       The line number is always the actual line number within the source
       file.  Included source files maintain their own line numbering.
       You can use this number in your text editor to locate the line
       within its file.  Since macro expansion lines are not in the
       source file, no line number is displayed.

       The special indicator byte is a plus (+) for macro expansion
       lines, a minus (-) for included source files, and is blank
       otherwise.

       The source line is converted to upper-case (except for strings and
       comments), and will be truncated if necessary to make the entire
       list line the proper width.  The default width is 79.  The width
       can be modified with LINESIZE and PAGESIZE.  The LINESIZE
       directive can also be used to send special codes to your printer
       (with the purpose of setting a font).

       All the assembly directives mentioned in this description can be
       looked up under Assembly Directives.


       68                                            Symbol Table Listing

                              Symbol Table Listing

       A symbol table listing can be activated with SYMDUMP+.  The symbol
       table is listed at the very end of the assembly.  All symbols in
       the program are included, except symbols within macro expansions
       or declarations, and symbols that were defined in code that was
       skipped due to conditional assembly.

       The symbol table listing is divided five parts: Branch Locations,
       Memory References, Equated Values, Defined Macros, and Undefined
       Symbols.  Each section starts a new page.  The titles describing
       the section replace the normal columnar headings.

       The symbols are sorted alphabetically within each section.  For
       the purposes of alphabetization, underscores are ignored, for
       example: the symbol A_B carries the same weight as AB, both of
       these symbols would come after AA and before AC.  If a value is
       displayed with the symbol, it will be lined up to the right,
       expressed in hex.

       The branch locations section lists all the branch labels (types
       NEAR and FAR) within the program, including the names of
       procedures (which are just near labels).  Each symbol is
       accompanied by the location it represents.

       The memory reference section lists all the memory reference labels
       (type BYTE, WORD, etc.) within the program.  Each symbol is
       accompanied by the location it represents.

       The equated values section lists all the symbols defined by the
       EQU directive.  Each symbol is accompanied by the value it
       represents.

       The defined macros section lists all the macros that where defined
       within the program.  Every macro that was defined will be listed,
       whether or not it was used.

       The undefined symbols section lists all symbols that were used but
       not defined.


       Assembly Messages                                               69

                                Assembly Messages

       The integrity of the source code is constantly checked during
       assembly.  Lines containing errors will be flagged with an
       appropriate error message.  Some lines are only flagged with a
       comment.  A comment is more of an observation than an error.
       Comments try to provide useful advice about the assembly.
       Comments are not included in the error count displayed at the end
       of assembly.

       Error and comment messages will be sent to the list file if a
       listing is being generated, otherwise the message will be
       displayed to the screen followed by the source line that caused
       the error or comment.  A line may be flagged with more than one
       message.  Paging occurs indiscriminately, so that error or comment
       messages may not appear on the same page as the line that they are
       flagging.

       Error messages start with "- - - Error: " and comment messages
       start with "- - - Comment: ".  Many error and comment messages are
       followed on the same line by sections of the source code or
       numbers.  Numbers will either be decimal or hexadecimal (followed
       by an "H").  If a line is flagged in an included file, the name of
       the file will appear in parenthesis following the message.  If a
       line is flagged in a macro expansion, the last source line number
       will appear in parenthesis.  If both of these conditions are true,
       then both the file name and line number will appear.

       Many times the thing that caused one error will cause others, so
       fixing up one error will often clear up others.  If the reasons
       for a particular error are unclear, try solving any previous
       errors first.

       Some errors may terminate the assembly.  If this happens, the
       message ">>>Cannot Continue<<<" will be displayed to the screen
       and the speaker will be sounded.

       Several assembly directives allow control over error flagging and
       detection.  The flagging of every undefined symbol occurrence can
       be activated or deactivated with FLAGALL+ and FLAGALL-; the
       detection of possible short unconditional jumps may be activated
       or deactivated with JUMP+ and JUMP-; and the flagging of unused
       symbols may be activated or deactivated with UNUSED+ and UNUSED-.
       A programmer defined error may be created with ERROR.  Finally,
       the maximum number of errors detected before the assembly is
       terminated can be controlled with ERRORMAX.  See Assembly
       Directives for more information on these directives.


       70                                               Assembly Messages

       The following is a description of all assembly messages:

       Address error
         There is some kind of error in an indirect memory operand.
         Probably an illegal combination of addressing registers.  The
         legal addressing register combinations are: BX, BP, DI, SI,
         BX+DI, BX+SI, BP+DI, and BP+SI.  Any of these combinations may
         also include an immediate data offset or displacement.

       Ambiguous memory reference
         A memory operand does not have its size properly specified.
         Usually occurs when the operands are a memory operand and
         immediate data and the size of the first is not defined.  Under
         those circumstances, the size of the memory operand should be
         defined with an explicit BYTE or WORD function.  This error also
         occurs if a LABEL directive is missing its operand.

       Cannot create list file: <file name>
         The list file could not be created or opened.  Probably because
         of an invalid file name.  The name of the list file is
         displayed.  Refer to the DOS manual for a description of legal
         file names.  Critical error.

       Cannot create object file: <file name>
         The object file could not be created or opened.  Probably
         because of an invalid file name.  The name of the object file is
         displayed.  Refer to the DOS manual for a description of legal
         file names.  Critical error.

       Could use JMPS: <displacement>
         The branch location is close enough so that a short
         unconditional jump (JMPS) instruction could be substituted for a
         normal jump (JMP).  The only effect this change would have is to
         shorten the resulting object code by one byte, i.e. the code is
         not incorrect the way it stands.  The flagging of possible short
         jumps is enabled with the JUMP+ directive.

       Data too long in declaration: <operand value>
         The initialization value (the second operand) of the DS
         directive is more than eight bits.  The value is displayed, it
         should be in the range 0 to 255.

       Disk full or write error: <file name>
         An error occurred in writing to the object or list file.
         Probably because the disk is full.  The name of the file in
         which the error occurred is displayed.  Make sure that the disk
         has enough free space, or send the object file or listing to
         another disk or device.  Critical error.

       Division by zero
         A division by zero occurred somewhere in an operand expression.
         The The value of the divisor must be changed to something other
         than zero.


       Assembly Messages                                               71

       Duplicate definition: <symbol>
         A symbol was declared more than once.  In addition to normal
         symbol declarations at the start of source lines, the parameter
         names after a MACRO directive are also considered symbol
         declarations (though only local to that macro).  Every duplicate
         definition of a symbol is flagged.  The symbol declarations must
         be changed so that they are all unique.  The symbol is
         displayed.

       ENDM without MACRO
         An ENDM directive was found without a corresponding MACRO or
         MACROC.

       ENDP without PROC
         An ENDP directive was found without a corresponding PROC.

       EQU without symbol
         The EQU directive was used without a symbol declaration.  An
         equate is meaningless without a symbol, thus a symbol
         declaration is required.

       IF statements nested too deeply: <maximum nest level>
         Conditional IF or IFN directives were nested too deeply.  The
         maximum nest level is displayed.

       Illegal addressing operand: <operand>
         An operand within brackets is not a valid addressing operand.
         The valid addressing operands are BX, BP, DI, SI, memory labels,
         and immediate data.  The operand is displayed.

       Illegal argument for ANYSIZE: <argument>
         The argument given for ANYSIZE is not valid.  The argument
         should be immediate data or a memory operand.  The argument is
         displayed.

       Illegal argument for BYTE: <argument>
         The argument given for BYTE is not valid.  The argument should
         be immediate data or a memory operand.  The argument is
         displayed.

       Illegal argument for DWORD: <argument>
         The argument given for DWORD is not valid.  The argument should
         be immediate data or a memory operand.  The argument is
         displayed.

       Illegal argument for FAR:
         The argument given for FAR is not valid.  The argument should be
         a near label, far label, or memory operand.  The argument is
         displayed.

       Illegal argument for NEAR: <argument>
         The argument given for NEAR is not valid.  The argument should
         be a near label, far label, memory operand, or immediate data.
         The argument is displayed.


       72                                               Assembly Messages

       Illegal argument for NEG: <argument>
         The argument given for NEG is not valid.  The argument should be
         immediate data.  The argument is displayed.

       Illegal argument for NOT: <argument>
         The argument given for NOT is not valid.  The argument should be
         immediate data.  The argument is displayed.

       Illegal argument for OFFSET: <argument>
         The argument given for OFFSET is not valid.  The argument should
         be a near label, far label, or memory label.  The argument is
         displayed.

       Illegal argument for QWORD: <argument>
         The argument given for QWORD is not valid.  The argument should
         be a memory operand.  The argument is displayed.

       Illegal argument for ST: <argument>
         The argument given for ST is not valid.  The argument should be
         immediate data.

       Illegal argument for TBYTE: <argument>
         The argument given for TBYTE is not valid.  The argument should
         be a memory operand.  The argument is displayed.

       Illegal argument for WORD: <argument>
         The argument given for WORD is not valid.  The argument should
         be immediate data or a memory operand.  The argument is
         displayed.

       Illegal number or symbol: <operand field>: <illegal character>
         An operand field started with a numerical digit (0 to 9), thus
         is interpreted as a number, but has an illegal character in it.
         Usually is a result of leaving the "H" off the end of
         hexadecimal numbers.  May also be the result of using a symbol
         that was inadvertently declared with a digit as its first
         character.  The operand field and the illegal character within
         it are displayed.

       Illegal operand in declaration: <operand>
         An operand in a DB or DW directive is invalid.  All DB operands
         must be immediate data or strings.  All DW operands must be
         immediate data.  The operand is displayed.


       Assembly Messages                                               73

       Illegal operand(s): <first type> <second type>
         One or both of the operands given for the instruction are
         not valid.  The first two operand types are displayed.  The
         valid operands for any given instruction may be looked up under
         Instruction Set.

         The following table shows the meaning of the displayed type
         bits.  Multiple bits may be active, like AX = 0006H (bits one
         and two):

         Bit  Operand Type
         ---  ------------
           0  no operand
           1  non-segment register
           2  accumulator (AX or AL)
           3  segment register
           4  memory operand in brackets
           5  immediate data
           6  string
           7  near label
           8  far label
           9  memory label
          10  8087 stack
          11  8087 stack top
          12  signed operand
          13  undefined symbol
          14  (internal use)
          15  (internal use)

       Illegal operator or symbol: <operator>
         One of the special delimiters was out of place or some sort of
         broader syntax error occurred in the operands of the
         instruction.  May be because of an illegal operand expression,
         like AX+1.  May be because of an extra operator, like 1+++1.
         May be because of a generally illegal construct, like (1+) or
         [OFFSET].  May be because of an illegal operator within a memory
         operand, like [5*3] or [1-BX].  May be because of illegal
         operators in the parameter names after the MACRO directive, like
         A+B.  The illegal character (operator) is displayed.  The
         operators AND, OR, XOR, and MOD will only show up as A, O, X,
         and \.

       Illegal printer code: <operand>
         A printer code following the LINESIZE directive is not valid.
         The printer codes must be 8 bit immediate data.

       Illegal reference: <value>
         The value of an equate changed during assembly and is thus not
         valid.  Probably because a changeable assembly constant was
         used, or the equate referenced an operand with OFFSET in it
         before the OFFSET argument was defined, or the equate referenced
         another, not yet defined equate.  The initial value of the
         equate is displayed.


       74                                               Assembly Messages

       Illegal use of MACRO symbol: <symbol>
         A macro symbol was used as an operand.  Macros may only be used
         as instructions.  The symbol is displayed.

       INCLUDE file not found: <file name>
         The include file could not be found or opened.  Probably because
         of an incorrect file name.  Make sure that all components of the
         file name are correct.  Remember that the source drive/path and
         an extension of ASM are assumed if not otherwise specified.  The
         name of the include file is displayed.

       INCLUDE's nested too deeply
         An INCLUDE directive inside of an included file was encountered.
         Include files may not be nested.

       INCLUDE within macro
         An INCLUDE directive inside of a macro expansion was detected.
         INCLUDE's may not be placed in macros.

       Invalid character in symbol: <symbol>
         The symbol being declared contains invalid character(s).
         Presently all symbols with a first character of "0" through "9"
         (reserved for numbers) or a first character of "$" (reserved for
         assembly constants) are flagged.  Macro parameter names
         (following a MACRO directive) can also be flagged in a similar
         manner.  The symbol must be changed so it conforms to the legal
         format.  The symbol is displayed.  See Reserved Symbols.

       Invalid operand size: <first size> <second size>
         No version of the instruction was found with matching operand
         sizes. This comment is provided to assist in fixing an Invalid
         Operands error.  The size of the first two operands are
         displayed. The valid operands and sizes for any given
         instruction may be looked up under Instruction Set.

         The following table shows the meaning of the displayed size
         bits.  Multiple bits may be active, like 5 = 0003H (bits zero
         and one):

         Bit  Operand Size
         ---  ------------
          0   8 bits, byte
          1   16 bits, word
          2   32 bits, double word
          3   64 bits, quadruple word
          4   80 bits, ten byte

         Bits 5 through 15 are for internal use.

       LABEL without label
         The LABEL directive was used without a symbol declaration.  A
         label declaration is meaningless without a symbol, thus a symbol
         is required.


       Assembly Messages                                               75

       Line size out of range: <specified size>
         The length of the line specified by a LINESIZE or PAGESIZE
         directive is either too small or too large.  The value must be
         in the range 45 to 158.  The value is displayed.

       MACRO without symbol
         The MACRO directive was used without a symbol declaration.  A
         macro declaration is meaningless without a symbol, thus a symbol
         is required.

       Macros nested too deeply: <maximum nest level>
         Macros are being expanded too deeply.  The maximum nest level is
         displayed.

       Missing ENDIF: <number>
         At least one ENDIF directive was found to be missing when the
         end of the source code was reached.  The number of missing
         ENDIF's are displayed.

       Missing ENDM
         An ENDM directive was found without a corresponding MACRO.

       Missing ENDP: <number>
         At least one ENDP directive was found to be missing when the end
         of the program was reached.  Since specific PROC's are not
         matched to specific ENDP's, the actual error may exist anywhere
         in the program, even though it isn't detected until the end of
         the program.  The number of missing ENDP's are displayed.

       Missing IF
         A NEXTIF, ELSEIF, ELSE, or ENDIF directive was found without a
         corresponding IF or IFN.  All conditional sections of source
         code must start with an IF or IFN.

       Missing or illegal operator: <field>
         Two fields were found not separated by a comma or valid
         operator.  Individual components of an operand expression must
         be separated by some kind of operator.  The individual operands
         of an instruction must be separated by commas.  Something like a
         misspelled AND operator could cause this error.  The second of
         the two fields are displayed.

       Missing PROC
         A RET instruction was found outside of a procedure.  Since the
         RET instruction needs a PROC directive to set the type of
         return, all RET's must fall within a procedure.  Near and far
         returns can be encoded independent of procedure definitions with
         RETN and RETF.

       Missing right bracket
         A memory operand using brackets came to an end without a right
         bracket (via an end of line or comma).  May occur because of a
         general error in syntax, like [OFFSET], where the bracket is
         passed to the OFFSET function as an argument and is overlooked.


       76                                               Assembly Messages

       Operand cannot be combined: <operand>
         The operand may not be used in an expression.  The operand is
         displayed.  Only immediate data may be used in expressions.

       Operands are incompatible sizes: <first size> <second size>
         The operands for the instruction are not compatible sizes,
         though the instruction involves exchanging data between the two.
         The sizes of the first two operands are displayed.  See the
         Invalid Operand Size error for a description of the size bits.

       Out of memory for code table: <maximum lines>
         The internal code table is full and no more lines can be
         assembled.  The maximum number of source lines that can be
         assembled is displayed.  See Memory Limitations.  Critical
         error.

       Out of memory for macro table: <bytes available>
         The internal macro storage area is full and no more macros can
         be defined.  The total available bytes of macro storage is
         displayed.  See Memory Limitations.  Critical error.

       Out of memory for symbol table: <symbol>: <bytes available>
         The internal symbol table is full and no more symbols may be
         defined.  The symbol that caused the error and the total
         available bytes for the symbol table is displayed.  See Memory
         Limitations.  Critical error.

       Overflow: <number>
         A number or the result of an expression is too big or too small.
         Individual numbers must be in the range 0 to 65535 (unsigned) or
         +32767 to -32768 (signed).  If any single value in an expression
         is signed, the entire expression is considered signed.  The
         final result of an expression must fall in the same unsigned or
         signed ranges as individual numbers.  If the error occurs
         because of an individual number, the number will be displayed.

       Page size out of range: <specified size>
         The length of the page specified by a PAGESIZE directive is
         either too small or too large.  The value must be in the range
         15 to 255. The value is displayed.

       Parenthesis nested too deeply
         The parenthesis in an operand expression were nested too deeply.
         Parenthesis may only be nested ten deep.

       Parenthetical error
         There was some kind of error in an operand expression involving
         parenthesis, like ((1).


       Assembly Messages                                               77

       Phase error: <previous value>
         The location counter somehow became out of phase with previous
         assembly passes.  The error may be occurring sometime previous
         to its detection, since the phase is only checked for symbol
         declarations (only labels).  This error probably means that the
         source code was assembled differently in different passes.
         Could be caused by something like conditionally assembling a
         section of the code based on the one of the time constants (like
         $TIME1), which may be different each pass.  Could also be caused
         by directly manipulating the location counter in an unsound
         fashion, like using assembly constants (which aren't really very
         constant) to set the location counter.  The previous location
         counter value is displayed.

       Procedures nested too deeply: <maximum nest level>
         Procedure declarations are nested too deeply.  The maximum nest
         level is displayed.

       Register size override: <first size> <second size>
         The size of the register is not compatible with the size of the
         memory operand.  The size of the memory operand may explicitly
         changed with a BYTE or WORD function.  The sizes of the first
         two operands are displayed.  See the Invalid Operand Size error
         for a description of the size bits.  This message doesn't
         necessarily indicate an error, but merely acts as a warning.

       Should be byte data
         The immediate data operand (port number) of an IN or OUT
         instruction is not eight bits.

       Source file not found: <file name>
         The source file could not be found or opened.  Probably because
         of an incorrectly typed file name.  Make sure that all
         components of the file name are correct.  Remember that the
         default drive/path and an extension of ASM are assumed if not
         otherwise specified.  The name of the source file is displayed.
         Critical error.

       Source line too long: <excess>
         The line within a macro expansion would be too long if all the
         parameters in that line were inserted.  The parameters or the
         line itself must be shortened.  The approximate amount by which
         the line is too long by is displayed.

       String not closed
         A string field was started with a single quote but not closed by
         a matching one.  A matching single quote must be added.


       78                                               Assembly Messages

       Too far for short jump: <displacement>
         The target of the branch is not close enough for a short jump
         (its displacement should be in the range +127 to -128, or 007F
         to FF80 hex).  If the instruction is a JMPS, then JMP may be
         used instead.  If the instruction is one of the conditional
         branches, the source code must be moved around so that target is
         closer, or a combination of conditional and unconditional
         branching must be used.  The present displacement is displayed.

           ;you could change the following ...
            Jz Toofar    ;TOOFAR is too far for a short jump

           ;... to the following
            Jnz Skipjump ;skip long jump on opposite condition
            Jmp Toofar   ;long jump to TOOFAR
           Skipjump

       Too many MACRO parameters: <maximum parameters>
         Too many parameters are being passed to the macro upon
         invocation.  The maximum number of parameters is not determined
         by the number specified in the macro declaration, but rather is
         based on internal memory constraints.  The number of parameters
         must be reduced.  The maximum allowed parameters are displayed.

       Undefined assembly directive: <number>
         Should not get this error.  It means that the instruction is an
         assembly directive that is not fully defined.

       Undefined error
         Should not get this error.  It means that an undefined error
         occurred.

       Undefined symbol: <symbol>
         The symbol was used but not defined anywhere.  Might be because
         the first digit of a hexadecimal number was not 0 through 9.
         This error can be enabled for all subsequent occurrences of
         the symbol with the FLAGALL+ directive.

       Unrecognized instruction: <mnemonic>
         The instruction mnemonic was not recognized.  It is not an 8086
         instruction, assembly directive, or a macro.  The mnemonic is
         displayed.

       Unused symbol: <symbol>
         The declared symbol was never used.  This message does not
         indicate an error, but rather assists in "cleaning up" the
         source code.  The detection of unused symbols enabled is enabled
         with the UNUSED+ directive.

       WASM detects checksum failure
         The copy of WASM.COM is corrupted and cannot be used.  If you
         don't know why you're getting this message, try making a new
         working copy from your master disk or the original archive file.


       Assembly Messages                                               79

       WASM detects incorrect DOS version
         The operating system is pre-2.0.  WASM requires PC or MS DOS 2.0
         or greater to function.

       WASM detects insufficient memory
         There is not enough free memory for WASM to function.  Though
         your computer may have enough memory installed, device drivers
         and memory resident programs could be using too much.  See
         Memory Limitations.

       80                                                 Instruction Set

                                 Instruction Set

       This is a brief list of all the legal predefined instructions and
       their operand types.  The instructions are divided up by function.
       The groups are: assembly directives, data transfer, arithmetic,
       logic, flag setting, control transfer, string manipulation, and
       processor control, 8087 Data Transfer, 8087 Arithmetic, 8087
       Transcendental, 8087 Constants, 8087 Flag Setting, 8087 Processor
       Control.  The assembly directives are more thoroughly described
       under Assembly Directives.  The 8086 and 8087 instructions are not
       thoroughly described in this documentation, you'll need another
       source for that.

       Instruction Format:

         <mnemonic> = <short description>
           <operand> [, <operand>, ...] [=<comment>]

       Operand Types:

         none     no operands
         reg      register (non-segment)
         seg      segment register
         accum    AX or AL
         mem      memory operand
         immed    immediate data
         stack    8087 stack operand
         near     near label
         string   string data
         symbol   a unique symbol

       Operands separated by slashes mean that either one may be used.
       Operands in capital letters are the literal operands accepted.
       Operands in brackets are optional, all others are required.

       Numbers in parenthesis indicate the allowable size (number of
       bits) for the specified operands.  If no size is given then the
       operands may be either 8 or 16 bit (where applicable).

       All 8087 instructions begin with F, while integer forms of
       instructions begin with FI, BCD forms begin with FB, and no-wait
       form begin with FN.  Instructions that pop the stack upon
       completion end with a P.  Instructions that reverse the order of
       operation (source <op> destination, instead of destination <op>
       source) end with an R.  Instructions that both pop and reverse end
       with an RP.  Instructions that encode without a wait begin with
       FN.

       ******************************************************************

                               Assembly Directives

       DB = declare bytes
         immed/string [, immed/string, ...]


       Instruction Set                                                 81

       DS = declare storage
         immed [, immed(8)] = bytes, value (default 0)

       DW = declare words
         immed [, immed, ...]

       ELSE = conditional "else"
         immed

       ELSEIF = conditional "else-if"
         immed

       ENDIF = end of conditional statement
         none

       ENDM = end of macro declaration
         none

       ENDP = end of procedure
         none

       EQU = equate, requires label
         immed

       ERROR = programmer defined error
         string = error message

       EXPAND+ = list macro expansions (default)
         none

       EXPAND- = do not list macro expansions
         none

       ERRORMAX = set maximum errors (default 65535)
         immed

       FLAGALL+ = flag all occurrences of undefined symbols
         none

       FLAGALL- = flag only first occurrence of undef. symbols (default)
         none

       IF = conditional "if"
         immed

       IFN = conditional "if not"
         immed

       INCLUDE = include source file
         string = file name (default source drive and ext)

       JUMP+ = flag long jumps that could be short
         none


       82                                                 Instruction Set

       JUMP- = do not flag long jumps that could be short (default)
         none

       LABEL = define label, requires label
         NEAR/FAR/BYTE/WORD/DWORD/QWORD/TBYTE/ANYSIZE

       LINESIZE = set page width (default 79)
         [immed] [, immed(8), ...] = page width, printer codes

       LIST+ = generate listing (default if list file specified)
         none

       LIST- = list output off
         none

       MACRO = start of macro declaration
         [symbol, ...] = parameter names

       MACROC = start of conditional macro declaration
         [symbol, ...] = parameter names

       NEXTIF = conditional "if", same level
         immed

       ORG = origin (default 100H)
         immed = relative to location if signed

       PAGE = start new page
         [immed/string]  = page number, subtitle
         immed [, string] = page number, subtitle

       PAGE+ = start auto paging
         [immed/string]  = page number, subtitle
         immed [, string] = page number, subtitle

       PAGE- = stop auto paging (default)
         none

       PAGESIZE = set page size (default 60,79)
         immed [,immed] = page length, page width

       PROC = beginning of procedure
         NEAR/FAR

       RESETC = reset byte counter
        [immed] [,immed] = counter value, checksum value (default 0, 0)

       SUBTITLE = set program subtitle
         string = subtitle

       SYMDUMP+ = symbol table dump on
         none


       Instruction Set                                                 83

       SYMDUMP- = symbol table dump off (default)
         none

       TITLE = set program title
         string [, string] = title, subtitle

       UNUSED+ = flag unused symbols
         none

       UNUSED- = do not flag unused symbols (default)
         none

       ******************************************************************

                                  Data Transfer

       IN = input
         accum, immed(8) = input from a fixed port
         accum, DX = input from a variable port in DX

       LAHF = load AH with flags
         none

       LDS = load DS and register
         reg(16), reg/mem

       LEA = load effective address
         reg(16), reg/mem

       LES = load ES and register
         reg(16), reg/mem

       MOV = move
         reg/mem, reg/seg
         reg/seg, reg/mem
         reg/mem, immed

       OUT = output
         immed(8), accum = output to fixed port
         DX, accum = output to variable port in DX

       POP = pop (16)
         reg/seg/mem

       POPF = pop flags
         none

       PUSH = push (16)
         reg/seg/mem

       PUSHF = pop flags
         none


       84                                                 Instruction Set

       SAHF = store AH to flags
         none

       XCHG = exchange
         reg/mem, reg
         reg, reg/mem

       XLAT = translate byte in AL
         none

       ******************************************************************

                                   Arithmetic

       AAA = ASCII adjust for add
         none

       AAD = ASCII adjust for divide
         none

       AAM = ASCII adjust for multiply
         none

       AAS =  ASCII adjust for subtract
         none

       ADC = add with carry
         reg/mem, reg
         reg, reg/mem
         reg/mem, immed

       ADD = add
         reg/mem, reg
         reg, reg/mem
         reg/mem, immed

       CBW = convert byte to word
         none

       CWD = convert word to double word
         none

       DAA = decimal adjust for add
         none

       DAS = decimal adjust for subtract
         none

       DEC = decrement
         reg/mem

       DIV = divide, unsigned
         [accum,] reg/mem = accum implicit


       Instruction Set                                                 85

       IDIV = integer divide, signed
         [accum,] reg/mem = accum implicit

       IMUL = integer multiply, signed
         [accum,] reg/mem = accum implicit

       INC = increment
         reg/mem

       MUL = multiply, unsigned
         [accum,] reg/mem = accum implicit

       NEG = decrement
         reg/mem

       SBB = subtract with borrow
         reg/mem, reg
         reg, reg/mem
         reg/mem, immed

       SUB = subtract
         reg/mem, reg
         reg, reg/mem,
         reg/mem, immed


       ******************************************************************

                                      Logic

       AND = and
         reg/mem, reg
         reg, reg/mem
         reg/mem, immed

       NOT = not
         reg/mem

       OR = or
         reg/mem, reg
         reg, reg/mem
         reg/mem, immed

       RCL = rotate through carry left
         reg/mem = one time
         reg/mem, CL = CL times

       RCR = rotate through carry right
         reg/mem = one time
         reg/mem, CL = CL times

       ROL = rotate left
         reg/mem = one time
         reg/mem, CL = CL times


       86                                                 Instruction Set

       ROR = rotate right
         reg/mem = one time
         reg/mem, CL = CL times

       SAL = shift arithmetic left
         reg/mem = one time
         reg/mem, CL = CL times

       SAR = shift arithmetic right
         reg/mem = one time
         reg/mem, CL = CL times

       SHL = shift logical left
         reg/mem = one time
         reg/mem, CL = CL times

       SHR = shift logical right
         reg/mem = one time
         reg/mem, CL = CL times

       XOR = xor
         reg/mem, reg
         reg, reg/mem
         reg/mem, immed

       ******************************************************************

                                  Flag Setting

       CLC = clear carry
         none

       CLD = clear direction
         none

       CLI = clear interrupt
         none

       CMC = clear complement carry
         none

       CMP = compare
         reg/mem, reg
         reg, reg/mem
         reg/mem, immed

       STC = set carry
         none

       STD = set direction
         none

       STI = set interrupt
         none


       Instruction Set                                                 87

       TEST = test
         reg/mem, reg
         reg, reg/mem
         reg/mem, immed

       ******************************************************************

                                Control Transfer

       CALL = call
         near = direct within segment
         immed (offset), immed (segment) = direct intersegment
         reg/mem = indirect within segment (16)
         mem = indirect intersegment (32)

       INT = interrupt
         immed(8)

       INT3 = type 3 interrupt
         none

       INTO = interrupt on overflow
         none

       IRET =interrupt return
         none

       JA = jump if above
         near

       JAE = jump if above or equal
         near

       JB = jump if below
         near

       JBE = jump if below or equal
         near

       JC = jump if carry
         near

       JCXZ = jump if CX equal to zero
         near

       JE = jump if equal
         near

       JG = jump if greater
         near

       JGE = jump if greater or equal
         near


       88                                                 Instruction Set

       JL = jump if less
         near

       JLE = jump if less or equal
         near

       JMP = unconditional jump
         near = direct within segment
         immed (offset), immed (segment) = direct intersegment
         reg/mem = indirect within segment (16)
         mem = indirect intersegment (32)

       JMPS = unconditional short jump
         near

       JNA = jump if not above
         near

       JNAE = jump if not above or equal
         near

       JNB = jump if not below
         near

       JNBE = jump if not below or equal
         near

       JNC = jump if no carry
         near

       JNE = jump if not equal
         near

       JNG = jump if not greater
         near

       JNGE = jump if not greater or equal
         near

       JNL = jump if not less
         near

       JNLE = jump if not less or equal
         near

       JNO = jump if not overflow
         near

       JNP = jump if not parity
         near

       JNS = jump if not sign
         near


       Instruction Set                                                 89

       JNZ = jump if not zero
         near

       JO = jump if overflow
         near

       JP = jump if parity
         near

       JPE = jump if parity even
         near

       JPO = jump if parity odd
         near

       JS = jump if sign
         near

       JZ = jump if zero
         near

       LOOP = loop CX times
         near

       LOOPE = loop while equal
         near

       LOOPNE = loop while not equal
         near

       LOOPNZ = loop while not zero
         near

       LOOPZ = loop while zero
         near

       RET = return, type determined by procedure
         none
         immed = add immed to stack

       RETF = within segment return
         none
         immed = add immed to stack

       RETN = intersegment return
         none
         immed = add immed to stack

       ******************************************************************

                               String Manipulation

       CMPSB = compare string byte
         none


       90                                                 Instruction Set

       CMPSW = compare string word
         none

       LODSB = load string byte
         none

       LODSW = load string word
         none

       MOVSB = move string byte
         none

       MOVSW = move string word
         none

       REP = repeat CX times
         none

       REPE = repeat while equal
         none

       REPNE = repeat while not equal
         none

       REPNZ = repeat while not zero
         none

       REPZ = repeat while zero
         none

       SCASB = scan string byte
         none

       SCASW = scan string word
         none

       STOSB = store string byte
         none

       STOSW = store string word
         none

       ******************************************************************

                                Processor Control

       CS: = code segment override prefix
         none

       DS: = data segment override prefix
         none

       ES: = extra segment override prefix
         none


       Instruction Set                                                 91

       HLT = halt
         none

       LOCK = bus lock prefix
         none

       NOP = no operation
         none

       SEG = segment override prefix (same effect as CS:, DS:, etc.)
         seg

       SS: = stack segment override prefix
         none

       WAIT = wait
         none

       ******************************************************************

                               8087 Data Transfer

       FLD = load to real to ST
         none = FLD ST, ST(1)
         [ST,] stack
         [ST,] mem(32,64,80)

       FILD = load integer to ST
         [ST,] mem(16,32,64)

       FBLD = load BCD to ST
         [ST,] mem(80)

       FST = store ST to real
         none = FST ST(1), ST
         stack [,ST]
         mem(32,64) [,ST]

       FIST = store ST to integer
         mem(16,32) [,ST]

       FSTP = store ST to real and pop
         none = FSTP ST(1), ST
         stack [,ST]
         mem(32,64,80) [,ST]

       FISTP = store ST to integer and pop
         mem(16,32,64) [,ST]

       FBSTP = store ST to BCD and pop
         mem(80) [,ST]


       92                                                 Instruction Set

       FXCH = exchange
         none = FXCH ST(1), ST
         stack [,ST]

       ******************************************************************

                                 8087 Arithmetic

       FADD = add real to ST
         none = FADDP ST(1), ST
         stack, ST
         [ST,] stack
         [ST,] mem(32,64)

       FIADD = add integer to ST
         [ST,] mem(16,32)

       FADDP = add ST to real and pop
         none = FADDP ST(1), ST
         stack [,ST]

       FABS = absolute value of ST
         none

       FCHS = change sign of ST
         none

       FDIV = divide ST by real
         none = FDIVP ST(1), ST
         stack, ST
         [ST,] stack
         [ST,] mem(32,64)

       FIDIV = divide ST by integer
         [ST,] mem(16,32)

       FDIVP = divide ST by real and pop
         none = FDIVP ST(1), ST
         stack [,ST]

       FDIVR = divide real by ST
         none = FDIVRP ST(1), ST
         stack, ST
         [ST,] stack
         [ST,] mem(32,64)

       FIDIVR = divide integer by ST
         [ST,] mem(16,32)

       FDIVRP = divide real by ST and pop
         none = FDIVRP ST(1), ST
         stack [,ST]


       Instruction Set                                                 93

       FMUL = multiply real with ST
         none = FMULP ST(1), ST
         stack, ST
         [ST,] stack
         [ST,] mem(32,64)

       FIMUL = multiply integer with ST
         [ST,] mem(16,32)

       FMULP = multiply real with ST and pop
         none = FMULP ST(1), ST
         stack [,ST]

       FPREM = partial remainder of ST divided by ST(1)
         none

       FRNDINT = round ST to integer
         none

       FSCALE = scale ST by ST(1)
         none

       FSQRT = square root of ST
         none

       FSUB = subtract real from ST
         none = FSUBP ST(1), ST
         stack, ST
         [ST,] stack
         [ST,] mem(32,64)

       FISUB = subtract integer from ST
         [ST,] mem(16,32)

       FSUBP = subtract real from ST and pop
         none = FSUBP ST(1), ST
         stack [,ST]

       FSUBR = subtract ST from real
         none = FSUBRP ST(1), ST
         stack, ST
         [ST,] stack
         [ST,] mem(32,64)

       FISUBR = subtract ST from integer
         [ST,] mem(16,32)

       FSUBRP = subtract ST from real and pop
         none = FSUBRP ST(1), ST
         stack [,ST]


       94                                                 Instruction Set

       FXTRACT = extract components of ST
         none

       ******************************************************************

                               8087 Transcendental

       F2XM1 = [2^ST]-1
         none

       FPATAN = partial arctangent of ST divided by ST(1)
         none

       FPTAN = partial tangent of ST
         none

       FYL2X = ST(1)*[LOG2[ST]]
         none

       FYL2XP1 = ST(1)*[LOG2[ST+1]]
         none

       ******************************************************************

                                 8087 Constants

       FLD1 = load 1.0 into ST
         none

       FLDL2E = load log base 2 of e into ST
         none

       FLDL2T = load log base 2 of 10 into ST
         none

       FLDLG2 = load log base 10 of 2 into ST
         none

       FLDLN2 = load log base e of 2 into ST
         none

       FLDPI = load pi into ST
         none

       FLDZ = load 0 into ST
         none

       ******************************************************************

                                8087 Flag Setting


       Instruction Set                                                 95

       FCOM = compare real to ST
         none = FCOM ST, ST(1)
         [ST,] stack
         [ST,] mem(32,64)

       FICOM = compare integer to ST
         [ST,] mem(16,32)

       FCOMP = compare real to ST and pop
         none = FCOMP ST, ST(1)
         [ST,] stack
         [ST,] mem(32,64)

       FICOMP = compare integer to ST and pop
         [ST,] mem(16,32)

       FCOMPP = compare ST(1) to ST and pop twice
         none

       FTST = test ST
         none

       FXAM = examine ST
         none

       ******************************************************************

                             8087 Processor Control

       FCLEX = clear exceptions
         none

       FDECSTP = decrement stack pointer
         none

       FDISI = disable interrupts
         none

       FENI = enable interrupts
         none

       FFREE = free ST(i)
         none
         stack

       FINCSTP = increment stack pointer
         none

       FINIT = initialize 8087
         none

       FLDCW = load control word
         mem(16)


       96                                                 Instruction Set

       FLDENV = load environment
         mem

       FNCLEX = clear exceptions, no wait
         none

       FNDISI = disable interrupts, no wait
         none

       FNENI = enable interrupts, no wait
         none

       FNINIT = initialize 8087, no wait
         none

       FNOP = no operation
         none

       FNSAVE = save state, no wait
         mem

       FNSTCW = store control word, no wait
         mem(16)

       FNSTENV = store environment, no wait
         mem

       FRSTOR = restore state
         mem

       FNSTSW = store status word, no wait
         mem(16)

       FSAVE = save state
         mem

       FSTCW = store control word
         mem(16)

       FSTENV = store environment
         mem

       FSTSW = store status word
         mem(16)

       FWAIT = wait
         none

       ******************************************************************


       8087 Programming                                                97

                                8087 Programming

       The 8087 NDP performs operations with its own internal, 80 bit,
       floating point registers.  These registers are implemented as a
       stack.  Operations are carried out by loading the relevant data
       onto the 8087 stack, executing the operations, and then storing
       the results back to main memory.

       Though the 8087 works with and can load very accurate real
       numbers, WASM can only intialize 8 and 16 bit integers.  There are
       several ways around this shortcoming:  1. You could load only 16
       bit integers.  2. You could encode a larger number into words and
       bytes.  3. You could write a short routine to load numbers.

         ;load some integers
          Fild Data1   ;load the 16 bit integer 56
          Fild Data2   ;load the 64 bit integer 0123456789ABCDEFH

         Data1 Dw 56           ;16 bit integer
         Data2 Label Qword     ;64 bit integer
          Dw 00123h
          Dw 04567h
          Dw 089abh
          Dw 0cdefh

         ;load a floating point real number
          Fbld Data3a  ;load 123456780
          Fild Data3b  ;load 10**4
          Fld St(0)    ;duplicate
          Fmul         ;multiply and pop, now have 10**8
          Fdiv         ;divide and pop, now have 1.23456780

         Data3a Label Tbyte    ;packed BCD number (low bytes first)
          Db 80h, 67h, 45h, 23h, 01h, 00h, 00h, 00h, 00h, 00h, 00h
         Data3b Dw 10000       ;will be the exponent

       Synchronization between the two processors is achieved with the
       WAIT instruction.  WASM automatically inserts a WAIT in front of
       all 8087 instructions.  There are several instructions that may be
       encoded without the WAIT.  They are: FCLEX, FDISI, FENI, FINIT,
       FSAVE, FSTCW, FSTENV, and FSTSW.  To encode these instructions
       without a WAIT, begin the mnemonic with FN, as in FNCLEX, FNDISI,
       etc.

       If data written by the 8087 is to be accessed immediately by the
       8086, an FWAIT must be explicitly encoded.  This forces the 8086
       to wait until the 8087 has finished writing the data.

          Fstp Result          ;store result
          Fwait                ;wait for 8087 to finish
          Mov Ax, Result       ;load result to AX

         Result Dw ?


       98                                            External Subroutines

                              External Subroutines

       Programs assembled by WASM may be used as external subroutines by
       other programs.  A programming language that can call pure binary
       image, external, machine language subroutines should be able to
       call programs assembled with WASM.  BASIC and Turbo Pascal are two
       languages that can do this.  Refer to the BASIC or Pascal manual
       for the specific implementation.

       BASIC expects the external machine language subroutine to be in
       the BLOAD format.  This is easily done adding the proper header to
       the file, which is as follows:

         ;this is a BLOAD header, it should
         ;be the first code in the program
          Db 0fdh    ;BLOAD marker
          Dw 0f000H  ;segment to load it at
          Dw 0       ;offset to load it at
          Dw $Size   ;size of program

       The segment and offset of the load can be any number, since it
       should be specified by the programmer when loading it from BASIC.
       Making load address F000:0000 (which is read only memory) will
       prevent loading it over something important if the address is not
       specified.

       Turbo Pascal external subroutines do not require any special
       format.

       The code within Turbol Pascal subroutines must be relocatable.
       This means that no references to the location counter should be
       made (the location is undefined).  Since memory labels cannot be
       used, there is no good way to access declared local data; its
       probably better to just do without such data.  BASIC subroutines
       may or may not have to be relocatable, depending upon where they
       are stored.  If the address is known beforehand (in an unused
       screen buffer for instance), the code need not be relocatable and
       the starting offset will be known and can be set with ORG.  If the
       BASIC subroutine is stored in a variable's data space or a file
       buffer, then the code must be relocatable.

       Machine language subroutines may be debugged by placing an INT3
       instruction within the code and then running the entire program
       (BASIC or Pascal) under DEBUG.  When the subroutine is executed,
       the INT3 will give control to the DEBUG program and allow you to
       step through your code.  Make sure to remove the INT3 and
       reassemble the code when you are through debugging.

       Programs that are assembled as subroutines are not directly
       executable, thus it may be a wise idea to name them with an
       extension other than .COM (which implies that a program is
       executable).


       Source Code Clarification                                       99

                            Source Code Clarification

       Many of the conventions used by WASM are also used by other
       assemblers and debuggers.  This section compares WASM to other
       assemblers and the DEBUG program provided with DOS.  This section
       also points out a few particulars of WASM syntax.

       Some assemblers add a suffix to the mnemonic to indicate the size
       of the operation, whether immediate data is involved, and the type
       of calls, jumps, and returns that are being used.  WASM identifies
       the type and size of the instruction mainly on the basis of the
       operands, in accordance with the DOS DEBUG program.

       WASM allows the programmer to define the size of the operand
       through the use of a functional operand (BYTE, WORD, etc.).  This
       is very similar to the structure used by the DEBUG program and the
       IBM Macro Assembler.

         ;the following statement in WASM...
          Mov WOrD [5+sI+  10 +Bp+5], not 1111111111111111B

         ; ...is disassembled as the following in DEBUG
         ; MOV     W,[BP+SI+14],0000          ;DOS 1.1 DEBUG
         ; MOV     WORD PTR [BP+SI+14],0000   ;DOS 2.0 DEBUG

       Near and far indirect branching may be implemented by specifying
       the size of the operand or actually using the NEAR and FAR
       functions.  Debug uses FAR for far branching and nothing for near
       branching.

          Call Near [Bx]  ;
          Call Word [Bx]  ;these two are the same thing to WASM
         ;Call [Bx]       ;debug format

          Call Far [Bx]    ;
          Call Dword [Bx]  ;these two are the same thing to WASM
         ;Call Far [Bx]    ;debug format

       The size of the string manipulation instructions are specified by
       a B or W suffix added to the mnemonic.  This is the same as the
       DEBUG program.

          Movsb  ;move string byte
          Movsw  ;move string word

       JMPS is the mnemonic that WASM uses to specify a short
       unconditional jump to a near label.  JMP always means a long jump.
       The (DOS 2.0) DEBUG program uses JMP for both long and short
       jumps.

          Jmps Location1    ;short unconditional jump
          Jmp Location1     ;long unconditional jump


       100                                      Source Code Clarification

       WASM sets the type of return for a RET based on the procedure
       type.  A near (within segment) or far (intersegment) return may be
       encoded without using a PROC through the use of RETN and RETF
       respectively.  The DEBUG program uses RET to indicate a near
       return and a RETF to indicate a far return.

          Proc  Far               ;<---
          Ret         ;far return     ; far routine
          Retn        ;near return    ;
          Retf        ;far return     ;
                                      ;
          Proc  Near                  ; <---
          Ret         ;near return    ;    ; near routine
          Retn        ;near return    ;    ;
          Retf        ;far return     ;    ;
          Endp                        ; <---
                                      ;
          Ret         ;far return     ;
          Endp                    ;<---

       The bit shifting instructions (SHL, SHR, ROL, etc.) are
       interpreted to be a single shift by WASM if there is only one
       operand (the operand to be shifted).  Shifts using the CL register
       as a counter are implemented by specifying CL as the second
       operand.  The DEBUG program requires a "1" as a second operand to
       specify a single shift.

           Rol Ax      ;roll AX left by one
         ; Rol Ax,1    ;roll AX left by one, DEBUG format
           Shr Byte [Bx],Cl   ;shift 8 bits at [BX] CL times

       Some assemblers leave out an operand if the operand is implicit in
       the instruction.  AX is implicit in the following 8086
       instructions: IN, OUT, MUL, IMUL, DIV, and IDIV.  WASM requires
       the AX (or AL) register in the IN and OUT instructions but allows
       the others with or without it.  The DEBUG program leaves out the
       AX or AL register on multiply or divide instructions, but does not
       on the others.

          In    Ax,Dx   ;AX receives input word from port in DX

         ;both of the following are: AX = DX.AX x CX
          Mul   Ax,Cx   ;WASM allows this
          Mul   Cx      ;WASM and DEBUG allow this

       DEBUG assembles some 8087 instructions differently than WASM.

          Fadd St(1)           ;this in WASM is encodes to
          Fadd St, St(1)       ;<--- this

          Fadd St(1)           ;but this in DEBUG encodes to
          Fadd St(1), ST       ;<--- this


       Source Code Clarification                                      101

       WASM and DEBUG implement instruction prefixes as a separate
       instruction, i.e. they appear on the line above the instruction to
       modify.  The prefixes are: LOCK, REP, REPE, REPNE, REPNZ, REPZ,
       and SEG.

          Rep
          Stosb       ;store byte CX times

          Seg Ss
          Mov Ax,[Bx] ;[Bx] is in the stack segment (SS)

       Individual segment overrides may also be specified as CS:, DS:,
       ES:, and SS:, which is how segment overrides are implemented by
       DEBUG.

         ;this is assembled properly by WASM and DEBUG
          Cs:           ;to WASM, this is the same as SEG CS
          Mov [500], Dl  ;[500] is in the code segment (CS)

       WASM and DEBUG both specify indirect memory operands by putting
       all values and registers inside the brackets.

         ;this in WASM ...
           Sub [Bx+10],Ax
           Sub [BX+Data],Ax
         ;... may be implemented by others like one of these
         ; Sub [Bx]+10,Ax
         ; Sub 10[Bx],Ax
         ; Sub Data[Bx],Ax

         Data Label Word

       The mnemonic for an optimized type 3 interrupt is INT3.

         ;both of statements these cause type 3 interrupts,
         ;but the first uses only one byte of code
          Int3
          Int 3

       WASM assumes the entire program and all data are in the same
       segment, so there are no segment definitions.  The location
       counter is automatically started at 100H, in accordance with COM
       file format.  Though WASM doesn't allow segment definitions, a
       program may, of course, set up and maintain its own segments
       during execution.

       The implementation and usage of assembly directives vary among
       assemblers.  The general format of procedure, macro, and data
       declarations are similar, but mostly incompatible among
       assemblers.  WASM uses a fairly simplified set of directives, most
       of which are comparable, though not compatible, to other
       assemblers.


       102                                      Source Code Clarification

       Several 8086 instructions mean the same thing as other
       instructions and produce identical object code.  The DEBUG program
       always disassembles these instructions using one particular
       mnemonic.  One example is JNLE (jump not less or equal) and JG
       (jump greater).  The DEBUG program disassembles both of these
       instructions as JG.

       Symbols that are declared within skipped source code should be
       undefined.  These symbols, though, are placed in the symbol table
       anyway and still subject to duplicate definition and other symbol
       declaration errors.

         ;in theory the second two symbols don't really
         ;exist, since they are in source code that is
         ;skipped because of the false IF directive; in
         ;spite of "not existing," the second declaration
         ;of SYMBOL2 causes a duplicate definition

         Symbol2
          If 0
         Symbol1  ;considered undefined
         Symbol2  ;duplicate definition
          Endif

       There is an uncaught error for certain registers as operands.
       When the operand DX is used in IN's and OUT's, and CL is used for
       shifts and rolls, WASM only looks for a register type, not those
       particular registers.  This means that in those cases any register
       will work in place of a DX or CL (except a segment register).
       Also WASM does not search for extra operands, they do not cause
       errors if they exist.

         ;some uncaught errors
          In  Ax,Bx
          Shl Ax,Bx
          Mov Ax,Bx,Cx,Dx


       Memory Limitations                                             103

                               Memory Limitations

       WASM requires a about 100 kilobytes (K) of free RAM for execution.
       The only aspect of WASM that varies with the amount of available
       memory is the macro storage capacity.  With a minimum amount of
       memory (100K), less than a 1000 bytes of macro storage is
       available.  Every free byte after that, up to 64K, is used for
       macro storage.  With 164K bytes available, the maximum usable
       amount of memory, about 1600 lines at 40 characters apiece can be
       stored.  The length of the macro lines is significant, i.e. the
       shorter the lines, the more lines that can be stored.

       The symbol table has room for about 2000 symbols at 10 bytes
       apiece.  Like macro lines, the shorter the symbols, the more
       symbols that can be stored.  An internal code table (which saves a
       partial tokenized assembly of the program) has room for 10800
       entries.  Every source line creates an entry in the code table,
       except blank lines and lines resulting from a macro expansion.
       Lines that are skipped due to conditional assembly and the
       conditional directives themselves DO take up room in the code
       table, even though they do not show up in the assembly.  The
       symbol table size and code table size do not change, even if the
       memory is available.


       104                                                   Bibliography

                                  Bibliography

       These books were used as references in the development of WASM and
       the writing of this documentation.  In addition to this list,
       there are many other excellent sources of information on the
       8086/8088 microprocessor and assembly language programming.

       Angermeyer, John, and Kevin Jaeger. "MS-DOS Developer's Guide."
         Indianapolis, IN: Howard W. Sams & Co., 1986.

       "BASIC Version 1.10." 2st ed. Boca Raton, FL: International
         Business Machines Corp., 1981 and 1982.

       Duncan, Ray. "Advanced MS DOS." Redmond, WA: Microsoft Press,
         1986.

       "iAPX 86/88, 186/188 User's Manual." Santa Clara, CA: Intel
         Corp., 1985.

       King, Richard A. "The IBM PC-DOS Handbook." Berkeley, CA: SYBEX
         Inc., 1983.

       Morgan, Christopher L., and Mitchell Waite. "8086/8088 16-Bit
         Microprocessor Primer."  Peterborough, NH: BYTE/McGraw-Hill,
         1982.

       "Technical Reference." Rev. ed. Boca Raton, FL: International
         Business Machines Corp., 1981, 1982, 1983, and 1984.

       "Turbo Pascal Reference Manual Version 3.0." Scotts Valley, CA:
         Borland International Inc., 1983, 1984, and 1985.


       Index                                                          105

                                      Index

       $                           61      Declaring data (cont.),
       '                           11        examples                  36
       ()                          14        location                  35
       ,                            6        storage                   35
       ;                            7        string                    35
       ?                           11        word                      35
       []                          11      Default file name            4
       8087,                       97      Delimiter                    6
         stack                     11      Directive,               6, 37
       Addressing,                           compatibility            101
         direct                    11        conditional               19
         indirect                  11        list of                   80
         registers                 11        syntax                     9
       ANYSIZE function            55      Distribution policy          1
       ASM filename extension       4      Dollar sign                 61
       Assembling programs          4      DS directive            35, 38
       BASIC subroutines           98      DW directive            35, 38
       Basic syntax                 6      DWORD function          56, 99
       Blank line                   7      EDLIN program                6
       Bload,                              $END constant               62
         address                   98      ELSE directive  19, 20, 21, 38
         format                    98      ELSEIF directive    19, 20, 21
       Brackets                    11                                  39
       Bug, in WASM               102      End of file                  6
       BYTE function           55, 99      ENDIF directive     19, 21, 39
       CALL instruction            17      ENDM directive          28, 40
       $CHKSUM constant            61      ENDP directive          17, 40
       COM filename extension       4      EQU directive               40
       Comma                        6      Equates                      8
       Comment,                            Error,                   5, 69
         description of messages   70        AND                       14
         message                   69        count                     69
         source                     7        critical                  69
       Compatibility of                      description of messages   70
         source code               99        flagging                  69
       CON device                   4        macro                     34
       Conditional assembly,       18        message                   69
         directive                 19        MOD                       14
         nested                    22        multiple                  69
         operand                   19        OR                        14
         operand testing           25        XOR                       14
         operator                  24      Error code,
       Constant                    61        upon termination           5
       Control characters           6      ERROR directive         41, 69
       $COUNT constant             61      ERRORLEVEL
       Data declaration            35        batch command              5
       $DATE1 constant             62      ERRORMAX directive      42, 69
       $DATE2 constant             62      EXPAND+ directive   34, 42, 66
       DB directive            35, 37      EXPAND- directive   34, 42, 66
       DEBUG program               99      Expression,                 14
       Declaring data,             35        examples                  14
         byte                      35        operators                 14


       106                                                          Index

       Expression (cont.),                 Macro (cont.),
         signed                    14        nested                    32
       File name, default           4        parameter             28, 30
       FLAGALL+ directive      43, 69        recursive                 32
       FLAGALL- directive      43, 69        symbol                    28
       IF directive    19, 21, 22, 43      MACRO directive         28, 47
       IFN directive   19, 21, 22, 43      MACROC directive        33, 47
       Immediate data,             10      Memory operand,             11
         characters                10        addressing registers      11
         in expressions            14        direct addressing         11
         size                      12        indirect addressing       11
       INCLUDE directive           44        size                      12
       Instruction,          6, 9, 37      Memory,
         bit shifting             100        allocation                62
         disassembly              102        code table               103
         list of                   80        label                      8
         prefix and override      101        limitation               103
         string                    99        minimum                  103
         syntax                     6        segments                 101
       Interrupt, type 3           98        symbol table             103
       JMP instruction             99      Message,
       JUMP+ directive         44, 69        descriptions              70
       JUMP- directive         44, 69        during assembly           69
       Label,                       8      NEAR function           56, 99
         in expressions            14      NEG function                57
         memory                 8, 35      NEXTIF directive    19, 21, 48
         near                       8      NOT function                57
       LABEL directive         35, 45      Number,                     10
       Line,                                 binary                    10
         blank                      7        decimal                   10
         syntax                     6        hexadecimal               10
       LINESIZE directive          46        signed                    10
       List,                    4, 66        size                      12
         columnar headings         67      Object file                  4
         header                    66      OFFSET function             58
         line                      67      Operand,                 6, 10
         page number               66        conditional               19
         paging                    66        constants                 61
         subtitle                  66        examples                  12
         symbol table              68        expressions               14
         title                     66        functional                55
       List file                    4        implicit                 100
       LIST+ directive         46, 66        required                  10
       LIST- directive         46, 66        size                  11, 25
       $LOC constant               63        syntax                     6
       LST filename extension       4        type                  10, 25
       Macro,                   8, 27        value                     25
         conditional               33      Operator,                   14
         defining                  28        conditional               24
         error                     34      ORG directive               49
         in conditional code       30      Origin,                     49
         invocation                30        default                  101
         listing                   34      Page number                 66
         memory limitation        103      PAGE+ directive         50, 66


       Index                                                          107

       PAGE- directive         50, 66      Subroutine (cont.),
       PAGESIZE directive      50, 66        Pascal                    98
       Parameter,                            relocation                98
         command line               4      SUBTITLE directive      52, 66
         command line examples      5      Symbol,                   6, 8
         macro                     28        as instructions            8
         macro                     30        as operands                8
         procedural                17        declaration                8
       Parenthesis,                14        declaration syntax         6
         signed                    14        label                      8
       Pascal subroutines          98        location of declaration    8
       Printer                      4        macro                     28
       PRN device                   4        required declaration       6
       PROC directive          17, 51        reserved                  65
       Procedure,                  17        table                      8
         declaration               17        type                       8
         far                       17        type determination         8
         local data                17        undefined                102
         near                      17        uniqueness        8, 65, 102
         nested                    17      Symbol table,                8
       Program structure           16        list                      68
       Question mark               11        memory limitation        103
       Quotation mark              11      SYMDUMP+ directive  52, 66, 68
       QWORD function              58      SYMDUMP- directive          52
       Register,                   10      System requirements          2
         16 bit                    11      TBYTE function              59
         8 bit                     10      Termination of assembly     69
         segment                   11      $TIME1 constant             63
         size                      12      $TIME2 constant             63
       Registration                 1      TITLE directive         53, 66
       RESETC directive            51      True                        24
       RET instruction        17, 100      TYPE function               59
       Semi-colon                   7      UNUSED+ directive       53, 69
       SIZE function               58      UNUSED- directive       53, 69
       $SIZE constant              63      VALUE function              59
       $SUM constant               63      $VERSION constant           64
       Source code,                        WORD function           59, 99
         clarification             99
         compatibility             99
         external                  44
       Source file,                 4
         external                  44
         type                       6
       Spaces                       6
       ST operand                  11
       Statistics, assembly         5
       String,                     11
         declaration               35
       Structured programing       16
       Subroutine,                 98
         BASIC                     98
         debugging                 98
         location counter          98
         naming                    98


