home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
asm
/
wasm
/
io.doc
< prev
next >
Wrap
Text File
|
1988-03-07
|
17KB
|
351 lines
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.