home *** CD-ROM | disk | FTP | other *** search
-
-
- Description of IO.ASM
-
- IO.ASM is an attempt to provide a standard i/o interface for
- assembler applications. Ways to manipulate strings, read from the
- keyboard, display to the screen, and perform file i/o are defined.
- All of the routines have the following characteristics:
-
- 1. All registers are preserved. (1)
- 2. No segment register values are assumed.
- 3. Parameters are passed on the stack. (1)
-
- (1) A few routines pass parameters in the registers.
-
- The above characteristics make the routines very flexible. For
- instance, when calling them, the programmer does not have to worry
- about setting up the segment registers or destroying uninvolved
- registers.
-
- The flags are not necessarily preserved (except for the special
- system flags, i.e. interrupt enable and single step interrupt).
- The only significant flag that might be modified is the direction
- flag (DF), which is sometimes cleared.
-
- The routines, as stated above, receive their parameters on the
- stack. This means that the parameters must be pushed on the stack
- in the proper order before calling the routine. Parameters are
- also returned on the stack. The Intel 8086 user's manual does not
- recommended returning parameters on the stack, but it works too
- conveniently to ignore. Note that if parameters are returned on
- the stack, they will have to be removed before any data below them
- is accessible. Because the stack is used so extensively, the
- program using these routines should have a good sized stack
- available, say no less than 200 bytes for IO.ASM plus any extra
- needed by your program.
-
- Two different types of strings are defined by IO.ASM. The first
- is a sequence of characters preceded by a length byte. The
- advantages of this kind of string are that it can contain any
- characters and be manipulated quickly. The disadvantages are that
- it is limited to a length of 255 characters and that it is more
- trouble to declare (since you must count its characters and
- manually specify its length). The other string type is a sequence
- of characters terminated by a byte 00. This kind of string may be
- any length and is easier to declare, but it can't contain byte
- 00's and is more trouble to manipulate. The second type of string
- is only used by routines that open, create, or delete files.
-
-
- The following is a program fragment using the IO.ASM routines to
- combine two strings and then display the result:
-
- ;put the location of DATA on the stack (destination)
- Mov Ax, Offset Data ;get offset of storage
- Push Ax ;put offset on stack
- Push Cs ;put segment on stack
- ;
- ;put first part of message on stack (source)
- Mov Ax, Offset Mess1 ;get string offset
- Push Ax ;put offset on stack
- Push Cs ;put segment on stack
- ;
- ;copy the first part of the messge to DATA, note the
- ;destination (location of DATA) is returned on the stack
- Call Copy_Str_P ;copy string to work area
- ;
- ;put second part of message on stack
- Mov Ax, Offset Mess2 ;get string offset
- Push Ax ;put offset on stack
- Push Cs ;put segment on stack
- ;
- ;append second part of the messge to the first part,
- ;the destination is returned on the stack
- Call Append_Str_P ;append string
- ;
- ;now display the string in DATA to the screen, the display
- ;routine does not return the string location, thus the stack
- ;is back to its original state
- Call Display_Str_P ;show string
-
-
- Mess1 Db 12,'Squares are ' ;first part of message
- Mess2 Db 11,'not round. ' ;second part of message
- Data Ds 256 ;work area
-
- Include 'Io.Asm' ;include procedure definitions
-
-
- Description of IO.MAC
-
- IO.MAC is set of macro definitions designed to make the use of
- IO.ASM easier. Generally speaking, there is a macro for each
- routine or set of routines in IO.ASM.
-
- The one restriction that exists with IO.MAC is that the BP
- register is not preserved and cannot be used to pass parameters,
- as it is sometimes used to set up the parameters that are passed
- to IO.ASM.
-
- With the macros defined in IO.MAC, the example for IO.ASM above
- could be more easily written:
-
- Copy Data,,Mess1 ;copy first part of message to DATA
- Append Data,,Mess2 ;copy second part of message to DATA
- Display Data ;display message
-
- Mess1 Db 12,'Squares are ' ;first part of message
- Mess2 Db 11,'not round. ' ;second part of message
- Data Ds 256 ;work area
-
- Include 'Io.Asm' ;include the procedures
- Include 'Io.Mac' ;include the macros
-
-
- Description of Runtime Library Implementation
-
- WASM does not produce true object files. To work around this
- drawback, a software implementation for a runtime library is
- provided. The advantages of a runtime library are that a single
- library can be used by many different programs (thus reducing
- redundant code), and the library source code need not be
- reassembled each time the program is reassembled (thus saving
- time). The only disadvantage to a runtime library is that the
- application must be able to find and load the library during
- execution.
-
- The goal of this runtime library implementation is to be able to
- do is something like CALL SUBRT, where SUBRT is a near procedure
- in a separately assembled file. The interface should be
- transparent, i.e. we want be able to pass parameters on the stack
- or in registers to and from the routine. This particular
- implementation does not allow the flags to be passed to routines,
- though it does allow flags to be returned. Also, there is no
- convenient way to directly access global data across the
- interface, which doesn't really matter too much, since data is
- normally passed in registers or on the stack.
-
- Three major components are needed to implement this runtime
- library: a routine redirection table, the dispatch code, and the
- library code. The redirection table is made up of substitution
- procedure headings, which make the program think that the
- procedures have been declared within it. The dispatch code is the
- program half of the interface, and the library code is the library
- half of the interface. The basic sequence of events is as
- follows: the redirection table accepts the initial procedural call
- and sets a routine index and library information, then passes
- control to the dispatcher code; the dispatcher code loads the
- library (if it hasn't already been loaded) and passes control and
- the routine index to the library code; the library code fixes up
- the stack, finds and executes the routine (based on the index),
- and returns directly back to the point where the routine was
- originally called.
-
- A redirection table is defined for each library (the redirection
- table for IO.ASM is IO.RED) and must be included in the program.
- The dispatcher code is in DISPATCH.ASM and must also be included
- in the program. The library code is in LIBRARY.ASM and must be
- included at the start of the library file.
-
- To use IO.ASM as a runtime library, just include the following
- statements in your program:
-
- Include 'IO.RED'
- Include 'DISPATCH.ASM'
-
-
- The dispatch code automatically loads the library into a specially
- allocated block of memory during execution. When a .COM program
- is loaded, all free memory is allocated to it, thus the program
- must explicitly free some memory before calling any routines
- defined in the library. The most efficient way to do this with
- the following code:
-
- ;--beginning of program, assume SS = ES = CS
- Mov Bx, Offset Progend ;get offset of end code and data
- Mov Sp, Bx ;new top of stack
- Mov Cl, 4 ;bits to shift
- Shr Bx, Cl ;perform shift, make paragraph form
- Inc Bx ;account for possible odd paragraph
- Mov Ah, 4ah ;DOS reallocation function number
- Int 21h ;execute
- :
- : ;program and data
- :
- Org +250 ;make room for stack
- Progend ;absolute end of program and data
- ;--end of program
-
- This code works by calculating the actual number of bytes used by
- the program and then reducing the present memory allocation to
- just those bytes. Since the default stack will probably be
- outside of the allocated memory, the stack must be moved. In this
- case, the offset of the end of the program is increased with the
- ORG statement to allow for a stack of that size and the stack
- place immediately after the program.
-
- Assuming that IO.ASM has been assembled to a library file called
- IO.BIN, the program now can use all the routines declared in
- IO.ASM, just as if they had been declared in the program itself.
- Incidentally, the name of the library, IO.BIN, is defined in the
- redirection table, IO.RED. SOUND.ASM is a sample program that
- actually uses the IO.BIN runtime library.
-
- To create a runtime library, all you have to do is write the
- procedures contained within the library and then write the
- redirection table (it could be a separate file or placed right in
- the program).
-
- A runtime library is differentiated from a normal program only by
- its library header and the last byte being a negative checksum.
- The first part of the library header is contained in the file
- LIBRARY.ASM (the library code). The second part of the header is
- a sequential list of offsets that point to the routines to be
- accessed. The library code finds the routine by indexing into
- this list of offsets. The first offset is index zero, the second
- is index one, etc.
-
-
- The following is the source code for an example runtime library
- that contains the routines SUB1 and SUB2:
-
- ;**********************************
- ;=== library header ==============;----- this is required
- ; for a library, must
- ;--- library code --------------- ; come at start
- ;
- Include 'Library.Asm' ;
- ;
- ;--- offsets to subroutines ------ ;
- ;
- Dw Offset Sub1 ;
- Dw Offset Sub2 ;
-
- ;=== body of library =============;----- these are just
- ; standard procedure
- ;--- procedure SUB1 ------------- ; declarations
- ;
- Sub1 Proc Near ;
- : ;
- <procedure body> ;
- : ;
- Ret ;
- Endp ;Sub1 ;
- ;
- ;--- procedure SUB2 ------------- ;
- ;
- Sub2 Proc Near ;
- : ;
- <procedure body> ;
- : ;
- Ret ;
- Endp ;Sub1 ;
-
- ;=== library checksum ============;----- this is required
- ; for a library
- Db Neg $Chksum ;
- ;**********************************
-
- The redirection table and dispatch code must exist within the
- program that's using the library. The redirection table accepts
- control after the CALL instruction and then passes control to the
- dispatch code. For each routine defined in the library, there
- must be a label in the redirection table. Once in the redirection
- table, the BX register is pushed on the stack, the routine index
- is loaded into BL, and the program jumps to a the redirection
- table DISPATCH statement. The DISPATCH statement is a macro that
- defines the library file name and passes control to the the
- dispatch code. The DISPATCH macro and the dispatch code are both
- contained in DISPATCH.ASM. The index in BL is passed directly to
- the library code to find the routine. A redirection table is
- needed for each runtime library being accessed, though only one
- copy of DISPATCH.ASM is needed for any number of redirection
- tables.
-
-
- The following is a program that makes use of the example library
- above. It assumes that the library has been assembled to
- SAMP.BIN:
-
- ;**********************************
- ;=== body of program =============;
- ;
- ;--- reduce memory allocation --- ;
- ;
- Mov Ah, 4ah ;function number
- Mov Bx, 100h ;get whole segment (includes stack)
- Int 21h ;execute, reduce allocation
- ;
- ;--- main program --------------- ;
- ;
- : ;
- Call Sub1 ;access external SUB1, etc.
- : ;
- Call Sub2 ;access external SUB2, etc.
- : ;
-
- ;=== redirection table ===========;
- ;
- ;--- procedure substitutions ---- ;
- ;
- Sub1 Push Bx ;
- Mov Bl, 0 ;set index, first offset in library header
- Jmp Process ;
- Sub2 Push Bx ;
- Mov Bl, 1 ;set index, second offset in library header
- Jmp Process ;
- ;
- ;--- transfer to dispatch ------- ;
- ;
- Process ;
- Dispatch 'SAMP.BIN' ;specify library file name
-
- ;=== dispatch code ===============;
- ;
- Include 'Dispatch.Asm' ;
- ;**********************************
-
-
- The dispatch code checks for several possible errors that can
- occur when using a runtime library. If an error is detected, a
- message will be displayed and the program will be terminated. The
- error message contains a number that specifies the type of error,
- which are as follows:
-
- Error
- Number Meaning
- ----- --------------------------------------------------------
- 01 Could not allocate memory. Not enough free memory is
- available to load the library. Probably means that you
- forgot to reduce the initial memory allocation.
-
- 02 Could not open library file. Probably means that the
- library file was not found. The name of the file to
- look for (including a drive and path) can be changed in
- the redirection table.
-
- 03 Incompatible library version. The library
- implementation version is incompatible with the
- dispatcher implementation version. The library or
- dispatcher should be updated and reassembled.
-
- 04 Error in library file. The library has an incorrect
- format or contains some other error, like a bad or
- nonexistent header or checksum.
-
- 05 Unknown error. Some kind of internal error or
- something. This error should not normally happen.
-
-