Dec 072017
Method to make QBASIC 4.5 return specified Return Codes when program terminates. Maintains QBasic’s clean up of vectors, and gives a -1 return code if termination is due to runtime errors. Patching involved. | |||
---|---|---|---|
File Name | File Size | Zip Size | Zip Type |
AEXIT.ASM | 661 | 382 | deflated |
AEXIT.OBJ | 493 | 418 | deflated |
AEXIT.QLB | 5193 | 3147 | deflated |
EEXIT.ASM | 123 | 92 | deflated |
EEXIT.OBJ | 231 | 208 | deflated |
INFO.TXT | 5398 | 2230 | deflated |
MOD.TXT | 3700 | 1655 | deflated |
TESTENV.BAS | 312 | 191 | deflated |
TESTEXE.BAS | 340 | 201 | deflated |
TPCREAD.ME | 199 | 165 | deflated |
Download File QBTERM2.ZIP Here
Contents of the INFO.TXT file
METHOD to enable QBASIC 4.5 to return a RETURN CODE on TERMINATION
==================================================================
Revision 2
Added AEXIT.ASM, AEXIT.OBJ & AEXIT.QLB
Support for EEXIT when in the QBASIC ENVIRONMENT
(provided you can include AEXIT.OBJ in your QLB ....
ie you have the corresponding LIB)
See (3)
----------------------------------------------------------------
(1) Patch BCOM45.lib
Since we are now going to END our Q-BASIC programs with our own
specified RETURN CODE, we need to change Q-BASIC's default RETURN CODE
from 0 to FF.
Thereafter, we will get this return code if our STAND-ALONE EXE program
exits with a run-time error (ie divide by zero etc)
B$END:
CALLB$END+b
XORAX,AX
PUSHAX
CALL_exit
Change XOR AX,AX to MOV AL,FFh;Default Return Code
(33C0 to B0FF )
In my copy of BCOM45.LIB, this was 1B0FC offset from the start of file
ie 1BOFC=33 ===> B0
1B0FD=C0 ===> FF
(2) Now we need a way to call _exit, and to pass it our required return code.
(Note: _exit is the exit routine in BCOM45.LIB that will clean up after
QBASIC and then terminate the program)
This gets a little complicated due to the QBASIC environment.
When working in the QBASIC Environment, we want to be able to see the Return
Code displayed, and we no NOT want to call _exit (which would TERMINATE the
Q-BASIC Environment and return us to DOS !)
When we COMPILE & LINK to make a STAND-ALONE QBASIC Program, we do not
necessarly want to DISPLAY a RETURN CODE message, but we DO want to call
_exit and have our specified return code.
Looking at the STAND ALONE program case first:
Since we cannot call _exit directly and pass our Return Code to it, we need
a very small ASSEMBLY CODE routine called EEXIT.
Our QBASIC program will look like this:
DECLARE SUB EEXIT(BYVAL retcode AS INTEGER)
....
program
....
EEXIT(5) {or EEXIT(a%)}
No need for an END.
Note END will return our -1 return code !!!!
EEXIT.ASM and EEXIT.OBJ are supplied with this package.
EEXIT.ASM is a simple program to JUMP to _exit
_exit expects an INTEGER to be passed by VALUE to it, and will use
this as the RETURN CODE.... (GREAT !!! Just what we want !)
All that is needed is to ADD the object module EEXIT.OBJ to BCOM45.lib
using the LIB.EXE program.
ie
LIB BCOM45
command: +EEXIT
list:
output lib:
THATS IT !!!!!
Note: You must make the STAND ALONE program from the DOS prompt level, using
(at last) BCOM45.lib as a library module.
----------------------------------------------------------
In the QBASIC ENVIRONMENT we will not be using BCOM45.LIB, so we need
a temporary LOCAL SUB called EEXIT while de-bugging or program.
An example follows:
DECLARE SUB EEXIT(retcode AS INTEGER)
...........
program
..........
EEXIT(5)
SUB EEXIT(rc%)
PRINT "Return Code is :";rc%
SLEEP 2
END SUB
Note that in the DECLARATION, retcode is NOT passed by VALUE, and the
addition of the LOCAL EEXIT sub.
The BYVAL must be ADDED, and the LOCAL SUB deleted when it comes time to make
the STAND ALONE program.
....................................................................
OK.... so the above is not very "CLEAN", but it DOES WORK !!!!
What is more important is that
(a) You get your desired return code
(b) You get -1 if you get a run-time error which is better than
the default 0 !!!
(c) QBASIC's CLEAN-UP housekeeping is maintained.
(just calling INT 21h with ah=4C does NOT !!!!)
(d) Within the QBASIC Environment, you get to see a display of
your RETURN Code as the program terminates.
**** PLEASE **** If you know a better way of doing this, or have any
suggestions for improving the method, let us all know !!!!
-------------------------- ENJOY ------------------------------
REVISION 2
==========
You can save having to modify your BASIC program to support EEXIT when
in the QBASIC ENVIRONMENT by including AEXIT.OBJ in your QLB
(assuming you can add it !!! ie Have the LIB)
AEXIT.OBJ is an ASM SUB that will display the Return Code, and is called
in exactly the same way (BYVAL) as EEXIT.OBJ, the code for use with a
STAND ALONE BASIC EXE program.
Note: Both EEXIT.OBJ & AEXIT.OBJ are ASM SUBs called EEXIT.
The difference is that EEXIT.OBJ terminates the program with the Return Code
being passed back to DOS, while AEXIT.OBJ displays the Return Code on the
Screen and does not Terminate the QBASIC Environment session.
Summary:
If you are able to add OBJs to your QLB then
(a) Add AEXIT.OBJ to your QLB
(b) Add EEXIT.OBJ to your BCOM45.LIB
(c) Patch BCOM45.lib if you want runtime errors to report -1
If you don't mind runtime errors of 0, don't bother to patch.
(d) Use the Definition
DEFINE SUB EEXIT(byval retcode as INTEGER)
(e) Within your basic program use EEXIT(returncode%) instead
of END or SYSTEM
If you can't add OBJs to your QLB (& need to use an existing QLB)
then read (1) & (2).
If you are not using a QLB, use AEXIT.QLB (QLB containing AEXIT.OBJ)
------------------------------------------------------------------------
==================================================================
Revision 2
Added AEXIT.ASM, AEXIT.OBJ & AEXIT.QLB
Support for EEXIT when in the QBASIC ENVIRONMENT
(provided you can include AEXIT.OBJ in your QLB ....
ie you have the corresponding LIB)
See (3)
----------------------------------------------------------------
(1) Patch BCOM45.lib
Since we are now going to END our Q-BASIC programs with our own
specified RETURN CODE, we need to change Q-BASIC's default RETURN CODE
from 0 to FF.
Thereafter, we will get this return code if our STAND-ALONE EXE program
exits with a run-time error (ie divide by zero etc)
B$END:
CALLB$END+b
XORAX,AX
PUSHAX
CALL_exit
Change XOR AX,AX to MOV AL,FFh;Default Return Code
(33C0 to B0FF )
In my copy of BCOM45.LIB, this was 1B0FC offset from the start of file
ie 1BOFC=33 ===> B0
1B0FD=C0 ===> FF
(2) Now we need a way to call _exit, and to pass it our required return code.
(Note: _exit is the exit routine in BCOM45.LIB that will clean up after
QBASIC and then terminate the program)
This gets a little complicated due to the QBASIC environment.
When working in the QBASIC Environment, we want to be able to see the Return
Code displayed, and we no NOT want to call _exit (which would TERMINATE the
Q-BASIC Environment and return us to DOS !)
When we COMPILE & LINK to make a STAND-ALONE QBASIC Program, we do not
necessarly want to DISPLAY a RETURN CODE message, but we DO want to call
_exit and have our specified return code.
Looking at the STAND ALONE program case first:
Since we cannot call _exit directly and pass our Return Code to it, we need
a very small ASSEMBLY CODE routine called EEXIT.
Our QBASIC program will look like this:
DECLARE SUB EEXIT(BYVAL retcode AS INTEGER)
....
program
....
EEXIT(5) {or EEXIT(a%)}
No need for an END.
Note END will return our -1 return code !!!!
EEXIT.ASM and EEXIT.OBJ are supplied with this package.
EEXIT.ASM is a simple program to JUMP to _exit
_exit expects an INTEGER to be passed by VALUE to it, and will use
this as the RETURN CODE.... (GREAT !!! Just what we want !)
All that is needed is to ADD the object module EEXIT.OBJ to BCOM45.lib
using the LIB.EXE program.
ie
LIB BCOM45
command: +EEXIT
list:
output lib:
THATS IT !!!!!
Note: You must make the STAND ALONE program from the DOS prompt level, using
(at last) BCOM45.lib as a library module.
----------------------------------------------------------
In the QBASIC ENVIRONMENT we will not be using BCOM45.LIB, so we need
a temporary LOCAL SUB called EEXIT while de-bugging or program.
An example follows:
DECLARE SUB EEXIT(retcode AS INTEGER)
...........
program
..........
EEXIT(5)
SUB EEXIT(rc%)
PRINT "Return Code is :";rc%
SLEEP 2
END SUB
Note that in the DECLARATION, retcode is NOT passed by VALUE, and the
addition of the LOCAL EEXIT sub.
The BYVAL must be ADDED, and the LOCAL SUB deleted when it comes time to make
the STAND ALONE program.
....................................................................
OK.... so the above is not very "CLEAN", but it DOES WORK !!!!
What is more important is that
(a) You get your desired return code
(b) You get -1 if you get a run-time error which is better than
the default 0 !!!
(c) QBASIC's CLEAN-UP housekeeping is maintained.
(just calling INT 21h with ah=4C does NOT !!!!)
(d) Within the QBASIC Environment, you get to see a display of
your RETURN Code as the program terminates.
**** PLEASE **** If you know a better way of doing this, or have any
suggestions for improving the method, let us all know !!!!
-------------------------- ENJOY ------------------------------
REVISION 2
==========
You can save having to modify your BASIC program to support EEXIT when
in the QBASIC ENVIRONMENT by including AEXIT.OBJ in your QLB
(assuming you can add it !!! ie Have the LIB)
AEXIT.OBJ is an ASM SUB that will display the Return Code, and is called
in exactly the same way (BYVAL) as EEXIT.OBJ, the code for use with a
STAND ALONE BASIC EXE program.
Note: Both EEXIT.OBJ & AEXIT.OBJ are ASM SUBs called EEXIT.
The difference is that EEXIT.OBJ terminates the program with the Return Code
being passed back to DOS, while AEXIT.OBJ displays the Return Code on the
Screen and does not Terminate the QBASIC Environment session.
Summary:
If you are able to add OBJs to your QLB then
(a) Add AEXIT.OBJ to your QLB
(b) Add EEXIT.OBJ to your BCOM45.LIB
(c) Patch BCOM45.lib if you want runtime errors to report -1
If you don't mind runtime errors of 0, don't bother to patch.
(d) Use the Definition
DEFINE SUB EEXIT(byval retcode as INTEGER)
(e) Within your basic program use EEXIT(returncode%) instead
of END or SYSTEM
If you can't add OBJs to your QLB (& need to use an existing QLB)
then read (1) & (2).
If you are not using a QLB, use AEXIT.QLB (QLB containing AEXIT.OBJ)
------------------------------------------------------------------------
December 7, 2017
Add comments