Format
CALL (string1,string2)
<-Format 1
CALL SUB (stringconstant1,[arg1,...,argN])
<-Format 2
Description
Depending on the format that you select, this statement can be used to
perform two different functions. Format 1 is used to load and execute
another program (in .EXE, .COM format). Format 2 is used when you have
compiled a subroutine in a .OBJ file, and wish to incorporate this routine
in an ASIC program, and CALL it as a subroutine. Notice the difference
between these two approaches. In format 1, execution of your ASIC program
is suspended, and a new .EXE or .COM file is loaded from disk and executed.
When the .EXE or .COM program terminates, your ASIC program resumes
execution. With format 2, however, the subroutine itself is bound into
your ASIC program with the DOS linker, so that when you call it, no disk
access is required, and the overhead of the call is much lower.
When using format 1, this statement can be used to load and execute other
programs compiled with ASIC or another compiler. String1 represents the
name of the program to execute. String2 contains any arguments to be
passed to the program (it may be NULL, i.e. ""). If an error occurs when
ASIC attempts to call the program, it will set the system ERROR variable to
255. Otherwise, the ERROR variable will be set to the value of the return
code of the called program (which is 0 unless the called program specifies
otherwise).
Format 2 is used to call a separately compiled subroutine, that uses the
BASIC (or PASCAL) parameter passing conventions. You could use this to
call a subroutine that you had written in ASIC or assembler. When using
this format, you must compile using the OBJ output option. ASIC will
produce an OBJ format output file, that can be linked with the standard DOS
linker. When you compile within the integrated environment, ASIC
automatically calls the DOS linker for you, when the OBJ option is
selected. With this format, stringconstant1 must be a string constant that
contains the name of the subroutine to be called. The remaining fields
(arg1 through argN) are optional, but if specified, they must be variables
or constants. These arguments will be passed to the called subroutine
using the stack. These arguments will be passed "by reference", which
means that a pointer to the variable will be passed, instead of the value
contained in the variable. This means that the subroutine you call can
modify the values of the ASIC variables passed. See the SUB and ENDSUB
statements for information on create OBJ subroutines using ASIC.
(See Chapter 10 of the ASIC manual, for more information on using format
2).
Example
CALL ("MYPROG.COM","")
REM other code follows
This statement would cause ASIC to load and execute the program
"MYPROG.COM". No arguments will be passed to the program. When MYPROG
terminates, the calling program will regain control on the line following
the call, in this case the "REM" statement.
CALL ("COMMAND.COM"," /C WP.BAT")
In this example, a ".BAT" type file is executed called "WP.BAT". To run
".BAT" files, it is necessary to load a copy of COMMAND.COM as shown above
(COMMAND.COM contains the DOS code required to load and execute ".BAT"
files). Using this format, you can also run some "built in" DOS commands
such as DIR or SORT. Using CALL with this format, is similar to using the
GWBASIC/BASICA SHELL command
CALL SUB ("mysub",A,A$,1)
In this example, a subroutine "mysub" is being called. Three arguments are
being passed to the subroutine, "A", "A$" and "1". You must set the
compiler output option to OBJ, and specify "MYSUB.OBJ" in the LINK options
subroutine list. The arguments will be passed to the subprogram on the
stack in the order: A,A$,1.
Comments
Format 1
If you are compiling with the OBJ output option, you must LINK your program
from the command line. This is due to the fact that, by default, LINK.EXE
will request all available memory for the program. When your program tries
to CALL another program, DOS has no memory to allocate for the called
program and the CALL will fail. To get around this, use the
"/CPARMAXALLOC" LINK parameter and run LINK from the COMMAND line. You
must estimate how much memory your program needs to load (in 16 byte
paragraphs). For example, to limit your program to 32k, use a LINK
statement such as the following:
LINK progname /CPARMAXALLOC:2000
If you fail to specify a large enough value for "/CPARMAXALLOC", LINK.EXE
will ignore the option and allocate all available memory, so you may have
to experiment with this parameter to determine the proper setting.
When using format 1, string1 must contain the FULL pathname of the program
(ie,"\directory\progname.COM") only if the program is NOT in the current
directory. You must include the file extension on the file name (for
example, use "MYPROG.COM" instead of just "MYPROG", or use "MYPROG.EXE"
instead of "MYPROG").
If you wish to pass arguments to the program build it as follows:
YOURPARM$ = "arguments"
N = LEN(YOURPARM$)
A$ = CHR$(N)
A$ = A$ + YOURPARM$
B$ = CHR$(13)
A$ = A$ + B$
CALL "progname" a$
The above creates an argument list according to the strict DOS calling
rules, however, you can just create the arguments in a string, and precede
them with a leading space. This will work for arguments up to 32
characters in length (space character is ASCII 32). You might want to try
this short cut first, and only resort to the full formal approach if you
have problems with it, or need to specify longer arguments:
CALL "progname" " arguments"
It is recommended (but not required) that you compile your program using
the EXE format (instead of the COM format) when your program uses format 1,
since an EXE program will release more memory when calling the program.
This will allow you to call a slightly larger program than is possible with
the COM format.
Format 2
When using format 2 , the following considerations apply. First, remember
that the arguments you pass to the subroutine must match the arguments the
subroutine expects to receive. For example, if you pass a single integer
to the subroutine, the subroutine had better expect to receive a single
integer, or the results will be unpredictable. Second, since all arguments
are passed by reference, all arguments can be modified by the called
routine. Be aware that if you pass a constant such as "1" to the routine
and it modifies the value to "2", that ASIC will now use the value "2" for
the constant value of "1" wherever "1" is referenced your program. For
example, suppose you wrote a subroutine called ADD that added the value of
argument 2 to the value of argument 1 and stored the result in argument 1:
CALL SUB ("ADD", 1,33)
PRINT "1=";
PRINT 1
END
Program output is:
1=34
Instead, you would want to code the program as follows:
A=1
CALL SUB ("ADD",A,1)
PRINT "A=";
PRINT A
PRINT "1=";
PRINT 1
END
Program output is:
A=34
1=1
Caution
IF YOU CALL A ".BAT" FILE AND DO NOT LOAD A COPY OF COMMAND.COM, THE
RESULTS ARE UNPREDICTABLE (SEE ABOVE FOR AN EXAMPLE OF HOW TO CALL BAT
FILE).
You may use the debugger with programs which contain "CALL" statements.
However, the programs you call should not themselves contain debugging
code. For example, if A.ASI calls B.ASI, then make sure you compile B.ASI
with the "Debugging Code" option OFF before you try to debug program A.ASI.
Failure to do so will cause the debugger to behave erratically. This also
applies to programs you write using other compilers, since they also use
the same interrupt as ASIC (INT 3).
See Also