

                               Object File Macros
                               ------------------

     The macros defined in the file OBJECT.INC allow WASM to create
     standard object modules that can be linked with object modules from
     other languages.  The primary limitations of these macros are that
     external symbols cannot be referenced and there are certain
     limitations in the way local data may be accessed.

     I have successfully used these macros to produce WASM subroutines for
     QuickBASIC version 4.0 (using LINK.EXE version 3.65), and Turbo C++
     version 1.0 (using TLINK.EXE version 3.0).

                                 General Layout
                                 --------------

     The format of a WASM object module consists of the INIT macro first,
     all PUBLIC definitions, the BEGIN macro, all assembler code and data,
     and finally the END macro.  All assembler code and data must be
     between the BEGIN and END macros.  Example:

         INCLUDE 'obj.inc'

         INIT    'MYFILE.ASM', '_TEXT', 'CODE', ALIGN_BYTE+COMBINE_PUBLIC

         PUBLIC  MyProc1, '_MyProc1'
         PUBLIC  MyProc2, '_MyProc2'

         BEGIN

       MyProc1 PROC FAR
         ret
         ENDP

       MyProc2 PROC FAR
         ret
         ENDP

         END

     The example above declares two public symbols using the 'C' naming
     style (i.e. case sensitive with preceding underscores).  The public
     symbols reference the two procedures.  The procedures are FAR, so the
     C program must be compiled using the medium, large, or huge memory
     models.

     When these macros are used, the result of the assembly is a valid
     object module and may be linked using LINK.EXE, TLINK.EXE, or other
     compatible linker.  For instance, the example above would be compiled
     as follows:

       WASM myfile myfile.obj

                                   INIT Macro
                                   ----------

     The INIT macro creates an object module header and defines the segment
     in which to place the code and data.  The syntax for INIT is:


       INIT name, segment, class, segtype

     The name is the name of the module.  Most compilers use the name of
     the source file (including the extension) to name an object module.

     The segment is the name of the segment.  Depending on the compiler and
     the memory model, it might be necessary to place code or data in
     specific segments.  Compilers from Microsoft and Borland (and probably
     most other vendors) place the code in segment '_TEXT' when using the
     near code memory models (small and compact) and the data in segment
     '_DATA' when using near data memory models (small and medium).
     Usually any name is okay if the segment is private.

     The class is the name of the segment class.  The segment class
     primarily affects the order of the segments.  You should use either
     'CODE' if you are defining public routines or 'DATA' if you are
     defining public data.  The class may be blank, in which case the
     segment has no class:

         INIT    'MYFILE.ASM', '_TEXT', , ALIGN_BYTE+COMBINE_PUBLIC

     The segtype is the type of segment.  There are two values that must be
     added together for this argument, the alignment and combine type.  The
     possible alignment and combine values are:

       ALIGN_BYTE        byte aligned
       ALIGN_WORD        word aligned
       ALIGN_PARA        paragraph aligned
       ALIGN_PAGE        page aligned

       COMBINE_PRIVATE   private segment
       COMBINE_PUBLIC    public segment
       COMBINE_STACK     stack segment
       COMBINE_COMMON    common segment

     If you wish to declare and access local data in the segment, it will
     probably be necessary to create a paragraph aligned private segment.

     Public procedures in private segments should be FAR and the language
     must be compiled using a far code model -- either medium, large, or
     huge.  When a routine accesses data in a private segment, the current
     code segment should be used:

         BEGIN

       MyProc1 PROC FAR
         push ds
         mov ax, cs          ;load data segment from CS
         mov ds, ax          ;
         mov ax, data        ;now we can access data
         pop ds
         ret
         ENDP

       data DW ?

         END



                                  PUBLIC Macro
                                  ------------

     The PUBLIC macro creates public symbol definitions.  A symbol must be
     public if it is to be used outside of the module.  The syntax for
     PUBLIC is:

         PUBLIC symbol, name

     The symbol is a symbol from the assembler code or data to be made
     public.  The name is the name to be used by other modules in accessing
     the symbol.  Example:

         PUBLIC MyProc, 'MYPROC'

     In this example, references to MYPROC in other modules will access the
     symbol MyProc in this module.

     Depending on the compiler and memory model, it may not be possible to
     mix public references to code and data in one module.

                                BEGIN/END Macros
                                ----------------

     The BEGIN macro must appear before all code and data and the END macro
     must follow all code and data.  No code or data may appear outside of
     the BEGIN and END macros.  The END macro is usually the final
     statement of the source file.  BEGIN starts an object module data
     record and sets the origin to zero.  END finishes the data record and
     creates a module end record.

                             Language Considerations
                             -----------------------

     There are certain conventions that must be followed when writing
     subroutines for high level languages:

     1. The procedure type (NEAR or FAR) must match the memory model.
        Procedures should be NEAR when using the small or compact memory
        models.  Procedures should be FAR when using the medium, large, or
        huge memory models.  Most languages that do not support explicit
        memory models use far code segments, thus procedures should be FAR.

     2. Most languages use one of two different naming and parameter
        passing conventions, 'C' or 'pascal' (even languages are not C or
        Pascal).  'C' routines should be given a case sensitive name with a
        leading underscore, expect their parameters to be pushed on the
        stack in reverse order, and not pop parameters when exiting.
        'pascal' routines should be given a case insensitive name (all
        capital letters), expect their parameters to be pushed on the stack
        in the order they appear in the source, and must pop all parameters
        when exiting.

     Parameters are accessed via an offset from the stack pointer (SP).
     This offset depends on the routine entry code and whether the
     procedure is NEAR or FAR.

     Example:


         PUBLIC MyProc, 'MYPROC'   ;'pascal' type public symbol
       ; PUBLIC MyProc, '_MyProc'  ;'C' type public symbol

         BEGIN

       MyProc PROC NEAR      ;might also be FAR
         push bp
         mov bp, sp          ;get stack pointer
         push di             ;other regs to save
         push ds             ;

         mov ax, [bp+4]      ;first 'pascal' parameter, last 'C' parameter
                             ;should be [BP+6] if FAR procedure

         mov bx, [bp+6]      ;next parameter
                             ;should be [BP+8] if FAR procedure

         ;
         ; rest of MyProc
         ;

         pop ds
         pop di
         pop bp
         ret 4               ;fix stack if 'pascal', otherwise just RET
         ENDP

     The registers that must be saved by an assembler routine varies from
     language to language.  Most compiler manuals describe the steps
     necessary in writing and calling assembler routines.  It may also be
     useful to look at a link map from the compiler and study an executable
     program from the compiler using a debugger.

     You can write object modules for Turbo Pascal if you place the code in
     the segment CODE and leave the class blank.  Since Turbo Pascal (at
     least version 5.5) ignores the alignment and combine values, local
     data cannot be accessed.

                               WASM Library Files
                               ------------------

     The WASM library files may be used in modules as long as certain
     conditions are met.  All library files assume that DS=ES=CS.  Library
     files that require STACK.ASM assume that SS=DS=ES=CS, thus a separate
     stack must be set up.  Some of the library files won't work in
     modules, like PARMS.ASM, because the current segment is assumed to be
     the PSP segment.  Since the library files produce code and data, the
     library INCLUDE statements must be between the BEGIN and END.  Several
     of the library files have startup code that should be executed, so you
     might want to place the library INCLUDE statements within a special
     initialization routine.  Note that WASM routines cannot call WASM
     routines in other modules because WASM object modules do not support
     external symbols.
