CALL

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

  • RUN
  • COMMAND$
  • SUB
  • ENDSUB