 --
                              ĿĿĿ
                                           
                                  Ĵ         
                                         
                              
              ĿĿĿĿĿĿ  ĿĿ
                                                  
                 Ĵ                  Ŀ    Ĵ   
                               ٳ           Ĵ ڿ 
                
 --
   BAssPasC Compiler version 2.32 CardWare *  Copyright (C) 1996-97 ESP-Team
 --

 Made by:
 ~~~~~~~~
             Gereffy rpd  (GyikSoft)    garpad@sparta.banki.hu
             Pilszy Istvn  (PilaSoft)    Pila.1999C.Piar@email.piar.hu
             Brthzi Andrs (MikroLab)    bar_and@sparta.banki.hu
             Kbler Istvn                 kiskubi@labor.obuda.kando.hu

   This document is translated to English by Zoltn Rajnai (mrz / AstroideA).
 --


                                   Foreword
                                  

  This documentation is far from being complete, and it's likely that it will
  never be complete, since the development of the compiler is running faster
  than the making of the documentation. Because of this, if something isn't
  clear, or something is missing, then please feel free to write an email
  (garpad@sparta.banki.hu) and we will help you (if we can)!

  We would be happy to get any sort of help, for instance if you could phrase
  something better than we can (which will not be hard) then please write it
  down and send it to us to put in this documentation!
  And of course if you notice any kind of bug or error in this text or in the
  compiler then let us know! If you discover something (ie. in the examples)
  that is missing from this documentation, then don't hesitate, contact us!
  Also write to us if you have some new idea, or you wrote a good LIB...


                              Table of contents
                             

        1. Introduction

        2. Installation
          2.1. The files
          2.2. BASSPASC.CFG settings
          2.3. BAPC_ASM command-line
          2.4. TASM & MASM problems

        3. The structure of BAP language programs
          3.1. The structure of the program
          3.2. Possibilities
          3.3. Limitations

        4. Compiler directives

        5. Basics
          5.1. Assigning values
          5.2. Mathematical and logical operators
          5.3. Abbreviations
          5.4. Labels
          5.5. Variables
          5.6. Constants
          5.7. Strings
          5.8. Segment-prefixes
          5.9. Code-repetition

        6. Instructions
          6.1. Conditional instructions (IF, CASE)
          6.2. Loop construction (FOR, REPEAT-UNTIL, WHILE)
          6.3. Stack handling   (PUSH, POP)
          6.4. Keyboard and screen handling
          6.5. File-operations  (FILE*)
          6.6. Miscellaneous instructions
          6.7. String-like instuctions (STOSx,etc.)

        7. Modular programming
          7.1. INDIRECT-s
          7.2. The usage of routine packages (LIB-s)
          7.3. INCLUDE-s
          7.4. BAP Object (BPO)
          7.5. The usage of PACKAGE-s

        8. Macros and functions

        9. The description of the routine packages (LIBs)

       10. Free registration


                               1. Introduction
                              

      This programming language has been made for those Assembly language
  programmers who want to make fast and small program code, but are
  striving for faster development, easier overview and less typing. A
  knowledge of the Assembly language is required to master this language.
  BAP is a mix of languages, becuase it mainly includes Pascal, C, Basic
  and Perl instructions (with more or less modifications). The compiler
  generates directly in to Assembly (.ASM) language, which can be compiled
  without any changes into programs. It's possible to make .COM or .EXE
  programs.

  It is much easier to program in BAP than in Assembly, but opposed to
  higher level languages, (C, Pascal, Basic...) the program will be
  exactly as fast as if it was written in Assembly, since it is being
  compiled directly into Assembly.

  Something else: in this documentation, and in other places, this program
  is being referred to in many ways. The reason for this is that in the
  beginning the BAssPasC name gradually changed, first it became BASPASC,
  then BAPC, now we just call it BAP. If we carry on this way, this is
  going to be the "B" language... ;-)


                               2. Installation
                              

      The installation is not difficult. Because you are already reading
      this documentation, it is likely that you have already uncompressed
      the program. If not, then I made a mistake... ;)

      Important: rewrite the paths in the CFG and BAT files to the
      appropriate directories and you are done.

   2.1. The files
  

      About the files in short:

    LIB         <DIR> - base .LIB files
    LIB-DOCU    <DIR> - documentation of .LIB files
    LIB-EXAM    <DIR> - examples for using the .LIB files
    EXAMPLES.V2 <DIR> - other examples for BAssPasC v2.0+
    DOC-HUN     <DIR> - Hungarian documentation
    DOC-ENG     <DIR> - English documentation

    BAPC_ASM.EXE   - the compiler itself
    BASSPASC.CFG   - the configuration of the compiler
    BAP2COMP.BAT   - BATCH file to make compilation easier

    BAPEDIT.EXE    - editor (word processor)

    ASM2BAP.EXE    - a very old util for compiling ASM files to BAP
    ASM2BAP.PAS    - source of ASM2BAP.EXE

  Documentation files (located in DOC-??? sub-directories):
    BASSPASC.TXT   - Documentation files
    BAPEDIT.TXT    - mini help for the editor
    REGISTER.TXT   - Registration form, don't forget: the registration is FREE!
    BUGS.TXT       - Known bugs
    WHATSNEW.TXT   - What is new in this version?

   2.2. BASSPASC.CFG settings
  

   CONFIGFILE, ie.:
   ~~~~~~~~~~~~~~~~
   1.  LIBDIR=F:\GYS_LIB\;H:\BOOGIE\LIB\
     PATHs for the .LIB files
     You can specify more paths separated by a ';' character
     They must be ends with a '\' character!

   2.  TEMPDIR=R:\TEMP\
     PATH for TEMP files.

   3.  REGFILE=F:\JOHNNY\BASSPASC.REG      <optional>
     PATH and FILENAME of the registration key

     Registration key searching priority:
      1. 'REGFILE' variable defined in the BASSPASC.CFG
      2. BASSPASC.REG in the actual directory
      3. BASSPASC.REG in the compiler's directory

   4.  USES=WRITE1,SYSTEM1,MEMORY           <optional>
     Name of the default libraries (.LIB files)

   5.  INCLUDE=JOHNNY.H,MATH1.H,MEMORY.H   <optional>
     Name of the default headers (.H files)

   2.3. BAPC_ASM command-line
  

     BAPC_ASM.EXE [options] [source[.bp2] [destination[.asm] [errorfile]]]
   options:
     /Z    ->  write line where the error found
     /BPO  ->  compile to .BPO format
     /PM   ->  compile for TRAN's PMODE 2.51 extender
     /MASM ->  compile for MASM assembler
     /NASM ->  compile for NASM assembler

   2.4. TASM & MASM problems
  

      Another note: the compiler assumes the usage of TASM, but we are
      planning a version for MASM (only if there is demand for it).
      But TASM versions are not compatible, due to this, if you are not
      using TASM v3.0 then we suggest using TASM with the /U300 option,
      which enables the emulation of version 3.0. The only difference (we
      noticed) is that versions newer than 3.0 of TASM handle segment
      definitions differently:

        TASM 3.0            -  MOV AX,[ES:DI]
        newer TASM and MASM -  MOV AX,ES:[DI]

      This is practically indifferent to the BAP compiler, but in the LIB-s,
      the 3.0 forms were used, so it may cause some problems if you compile
      programs which use the LIB-s without the /UT300 option.


                  3. The structure of BAP language programs
                 

      The compiler accepts (almost) all Assembly instructions and directives,
  and puts these into the ASM file unchanged. So if we can't use certain
  portions of BAP, we can write those parts in Assembly.
      The compiler has two operating modes: ASM- and BAP-mode. BAP mode is
  assumed as the default mode of operation. In this mode, a mixture of BAP and
  Assembly can be used. In ASM-mode only Assembly instructions are allowed.
  For more informations look at the compiler directives (4. chapter)

   3.1. The structure of the program
  

      In the following section we will introduce a general program format.
  The data placed between the relation signs ("<" and ">") refers to a
  paramater, so you have to write an actual value there; square brackets
  ("[" and "]") refers to a parameter that can be left out.


    ; [Remark]                               Remarks can be placed anywhere.

    .x86 or .80x86                           This compiles the TASM header.

    USES <1.Library [, 2.Library [,...] ] >  Libraries of LIB extension to
                                             be used.
    INCLUDE <1.header.H [, 2.header [,...]>  Some LIB-s require the header
                                             files (*.H) too.

    <Program body>

    [...]                                    The instrucions of the main
                                             program body
    [EXIT]                                   To exit the program.

    [ <Procedure1>::
      [...]
      ret
    ]

    [ <Procedure1>::
      [...]
      ret
    ]

    [...]

   [ INCLUDE file1[,file2...] ]              Procedures stored in other
                                             files

   [ INCLUDEDx file1[,file2...] ]            The required binary data files

  Note: this was only a general example, most of the instructions can be
         placed anywhere.

  Example: a classical program that writes Hello World:

       .386
       WRITELN'Hello World!'
       EXIT

     Besides this the structure of the program is the same as the Assembly
  language programs, so the rules are the same ie.: the placing of the
  procedures, the Assembly macros (its advisable to use the macros of BAP),
  the loop constructions, etc.

  Comments can be put in a program the following way:
    .COMMENT        ; Dont have to compile from here
    [...]
    .ENDCOMM[ENT]   ; End of the comment, parts needed to be compiled follow
  (This is useful for commenting out large sections of a program)

   3.2. Possibilities
  

    Program lines:
    ~~~~~~~~~~~~~~
     The main difference between the BAP syntax and the syntax used in
   Assembly is that in BAP, more instructions can be placed on one line.
   Due to this, instructions which belong together can be put in one line,
   and the source program will become easier to read. The instructions are
   separated by // from eachother.

  ie.:                  MOV AX,10 // MOV BX,10
  or in BAP:            AX:=10//BX:=10

  This will be of great importance in whole line instructions ie. PUSH(),
  REP(), THENCMD, DO...

    One line written in more lines:
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Like in ANSI C, one instruction can be written in more lines. When doing
  this one has to put a \ sign in the beginning of the following lines.
  (Space and Tab can NOT be used before the \ sign!!). Some examples:

        IF (AX=7 AND BX=6)
      \ OR (AX=6 AND BX=7)
      \ THENCMD !Routine

        or:

      WRITELN'This is a text of more than one line',13,10
      \'of which this is the second line!'

  Note: a full length could be a maximum of 512! (SORMAXSIZE)


    Procedure:
    ~~~~~~~~~~

  Declaration:
       <Procedure>::
       [...]
       [ret]

  Or the common way:
       <Procedure> PROC NEAR
       [...]
       <Procedure> ENDP
  Note: the word NEAR can be left out, the compiler will write it for you.

  Note: the declaration using :: or PROC will change the value of ^, due
  to this, if this is not wanted then <Procedure>:. should be used to declare
  a procedure. This mainly concerns routines with multiple entry points.


  Calling of procedures:
        !<Procedure>
  The result of the compilations:  Call <Procedure>

   3.3. Limitations
  

   maximum length of a line:      512 characters (SORMAXSIZE)
   levels of WITH:                32
   levels of IF:                  64
   levels of UNTIL and WHILE:     32
   levels of FOR:                 20
   levels of CASE:                16
   maximum number of indirect-s:  20
   maximum length of subroutines: 32kb at full length (this may be larger, but
                                  the compiler will display a 'proc not found'
                                  warning, this might also cause problems when
                                  using LIB-s)
   maximum length of macros:      8kb
   maximum length of functions:   8kb


                            4. Compiler directives
                           

  .x86 or .80x86 (x = 0..6)
  ~~~~    ~~~~~~
     Every BAP program has to include this before the program code. The
 instruction gets compiled into the output file unchanged. Further, when
 using it for the first time, a TASM header gets generated. The content
 depends on the usage of the .EXE and .PMODE switches.

 .PMODE
 ~~~~~~
     Turns on the usage of PMODE v2.5x by TRAN, and the program will be
  compiled accordingly.

 .EXE
 ~~~~
     The output ASM file will be compilable to .EXE. For the moment, only
  the 2 segment memory model can be used, in which one segment contains
  the program code, and the other segment contains the program data and the
  stack. Warning: when compiling to .EXE different LIB-s have to be used,
  ie.: SYSEXE instead of SYSTEM1, MEMEXE instead of MEMORY.

 .ASM
 ~~~~
     This makes the compiler run in Assembly mode. In this mode BAP language
  instructions can NOT be used. This way the speed of compilations will be
  faster. Further those Assembly language instructions will be available,
  which BAP has redefined (ie. IF). This switch can also be used to turn off
  the automatic TASM-header generation.

   .ASM
   <special header>
   .386
   .BAP


 .BAP
 ~~~~
    Switches the compiler back to BAP mode.


 .STACK=nnn
 ~~~~~~~~~~
     Sets the size of the stack. The compiler always generates an array of
   word of this size at the end of the output file. This has two effects:
    - we can be sure that our program that is close to 64k does not write
      the stack over.
    - a place remains for the stack when freeing up memory (ie. !MEMINIT)
   If you do not need a stack then type: .STACK=0 or just .STACK=

 .MEGJ OFF  or  .NOMEGJ
 ~~~~~~~~~      ~~~~~~~
     Makes the compiler omit the comments in the output file (default
  value is OFF.) (megjegyzs in Hungarian means comment. :)

 .MEGJ ON  or  .OKMEGJ
 ~~~~~~~~      ~~~~~~~
     Makes the compiler inclued the remarks in the output Assembly file.


 .BAPLINE ON
 ~~~~~~~~~~~
     The BAP compiler writes a ";[filename#linenumber]" remark at the end of
  every line. This way when there is an error ( and the displaying of the
  erroneous line switch off your Assembly compiler is turned on), the
  erroneous line of your BAP code will also be displayed. This instruction
  enables this. (default values is ON.)

 .BAPLINE OFF  or  .NOBAPLINE
 ~~~~~~~~~~~~      ~~~~~~~~~~
     Turns off the BAPLINE function.


 .SZEPASM
 ~~~~~~~~
     The output file will be tabulated, forms structured paragraphs, and
  leaves an empty line where there is a new BAP line. (szp in hungarian
  means nice :)

 .ALIGN [n[,x]]
 ~~~~~~~~~~~~~~
 This is equivalent to the ALIGN found in ASM, some changes:
   - there is no limitation (in TASM only a value of 2 was allowed: ALIGN 2)
   - doesn't necessarily place NOP-s in empty spaces

 n = the unit, to whose closest multiple the code should be aligned. If we
     omit this parameter, then default value given in .ALIGN=n will be used,
     default=4
 x = the instructions used in the empty spaces (1 byte instruction!)
     default:  in the VAR indirect "db ?", elsewhere "NOP"

 ie.: .ALIGN 8,DB 99h
      .ALIGN 8
      .ALIGN=8 // .ALIGN


 .LIBMODE ON|OFF
 ~~~~~~~~~~~~~~~
    This is used to switch between INC/LIB compilation modes. It's useful
    for example if we dont know which parts of an INC will be needed, or if
    there is a part in a LIB that needs to be compiled for sure.
     Default: in INCLUDEPROC and USES [ON], elsewhere [OFF]

 .CHAR=new_instruction   ; redefines the WRITECHR instruction (max. 256 chr)
 ~~~~~~~~~~~~~~~~~~~~~

 .FC [ON|OFF]            ; FastChar mode (writes with Int 29h) (default=OFF)
 ~~~~~~~~~~~~

 .UPCASE [ON|OFF]        ; The noticing of UPCASE-d labels
  ~~~~~~~~~~~~~~~~       ; (needed because of the LIB-s and subroutine names)
                         ; (default=ON)

 .ANTIDEBUG [ON|OFF]
 ~~~~~~~~~~~~~~~~~~~
   When turned on, an INT 3 will be used instead of INT 21h, this makes
   debugging a little harder. The setting of INT-vectors is being handled
   by the INITANTIDEBUG macro in ANTIDBG.H .

 .ERRORFILE filename
 ~~~~~~~~~~~~~~~~~~~
   The writing of error messages into files! (which are displayed with
   WRITE_ERROR_BAP) The file gets generated at that time and the errors
   are displayed in the file from then on.

 .OUT text   Remarks to be displayed during compilation.
 ~~~~~~~~~
   Note: If its placed in capitals at the start of a line, then it gets
   displayed before STR0_NYIR (so the space will not be taken out), otherwise
   it gets displayed after the crop. The messages are beign displayed by
   WRITE_BAP_ERROR, due to the ;[filename#linenumber] is there at the end too.


                                  5. Basics
                                 

   5.1. Assigning values
  

     General form: "aa:=bb"
  compiled:
   - if aa=bb, then nothing (ie. MOV AX,AX makes no sense)
   - if sizeof(aa)<>sizeof(bb) then "MOVZX aa,bb" (ie. ECX:=DH)
   - if bb=0 and aa=register then "XOR aa,aa" (ie. AX:=0)
   - otherwise "MOV aa,bb"   (ie. AX:=3)

  'bb' can be in a HI:LO format too, meaning we can assign a value
  separately for the lower and higher half of bb separated by ":".
  Ie." AL:=3:8" is the same as "AL:=16*3+8".
  Note: if aa is not a register, then we the compiler doesnt know the
  size of aa, it will assume it to be a data of 16 bits!

  Assigning values to segment registers
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  When using segment registers one can assign values using the stack too,
  ie.: ES=B800h  the compiler compiles this to PUSH 0B8000H//POP ES.
  or ie.: DS=CS
  This is needed because you can not assign direct values to segment
  register like MOV ES,B8000h or MOV DS,CS .

  Assign values to pointers:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~
  register->place_it_points_to
  Ie.: DX->FILENAME (in ASM: LEA DX,FILENAME)

  If there is nothing after -> , then it will point to the next label
  created during indirect-switchingm, ie.: DX->//VAR BUFFER:DB*8192
  ( DX->BUFFER // VAR BUFFER:DB 8192 )

  This applies to OFFSET also, ie.: AX:=OFFSET // CONST SMTHNG:DD=1234


  Assigning direct values to registers:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ie.: DOS #(4c00h,BX=CX,,0,SI=7,ofs TABL)
effect:
   MOV AX,4c00h
   MOV BX,CX
   XOR DX,DX    ; OPTIMIZED FORM OF MOV DX,0
   MOV SI,7
   MOV DI,OFFSET TABL
   INT 21H
If the compiler encounters #( and ) in one line, then the values between
the parenthesis will be interpreted az direct value assignments.
1. example: #(4c00h)
 there is no register given, this way the next register in line will be
 assigned the value. (conting starts at AX)
the order of registers: (default: AX)
  EAX,EBX,ECX,EDX,ESI,EDI,EBP
  AX,BX,CX,DX,SI,DI,BP
  AL,BL,CL,DL,AH,BH,CH,DH
  ES,DS,FS,GS
  - if there is nothing between two commas (,,), then the compiler doesnt
    modify the respective register: #(8,,5) -> AX:=8,CX:=5 but BX is unchanged
  - if some register is assigned a value of 0, the compiler will optimize
    it with an XOR instrurction (this is shorter than MOV)
2. example: #(BX=7) or #(BX:=7)
  there is a register defined here, so the value will be placed in the
  defined register (MOV BX,7 will be put in the .ASM file)
  If the register is present in the above mentioned register order list,
  then the register counter will be placed to the respective register.
  ie.: #(BX=7,8) then BX=7 and CX=8, and the register counter will point
  to DX.


  mem->mem value assignment:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~
    RMOV dest,src        =>  AX:=src//dest:=AX
    RMOV dest:=src       =>  AX:=src//dest:=AX
    SMOV dest,src        =>  PUSH src//POP dest
    SMOV dest:=src       =>  PUSH src//POP dest
    RMOV(reg) dest,src   =>  reg:=src//dest:=reg
    RMOV(reg) dest:=src  =>  reg:=src//dest:=reg
  Note: you can leave the space out after the ), but the source will not
        be as readable.  ie.: RMOV(AX)LABEL1:=LABEL2

  LDD, LDDM, SDD, SDDM instructions:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 LDD[M] op1:op2,op3  ; op1:=HI(op3) and op2:=LO(op3) ; separation of a 32 bit
                                                       value
    LDD: through the stack: PUSH op3//POP op1//POP op2
    LDDM: with memory indexing: MOV op2,WPT op3 // MOV op1,WPT op3[2]
 SDD[M] op3,op1:op2   ; op3:=(op1 SHL 16)+op2        ; putting a 32 bit value
                                                       together
 Note: you can separate or put together values in memory using the stack
       (SDD,LDD)!

   5.2. Mathematical and logical operators
  

        BAP:       ASM:      function:

       ++aa      INC aa     aa=aa+1        incrementing by 1
       --aa      DEC aa     aa=aa-1        decrementing by 1
       aa+=bb    ADD aa,bb  aa=aa+bb       addition
       aa-=bb    SUB aa,bb  aa=aa-bb       subtraction
       aa&=bb    AND aa,bb  aa=aa AND bb   logical AND
       aa|=bb    OR  aa,bb  aa=aa OR bb    logical OR
       aa?=bb    CMP aa,bb  aa ? bb        comparation
       aa<>bb   XCHG aa,bb  aa<=>bb        exchanging values

       Note: <> (exchanging of values) works even when neither of the operands
       is a register, in this case it uses the stack. Ie.: DS<>ES, MEM1<>MEM2

       >>aaa     SHR aaa,1
       <<aaa     SHL aaa,1
       aaa>>n    ROR aaa,n
       aaa<<n    ROL aaa,n
       aaa>0>n   SHR aaa,n
       aaa<0<n   SHL aaa,n
       aaa>C>n   RCR aaa,n
       aaa<C<n   RCL aaa,n

     Omission of parameters:
     ~~~~~~~~~~~~~~~~~~~~~~~
 You dont need to define all of the parameters for some instructions:
 1. When using the SHR,SHL,RCR,RCL,ROR,ROL,SAR instructions, you can omit
 the ,1 .  (ie.: SHL AX = SHL AX,1 )
 2. When using the XOR,ADD,SUB,OR,TEST,AND instructions using one parameter
 assumes the other being the same (ie.: XOR AX= XOR AX,AX )

   5.3. Abbreviations
  

    SH  = SHORT
    OFS = OFFSET
    BPT = BYTE PTR
    WPT = WORD PTR
    DPT = DWORD PTR
    QPT = QWORD PTR
    TPT = TBYTE PTR

   5.4. Labels
  

 Automatic label generation:
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @:  ; this generates a label, which can be referred to with a @ or a @n
    symbol. When using @n , n refers to a relative linenumber:
      @0 = @ = the previous @:
      @1 = the next @:
      @-1 = the @ before the previous @:
    This is useful when making loops: @: loop_code // LOOP @

 MULTILABELS:
 ~~~~~~~~~~~~
   Now you besides the @: there is @A:...@Z: too, and each one has a different
   counter. This way there are 27 labels which you can manage! ;-)
   I hope this will be enough for everyone...
   ie.:
   JMP @A1 >Ŀ
   @:       <Ŀ 
   CX:=10           
>@A:      <
  !ROUTINE//JNZ @ 
LOOP @A

 Local labels: ^
 ~~~~~~~~~~~~~~~
 Assigning values:
    - WITH labelname     ;  ^ = label
    - ENDWITH            ;  ^ = label before WITH
    - name::             ;  ^ = name  (name of subroutine)
    - name PROC [NEAR]   ;  ^ = name  (name of subroutine)
    - name ENDP          ;  ^ = label before PROC
  Note: an underscore (_) is placed before the label: ^ = label + '_'
  ie.:  ROUTINE:: JCXZ ^END//...//^END: RET
  Importance: the same label can be used in many different subroutines too
              (ie.: ^END:)
  Note: WITH remembers the last 32 labels, and one label can be a maximum
        of 128 characters long.

 Redefinable label: ~
 ~~~~~~~~~~~~~~~~~~~~
  Value assignment:  ~=label
  It doesn't change until the next ~= , so it's independent from the sub-
  routines. This can be used well in LIB-s, when the same value has to be
  accessed many times in a LIB, but it shouldn't affect the other LIB-s or
  program parts.

 Start of line label: 
 ~~~~~~~~~~~~~~~~~~~~~~
  This possibility exists since version 2.3 of BAPC, which makes writing
  smaller loops easier. Because instead of writing "@: loop_code//LOOP @",
  it's enough to write "loop_code//LOOP ". The compiler generates a label
  to the start of the line, and the  found in the same line gets replaced
  by this label. The only exception to this is the PUSH() instruction, when
  this produces wrong code. Due to this, it puts the label after the PUSH().
   STOSW//LOOP //PUSH(DI) LODSB//++CX//JNZ //PUSH(SI) LODSB//STOSW//LOOP 
   <           <           <

  ie.: PUSH(BX) !ROUTINE//--BX//JNZ 
  Compiled:
    PUSH BX
      label:
        !ROUTINE
        --BX
      JNZ label
    POP BX

 Special labels:
 ~~~~~~~~~~~~~~~
   ENDIF as a label: jumps to the next ENDIF
   RET, RETC, RETS : jump to the previous (or there is no such instruction
                     before, then the next) instruction like these.

   5.5. Variables
  

  Variables defined in clear ASM language should be placed separate from the
  code in one place. Something like this:
      VARIABLE1 DW ?
      VARIABLE2 DD ?
      VARIABLE3 DD ?
      ARRAY DB 256 DUP (?)
      ...

  BAP makes it possible to put variables between our code.
  The declaration of the variables is similar to that of PASCAL.
  The example above in BAP form:
       VAR VARIABLE1:DW
       VAR VARIABLE2,VARIABLE3:DD
       VAR ARARY:DB*256
  VAR insrtuctions can be written anywhere. It's not necassary to place them
  after the code in one pile. This makes it possible to place the variables
  next to the initialization: VAR VARIABLE:DW // VARIABLE:=start_value
  Further, if the start_value is in a register, then the type definition can
  be omitted and VAR TEMP_AX=AX is enough, this is the same as
  VAR TEMP_AX:DW//TEMP_AX:=AX in practice.
  If a variable is a pointer type, then the starting value can be given like:
  VAR POINTER->PLACE_IT_POINTS_TO
  This is the same as VAR POINTER:DW//MOV POINTER,OFFSET PLACE_IT_POINTS_TO...
  Note: an array can be assigned a starting value, but this will be placed in
  the first record of the array, and the whole array will NOT be filled with
  this value.

  Note: Variables get placed in the VAR indirect.
  Except if .VARIND=something has been used to redefine the name of the indirect.

   5.6. Constants
  

  In pure ASM we declared the constants separated from the code, in one place,
  something like this:
     MYCONSTANT1 DW 1234
     MYCONSTANT2 DB 'Hello world!'
  BAP makes it possible to write the constants between the code.
  In BAP this looks like this:
     CONST MYCONSTANT1:DW=1234
     CONST MYCONSTANT2='Hello world!'
  (So when using strings, you don't have to specify the type)

  Note: Constants get placed in the indirect called CONST.

   5.7. Strings
  

  Strings can be defined in the parameters of instructions too, they don't
  have to be named separately.
  ie.: WRITE 'Hello world'
  In ASM this would look like:
    ; code:
    LEA DX,label
    MOV AH,9
    INT 21h
    ...
    ; constants:
    label DB 'Hello world',36

    We can use the string definition in special cases too, with the help
    of STROFS:
      DX:=STROFS'Hello world',36
    or even simpler:
      DX->'Hello world',36

    Notes:
    - OFSSTR can be used instead of STROFS
    - -> can only be used if it is followd by a ' , while you can use STROFS
      followed by numbers: SI:=STROFS 13,10,'Hello',13,10,36
    - STRINGS defined like this get place in the TEXT indirect.

   5.8. Segment-prefixes
  

    CS:,DS:,ES:,FS:,GS:,SS: get compiled 'DB nn', this way they can be used
    before any instruction.
    ie.: ES:LODSB (in ASM this would be: LODS BYTE PTR [ES:SI])
    Warning! ES: segment can not be redefined! (STOSx,SCASx)

   5.9. Code-repetition
  

    The format is: REP(count) thing_to_repeat
    "thing_to_repeat" gets compiled "count" times after eachother.
    ie.: REP(16) STOSB//AL+=3
    "count" has to be a decimal or hexadecimal number, it can not be a label
    or anything else.


                               6. Instructions
                              

   6.1. Conditional instructions (IF, CASE)
  

    Rules:
    ~~~~~~
    - A condition instrucion can be followed by an S character. This sets
       the signed mode, which is needed for the descrimination between
       WORD and INTEGER types.
       The N character is the NOT function for a whole condition:
        ie.: IF NOT(condition) = IFN condition
    - Multiple parenthesis can be used
    - Logical operators that can be used: NOT, AND and OR
    - Conditions:
         a<b, a>b, a=b, a==b, a!=b, a<=b, a=<b, a>=b, a=>b, a<>b, ab, ab
    - Special conditions:
       - KEYPRESSED and KEYPRESSEDP: is the same as in pascal, the P at the
         end means, that for the time of the check it saves the used registers
         It's value is TRUE, is there is something in the keyboard buffer.
         ie.: REPEAT UNTIL KEYPRESSED
       - FLAG-s: the flags of the CPU can be used like this: "FLAG x" or "FLAGx"
         ie.: IF FLAG C OR AX<CX THEN ^WRITE_ERROR
    - IN[] function: ie. IF a IN[b,c,d,e..f,g..,..h] THEN ...
    - NIN[] = NOT IN[]
    - Comparations that contain more elements don't need to have the elements
      after the 2nd element completely written:
        IF LONGLABELNAME>5 AND <17 THEN...
      So if you do not define the parameter for the second comparation, then
      the element that was last used gets used for the comparation.
      WARNING! This does NOT work when using macros!
      (ie. IF MACRONAME>5 AND <17 THEN...)

    Note.: Naturally, both elements (a and b) of a comparation can not be
    memory-variables, because CMP mem1,mem2 is not allowed!!

    THEN label -structure:
    ~~~~~~~~~~~~~~~~~~~~~
       It jumps to the label if the condition is true:
       IF condition THEN label

    THEN/ELSE/ENDIF -structure:
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       - ELSE is not mandatory
       - THEN is not mandatory (IF condition  is enough)
       - The maximum nested IF statements is 64.
       IF <condition> THEN
          [instructions...]
          [...]
       ELSE
          [instructions...]
       ENDIF

    THENCMD-structure:
    ~~~~~~~~~~~~~~~~~~
       IF <condition> THENCMD <instructions...>
       this can be used when we have short instructions, ie:
       IF AX>CX THENCMD AX:=CX
       note: when using THENCMD the instructions until the end of the line
             (not until //) get compiled to be executed when the command is
             true!
       In practice IF <condition> THENCMD <something> gets compiled like this:
         IF <felttel> THEN
           <valami>
         ENDIF
       Because of this the use of ELSE after THENCMD is allowed!
       ie: IF AX=5 THENCMD WRITELN'AX=5"//ELSE WRITELN'AX<>5'

    CASE instruction:
    ~~~~~~~~~~~~~~~~~
  ie.:  CASE AL OF
        1,3,^XYZ: NOP           ; THENCMD-type
        128:                    ; THEN..ENDIF type
          INSTR1//INSTR2        ; Any number of line can be written
          INSTR3//END         ; the end of the line is marked by "END"
        'A'..'Z':>ROUTINE       ; jump to ROUTINE
        ELSE
          This the place for ELSE  ; if none of the above is true...
        ENDCASE
  Note: between CASE and ENDCASE (except if there is a part closed with END),
  things before the first colon are used as the condition, ie.:
  "abc: instructions" is the same as "IF case_var IN[abc] THENCMD instructions"
  (where case_var is the thing between CASE and OF). So the things written
  for IN[...] are valid for things before the colon! A "abc:>label" is going
  to be "IF case_var IN[abc] THEN label"!

       6.2. Loop construction
      

      Front testing loops:
      ~~~~~~~~~~~~~~~~~~~~~~

      The cycle gets repeated while the condition is true.
      Note: things stated in part 6.1. apply to the <condition> !

      WHILE/ENDWHILE structure:
         WHILE <condition>
           <instructions...>
         ENDWHILE

         WHILE/DO structure:
      WHILE <condition> DO <instructions...>
      or
      WHILE <condition> DOCMD <instructions...>


     Back testing loops:
     ~~~~~~~~~~~~~~~~~~~
   REPEAT/UNTIL structure:
      REPEAT
         <instructions...>
      UNTIL condition
   This loops get executed at least once, and until the condition turns
   true. (If the condition is true, then the loop stops)


     Incremental cycles:
     ~~~~~~~~~~~~~~~~~~~
   1. Simple LOOP cycles:
   ~~~~~~~~~~~~~~~~~~~~~~
     LOOP(size) something//something//...
     LOOPF(size) something//something//...

   LOOPF checks with a JCXZ if it can run the cycle.
   'size' goes into CX and will be the number of repetitions.

   2. FOR instructions:
   ~~~~~~~~~~~~~~~~~~~~
   It has 2 main types, CMP type and LOOP type. Both start with a FOR
   and the end of the cycle core is marked with the NEXT instruction!

   1. FOR[P][F][E][An] a[:]=b [DOWN]TO c [STEP x] [DO cmd1//cmd2...]
      F=forward (front testing)
      S=signed  (the numbers are signed)
      E=EQU (if it should reach 'a' or 'b')
      P=push a  (stores the value in the stack for the time of the cycle core)
      An = .ALIGN n  (should only be used when optimizing for speed)

      - TO = counts upforwards, DOWNTO counts downwards.
      - If there is a STEP x defined, then the count will go by steps of x
      - if there is a DO defined, then the part after the DO will be the cycle
        core and there is no need for NEXT at the end.

   2. FOR[P]L[P][An][F][S][(size)] a:=b [TO|DOWNTO|STEP x] [DO cmd1//cmd2...]
      P=push a   (before the L)
      L=loop     (the next parameter)
      P=push CX  (after the L)
      An = .ALIGN n
      F=forward (JCXZ)
      S=short  (it uses a LOOP instruction instead of --CX//JNZ , for a cycle
                core that does not exceed 128 bytes in length)

      Note: the order of the options does not matter, except for the order
            of P and L.

   Ie.
   Incorrect:
     FOR a:=b
     FORL a

   Correct:
     FORPL a
       @: PUSH a//...//POP a//loop @
     FORL a:=5
       MOV a,5//@:...//LOOP @
     FORL a TO
       @: ...//++a//LOOP @

   6.3. Complex stack handling
  

  1. PUSH r1,r2,r3... s POP r1,r2,r3...
     (the order does not have to be reversed)

  2. Special values:
     ALL = PUSHA         (ie: PUSH ALL,FL,CIM1)
     AD  = PUSHAD
     FL  = PUSHF
     FD  = PUSHFD
     AS  = PUSH ALL,DS,ES

  3. instructions of a whole line: PUSH(r1,r2,...) xxxx
     this saves r1,r2,... in the stack for the time of the xxxx instructions
     ( PUSH r1,r2,...//xxxx//POP r1,r2,...)

  4. If there just a 'PUSH' (nothing following it), then the parameter of
     of the last PUSH instruction gets stored in the stack again, so
     ie: PUSH AX//PUSH// stores AX twice in the stack!

     If there just a 'POP' (nothing following it), then the parameter of
     of the last PUSH instruction gets saved from the stack, so
     ie: PUSH AX//POP// stores and restores AX from the stack!

     PUSH and POP 'remembers' 32 levels and a can save a line of maximum
     63 characters.

     ie.:

       PUSH AX//PUSH//PUSH ^LABEL   =>  PUSH AX//PUSH AX//PUSH ^LABEL
       then:
       POP//POP//POP   =>  POP ^LABEL//POP AX//POP AX

   6.4. Keyboard and screen handling
  

     Keyboard handling:   ; output: AH=scan code AL=ascii code
     ~~~~~~~~~~~~~~~~~~
  WAITKEY       ; XOR AX//INT 16h     waits for a keypress
  READKEY       ; AH:=1//INT 16h      read the status of the buffer
  READSHIFT     ; AH:=2//INT 16h      state the SHIFT/CTRL/ALT keys
  GETKEYn       ; AH:=n//INT 16h      the previous 3 inst. in another form

     Positioning on the screen:
     ~~~~~~~~~~~~~~~~~~~~~~~~~~
  GOTOXY x,y         ; DL:=x//DH:=y//GOTOXY
  GOTOXY y:x         ; DX:=x+y*256//GOTOXY
  GOTOXY value       ; DX:=value//GOTOXY
  GOTOXY
  WHEREXY

     Writing to the screen:
     ~~~~~~~~~~~~~~~~~~~~~~
  WRITE'string'      ; writing a string
  WRITELN'string'    ; -//- and a linefeed + carriege return
  WRITELN            ; just a linefeed
  WRITESTR label     ; = DX->label//WRITESTR
  WRITESTR           ; = DOS 9
  WRITECHR c1,c2,,c3 ; write characters, if there is nothing between two
                     ; commas, then the last character gets repeated

   Note: the character writing instructions are redefinable:
     .FC option:   FastChar, then the writing will be done by INT 29h
     .CHARCMD=xxx: User defined writing routine (ie. AH:=15//STOSW)

   6.5. File instructions
  

    General format: FILExxx [VAR] [handle]
    'handle' is the name of the file-variable, VAR can signal, if the
    compiler has the define the variable not us. Instructions:

    Open:
    ~~~~~
     FILEOPEN   =  DOS 3D00h[//handle:=AX]    open file to read
     FILEOPENR  =  DOS 3D00h[//handle:=AX]    open file to read
     FILEOPENW  =  DOS 3D01h[//handle:=AX]    open file to write
     FILEOPENRW =  DOS 3D02h[//handle:=AX]    open file to read and write
     FILEOPENP  =  DOS 3D10h[//handle:=AX]    protected file open to read
     FILECREATE =  CX:=20h//DOS 3Ch[//handle:=AX]  create a file

   Handling:
   ~~~~~~~~~
     FILEREAD   =  [BX:=handle//] DOS 3Fh     read a block
     FILEWRITE  =  [BX:=handle//] DOS 40h     write a block
     FILECLOSE  =  [BX:=handle//] DOS 3Eh     close a file
     FILECALL   =  [BX:=handle//] DOS         general file operation call

   Positioning:
   ~~~~~~~~~~~~
     FILEPOS     =  [BX:=handle//] DOS 4200h  from the start of the file
     FILEPOS0    =  [BX:=handle//] DOS 4200h  from the start of the file
     FILEPOSREL  =  [BX:=handle//] DOS 4201h  relative
     FILEPOS1    =  [BX:=handle//] DOS 4201h  relative
     FILEPOSBACK =  [BX:=handle//] DOS 4202h  from the end of the file
     FILEPOS2    =  [BX:=handle//] DOS 4202h  from the end of the file

   Special positioning:
   ~~~~~~~~~~~~~~~~~~~~
     FILEHOME    =  [BX:=handle//] XOR CX//XOR DX//DOS 4200h  jumps to the start of the file
     FILEAPPEND  =  [BX:=handle//] XOR CX//XOR DX//DOS 4202h  jumps to the end of the file
     FILEWHATSIZE=  [BX:=handle//] XOR CX//XOR DX//DOS 4202h  DX:AX=length of the file
     FILEGETPOS  =  [BX:=handle//] XOR CX//XOR DX//DOS 4201h  DX:AX=file position

   Miscellaneous:
   ~~~~~~~~~~~~~~
     FILEDELETE  = Deletes the file
     FILERENAME  = Renames the file
     MKDIR       = Creates a directory
     CHDIR       = Changes the current directory
     RMDIR       = Removes a directory entry

  Exampe for a short file dumper:
  .386
  DX->'filename',0
  FILEOPEN VAR NUM               ; opening of the file, the name is in DX
  ;
  DX->//VAR BUFFER:DB*8192
  CX:=8192
  FILEREAD                        ; Reading, place in DX, length in CX
  ;
  SI:=DX
  LOOP(AX) WRITECHR LODSB         ; Writing to the screen
  ;
  FILECLOSE                       ; Close the file
  EXIT

   6.6. Miscellaneous instructions
  

   - UPCASE reg  : reg:=UPCASE(reg), a makes the character uppercase.

   - DECODE reg  : reg:=decode(reg), decoding with the codes specified in
                   .CODE=x,y .

   - INTCALL xx  : callsn interrupt,  PUSHF//CALL DPT xx

   - DOS         : INT 21h   (calling of DOS-functions)
     DOS xx      : AH:=xx//INT 21h
     DOS xxxx    : AX:=xxxx//INT 21h

   - MOUSE xxxx  : AX:=xxxx//INT 33h
     EGERBE      : turns the mouse cursor on
     EGERKI      : turns the mouse cursor off
     GETMOUSE  =>  BX=buttons, CX=x  DX=y  reads the coordinates of the mouse
     SETMOUSE  <=  CX=x, DX=y              set the coordintaes of the mouse
     RESETMOUSE or INITMOUSE  => AX=0 if error, AX=255 if ok, BX=num. of buttons

   - BIOS,
     BIOS xxxx   : VIDEO-BIOS functions, AX:=xxxx//INT 10h

   - DOSEXIT,      Exits the program and returns to DOS...
     DOSEXIT xx  : AX:=4C00h+xx//INT 21h  (xx=return code)

   - EXIT,
     EXIT xx     : by default, it's the same as DOSEXIT, but this one can be
                   redefined with the .EXIT=xxx instruction!!

   - OUTAL and OUTAX  : OUT DX,AL and OUT DX,AX
   - OUTB p1,p2,...  : AL:=p1//OUTAL//AL:=p2//OUTAL...
                       the giving of parameters is the same as with WRITECHR

   - RETC        = CLC//RET   ; Note: these can be referred to as addresses
   - RETS        = STC//RET

   - ALDIV xx -> DB 0D4h,XX  [This non documented instructions divides the
                 value in AL with xx, and the remainder goes into AL, the
                 result goes into AH
                      >> SPEC. CASE: ALDIV 10  DB D4,0A  AMM <<

   6.7. String-like operations
  

   STOSxy:    general form: STOSxy data1,data2...
   ~~~~~~~
   STOSxy (if there is no y, then y=x) gets interpreted the following way:
     it stores the size of data specified in x
     and loads the register with the size in y (B->AL, W->AX, D->EAX)
   This way you can write: STOSBW,STOSWB,STOSDD, or any other combination)
   ie:  STOSWB 'H','W'   =>   AL:='H'//STOSW//AL:='W'//STOSW
   ie:  STOSB 'H','W'    =>   AL:='H'//STOSB//AL:='W'//STOSB

   OUTB and OUTW, work the same way as STOSx:
   ~~~~~~~~~~~~~
     OUTB x1,x2,...  ->  MOV AL,x1//OUT DX,AL//MOV AL,x2//OUT DX,AL...
     OUTW x1,x2,...  ->  MOV AX,x1//OUT DX,AX//MOV AX,x2//OUT DX,AX...

   REP*n:
   ~~~~~~
   you can specify the number of repitions directly by REP, ie:
   REP*1000 STOSD 0
   compiled:
     CX:=1000
     EAX:=0
     REP STOSD


                            7. Modular programming
                           

   7.1. INDIRECT-s
  

 This means, that we can edit more than one part at a time of our source.
 So: if we put an instruction, or a group of instructions between { }-s,
 then, the part between the { } gets placed in a temporary file, who's name
 should be written directly after the { . In the future these files can be
 fitted in the code by referring to them with the .INDIRECT name1,name2, ...
 instruction, or can be fitted in with and .INDIRECTCALL in the appropiate
 place.

  ie:
  .386
  WRITELN'FIRST'
  {XYZ WRITELN'THIRD' }
  WRITELN'SECOND'
  .INDIRECT XYZ
  WRITELN'FOURTH'
  EXIT

  Typical area of use:
   - defining of variable, and constants between the code
   - moving code parts
   - making initialization routines

  Special INDIRECTS also exist:
      VAR   this is where the variables get placed (see at the VAR command)
      CONST this is where the constants get placed (see at the CONTS command)
      TEXT  this is where the texts get placed (see WRITE... and STROFS)

  These can be written to directly:
    CONST: DB 'this get placed in CONST!'
  a practical example:
    VAR: .ALIGN 16

  It's important to note, that the compiler puts all of the indirects that
  havent been fitted, at the end of the program, the order is the same as the
  order of the definitions, except that the VAR indirect always gets placed
  last.

   7.2. The usage of routine packages (LIB-s)
  

 You can use routine libraries with the help of the BAP compiler, of which
 only the used routines get compiled.

 These routine packages are generally in files of .LIB extension (their
 PMODE versions get a .PML extension), and are in one (or more) separate
 directories, which is (or are) defined by the LIBDIR= variable in the
 BASSPASC.CFG file. There is a basic LIB-kit for BAP, which contains all
 the more important routines, starting from the string operations, all
 the way to routines to help program the graphic and sound cards.
 (see chapter 9.)

 Generally there is a file of .H extension, that belongs to the newer
 (made relative to the v2.0+ of BAP) LIB-s, which contains the functions,
 macros and structures. These can be included with the INCLUDE command.


 The commands to use these are the following:

 CALL procedurename  or  !procedurename
 ~~~~~~~~~~~~~~~~~~      ~~~~~~~~~~~~~~
 Calling of a subroutine, if it is not in the source of the program. This
 routines are looked for in the LIB-s defined by USES.

 .COMPROC procedurename
 ~~~~~~~~~~~~~~~~~~~~~~
 This asks for the compilation of the routine, it's like a CALL, but a CALL
 instructions does not get compiled.
 This is generally used for interrupt handling routines, which are not called
 with a CALL instruction.

 .DEFPROC procedurename
 ~~~~~~~~~~~~~~~~~~~~~~
 Tells the compiler that 'procedurename' is the name of a procedure.
 This is needed, if for example 'procedurename' gets called as a procedure,
 but is defined to be something else. (ie. a label or a variable)
 It's usage is not mandatory, but advisable if we dont want any warning
 during compilation.
 ie:
   CALL ROUTINE_PTR
   .DEFPROC ROUTINE_PTR
   VAR ROUTINE_PTR:DW

 USES lib1,lib2...
 ~~~~~~~~~~~~~~~~~
 It's advisable to use this command at the start of the program. It's affect
 is that, the routines needed will be copied in at the .INDIRECTCALL command,
 or at the end of the program.

 INCLUDEPROC lib1,lib2...
 ~~~~~~~~~~~~~~~~~~~~~~~~
 The needed procedures will be we copied in at the place of this command.

   7.3. Compiling of INCLUDE files
  

    INCLUDE file.inc [,file2,file3...]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Inserts a BAP language file or files.
  Note: the header (.H extension) files also get placed in with this, but
  at the very start of the program)

    INCLUDEDx file.dat (x can be B=byte, W=word, D=dword, or Q=qword)
    ~~~~~~~~~~~~~~~~~~
  Inserts a binary data file in the form of DB/DW/DD/DQ.

  If you dont need the whole file, then you can specify a range:
     INCLUDEDB filename[SC,EC]      (SC=start position, EC=end pos. or +size)
     if the specified number is negative, then it means that it's specified
     relative to the end of the file.
     if EC is positive, then it gets add to SC, so we defined a length.
   This works with all of the INCLUDEDx too of course...
   IF ec>filesize, then the compiler displays a !!Warning!! too.
   Note: EC refers to the last byte (not the byte after the last byte)!
         But for example with INCLUDEDW, it doesnt refer to the last word,
         but to the last byte...!!


    CODEINCLUDEDx file.dat
    ~~~~~~~~~~~~~~~~~~~~~~
  The data file gets fitted, encoded. (see also DECODE reg and .CODE a,b)

    ASMINCLUDE file.asm
    ~~~~~~~~~~~~~~~~~~~
  Inserts an Assembly language file, and does not compile it, this way the
  compilation will be faster.

   7.4. BAP Object (BPO)
  

  A .BPO file can be made from a .INC file which can be compiled faster,
  and does the same thing, with the /BPO switch of the compiler.
  So it's useful to compile (once) those .INC files which are not altered
  frequently into .BPO files and to change the "INCLUDE file.INC" to
  "INCLUDE file.BPO".
  Note: If you modify the original .INC file, then you have to compile it
  to .BPO format yourself! (The compiler notices the change and gives you
  a warning!)

  This is useful mostly if you are compiling on a slow machine, or the whole
  source code of a program is long, otherwise the speed increase is not
  significant.

  Note: When compiling to .BPO you have to make sure, that the .H files are
  INCLUDE-ed in the .BPO file that you compile, otherwise the macros do not
  get compiled. You shouldnt compile OOP programs to .BPO, because the
  macro changes will not be inherited.

  The structure of the .BPO file:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  .FILEINFO filename,size,datetime  ; this is how the compiler knows that...
  .ASM                              ; ...it has been modified
  ...    ;A program (.INC) compiled to ASM
  .BAP
  USES xxxx
  .DEFPROC xxx  ;; So the CALL-s will be ok (not to get a  Proc Not Found)
  .COMPPROC xxx ;; So the .LIB-s will be ok (to compile what we need)
  {indirect1_name  ; The contents of the .IND file-s
  .ASM
  ...  ; the contents of the .IND file
  .BAP
  }
  {indirect2_name
  ...
  }
  ...

   7.5. The usage of PACKAGE-s
  

  IMPORTANT! This function is still under testing, and does not always work
  right. So be careful when using it.
  Note: it's practical to compile in 2 runs when using PACKAGE-s, there is a
  .BAT file in the examples.


  I adopted the PACKAGE command from PERL (UNIX script).
  The main point: areas can be marked, and variables defined within
  these areas can not be seen from the outside! This makes it easier to
  link together programs, that were written separately. The names of variables
  will not get mixed up. This is true for labels also.
  Usage:
  .PACKAGE name  ; opens the scope called 'name'
  .PACKAGE OFF   ; closes the scope
  .PACKAGE       ; switches to the last used scope
  .LABEL label   ; defining of a label, so we can use it before we defined
                 ; it (!! there are still problems with this...)

The point: if you want to include a program part that you have written at
another time, then you generally have many labels with the same name...
A good solution to this is to put a .PACKAGE something before the INCLUDE
and then this will be independent from the others, so it doesnt matter if
there are labels of the same name, the don't interfere with each other.

Example:
  VAR I,J:DW
  I:=17
  J:=99
  IF AX=7 THEN LABEL  ; So which LABEL does this jump to? The second one of course
  .PACKAGE SOMETHING
  VAR I:DW      ; This I variable is completely independent from the previous one
  LABEL:        ; You can use a label too...
  I:=22         ; Warning! VAR has to be before the first reference in the
  J:=23         ;   scope
  .PACKAGE OFF  ; End of scope.
  LABEL:        ; Haven't we used this before!? Of course, but in another scope.
  BX:=I         ; The value of BX will be 17. (not 22, because that's in another scope)
  CX:=J         ; The value of CX will be 23, because it's not redefined in the scope
                ; so the second assiging of the value also refered to the original J

Another example:
  VAR I:DW  ; Make this variable A
  .PACKAGE SOMETHING
  I:=17     ; A:=17
  VAR I:DW  ; This variable B
  I:=22     ; B:=22
  ; OK? So until a variable is defined again, the other variable is seen.
  ; So I:=17 refers to the I the was defined first, and not the on inside
  ; the package. This is what LABEL: is for
  ; If we write .LABEL I after .PACKAGE SOMETHING then both will refer to B.

Note: The evaluation inside a scope is a little slower then normal, but not
by much. Ie. in 600 scopes were just 3x as slow as the defined labels, and
this means, that we have to check 600 words for every word. If you have lots
of scopes, but few variables in each one, then it will be fast.


                           8. Macros and functions
                          

  At the start, macros and functions were 2 different things in BAPC, but
  now they bound together!

  Definition:
    #macroname(input_parameters):output_param=instructions

  Usage:
    macroname(input_parameters)
  or
    macroname input_parameters

  macroname  = name of macro, one word, like it was a label

  input_parameters = register or a label, the used input parameters
                     will be copied here!
                       ie.:        #MACRO(CX,EAX,ADDRESS)=!ROUTINE
                       calling:    MACRO(BH,DH,12)
                       compiled:   CX:=BX//EAX:=DH//ADDRESS:=12//!ROUTINE

  output_parameter = if the macro is a function then this will be it's output
                     parameter
                         ie.:        #MACRO(DX):BX=!ROUTINE
                         calling:    ADDRESS:=MACRO(12)
                         compiled:   DX:=12//!ROUTINE//ADDRESS:=BX
                     Note: %n can be used here too!

  instructions = this is where the code that will be executed comes, that goes
                 between the output and the input parameters. This can be left
                 out, but you still have to include the = sign!
                 ( ie.: #MACRO(AX):AX= )

                 The input parameters can be reached with the %n, just like in
                 batch languages, ie: #MACRO=BX:=%1 is the same as #MACRO(BX)=
                 If you refer to something with %n that has not been given when
                 calling the macro, then you will get an error message. Because
                 of this, the parameters that were not mandatory have to be
                 marked with %?n.
                 Ie: #REP32=DB 67H//REP %?1
                   This can be called two ways:
                      REP32   or:    REP32 LODSB
                   neither of these causes an error when compiling!

 If there are output parameters given when the macro is defined, then the
 macros can be used like functions:
 ie.: Defining:   #ALLOCMEM(BX):AX=DOS 48h
      Calling:    MEMSG:=ALLOCMEM(1000h)

  Special output parameters can be given, ie:
  def:    #NUM:(%1 IN ['0'..'9'])=
  call:  IF NUM(AL) AND NUM(AH) THENCMD WRITELN'This is a number!!!'

  The output parameter can change, according to the input parameter:
  ie.:  #MEM_ADD:%3=%3:=%1//%3+=%2
        ADDRESS3:=MEM_ADD(ADDRESS1,ADDRESS2,AX)
        (the third parameter here referes to the register to be used)

  And the last one is a strange, but useful macro:
    #AX(AX):AX=
  Usage:
    because IF MEM1=MEM2 THEN... can not be compiled (there is no CMP mem,mem
    instruction), you have to write IF AX(MEM1)=MEM2 THEN...

  With these macros, it's possible to write object oriented programs in BAP.
  Furthermore, BAP instructions can be redefined, ie. after #MOV=MOV %2,%1
  the compile "goes crazy", because it switches the parameters of the MOV
  instructions! =)
  A good practical example of this is when the redefining the WAITKEY instr.
  when you want to use a screensaver or a keybar...

    The "only-function"-s
    ~~~~~~~~~~~~~~~~~~~~~
  As I have stated, in the beginning, macros and functions were 2 different
  things, some things - mainly due to compatibility reasons - have stayed:

  SETOUT routinename=outputparam   ; the defining of outgoing parameters
  Ie: after SETOUT !ROUTINE2=CX   AX:=!ROUTINE2 compiled: is !ROUTINE//AX:=CX

  Note: if we refer to a routine like a function, whos parameter has not
  been specified with SETOUT, then by default the parameter is going to be AX.
  ie.: DX=!ROUTINE  compiled:  !ROUTINE//DX:=AX (only if there was no SETOUT!)


     Special functions:
     ~~~~~~~~~~~~~~~~~~
  LODSx    ie.: WRITECHR LODSB
           compiled:  LODSB//WRITECHR AL
           (Specified with macros, this would be: #LODSB:AL=LODSB)

  ++,--,>>,<<
            ie:  CX:=++AX     compiled:  ++AX//CX:=AX
            ie:  CX:=--<<AX   compiled:  SHL AX//--AX//CX:=AX


                  9. The description of the routine packages
                 

  These could be found in the LIB-DOC directory in a file called libname.TXT,
  if not, then a documentation of that LIB has not been completed. :(
  In this case, i recommend the reading of the .H and .LIB files, generally
  you can understand everything from the comments. The reviewing of the
  sample programs is also very helpful...


                            10. Free registration
                           

  Because BAP is CardWare, the registration is totally free!!!

  The registration:
  - read and fill out REGISTER.TXT !!!
  - Get in contact with us, and send it to us, in the reply, you will get a
    BASSPASC.REG file, which you will have to copy in your compiler directory

    - send it in an E-mail, this would be the easiest solution.

      my address:  Gereffy rpd
                     (GyikSoft)
                garpad@sparta.banki.hu

         in the SUBJECT write: BASSPASC REGISTRATION

    - or send via snail mail, but DO send a disk, and a self addressed,
      stamped envelope too! (if you're not Hungarian, then it's not the
                        recommended way, but just do it, if you think!)
      (if you've written a good program too, then send it along! :-)
      the address:    Brthzi Andrs
                         (Boogie)
                      1043, Budapest
                       Nyr utca 53.

    I'm sure you are thinking: if it's FREE, then what's the use of it?
    The answer is simple: because BAssPasC is a new initiative, we would
    like to keep track of how well it spreads, how many people use it,
    is it worth it to make new versions, or are we the only ones using it?
    So if you like it, and would like new versions, then write to us, and
    register your copy!

  Why is it good to register?
    - the compiler wont countdown (this is already worth it ;-)
    - you will constantly get the info of new versions (if you want to)
    - if you are stuck, or dont understand something, then you can write
      us in E-mail and we will help you (if we can)

  THE END 

