ID Number: Q39536
3.x 4.00 4.01
MS-DOS
Question:
We are writing a terminate-and-stay-resident (TSR) software
application and would like to use the MS-DOS EXEC function (MS-DOS
Interrupt 21H, Function 4BH), but we are not able to get it to work.
Will this function work from within a TSR application? In other words,
is there any difference between executing a child process by using the
EXEC service from a TSR application as opposed to a normal
application?
Response:
There are many considerations for using the MS-DOS EXEC function from
a TSR application. This is not a simple issue. We have to make the
following assumptions:
1. You have a TSR application residing in memory that wants to call
the MS-DOS EXEC function to execute another child application.
2. The TSR is written in assembly language. Working from such a
theoretical base, we don't have to worry about idiosyncrasies and
abstractions of the run-time library functions of high-level
languages (e.g. how the Microsoft C Compiler is handling its spawn,
EXEC, or system functions). For applications working this close to
the system, it's a good idea to program in assembly language
anyway, since you have to be very familiar with every machine
instruction that you make.
3. Your program is intelligent enough to know when it can and cannot
issue MS-DOS services--reentrancy problems will bring a TSR
application to a quick halt if the program is not careful. The
application must be able to detect when MS-DOS is in a critical
section and must refrain from issuing MS-DOS calls; otherwise, the
application will have problems. One of the best sources of
information on how to do this is article 11 of "The MS-DOS
Encyclopedia."
4. The program is running under the proper environment (i.e., PSP or
PHP). This, like the reentrancy issues, is described in detail in
article 11 of "The MS-DOS Encyclopedia." Without this, there is a
good chance that MS-DOS will be confused as to who is issuing
MS-DOS calls: the foreground application or your TSR application.
At this point, we can hopefully assume that we have a "well-behaved"
TSR application that knows when to attempt calling MS-DOS, and how to
save and restore its environment to avoid any confusion with the
foreground application; also, we don't have to be concerned with the
limitations of an HLL (High Level Language) run-time library.
These, of course, are a lot of limitations.
From this point, your TSR should be able to safely call the MS-DOS
EXEC function.
Complications
At this point, your TSR application will most likely run into problems
when it is not able to find enough memory to EXEC a program. A TSR is
almost always at the mercy of the current foreground application's
environment, and how the environment is controlling the system. These
programs often allocate the largest chunk of free memory when they are
invoked, and they do not leave you enough to use for your EXEC. An
example of this is COMMAND.COM, which allocates all available memory
so that it can place its transient portion at the top of memory. Most
.COM files allocate all of memory; the only way that you could have
free space is if the program issues MS-DOS Interrupt 21H Service 4AH,
SETBLOCK. This would free up some of the memory it has allocated for
this process, perhaps giving you enough room to EXEC your program.
Many .EXE files have this allocation size set to a smaller value; this
field is in the EXE header.
The result of all of this careful planning and coding is that you may
be able to EXEC a program, depending on the current application
running, how much memory it has allocated, and how much memory is
free. Thus, writing a TSR that uses EXEC is possible if it is done
carefully, but it is dependent on the foreground application. That is,
the success of the EXEC is based on the currently running program and
how much memory is available (which is largely a factor of the
currently running program).
Another example of how a TSR application may foul up the foreground
application is if it does something such as allocating memory to
perform an EXEC operation. If the foreground application has freed up
enough memory to allow you to work with, it very well may be that the
foreground application is planning on using this memory for its own
purposes, for example, EXECing its own child process. It will not
expect a background TSR application to allocate this memory and use it
for its own use. This may have unpredictable results in the operation
of the foreground application.
MS-DOS is a single-tasking environment that does not have the proper
support for multiple processes. Instead of the operating system
performing time slicing between processes, more than one process is
able to occupy memory only by hooking onto interrupts and interrupting
another application. How successful a background application is at
interrupting this foreground application is almost entirely up to the
background application, and MS-DOS has no control over this. Once the
background application is in control of the system, it may not be able
to perform what it wants, since it is at the mercy of the current
environment in which the foreground application is running. Writing
TSR applications is a haphazard and risky thing to do.