muta...@gmail.com
2023-05-21 04:07:07 UTC
Ok, so this is initial thoughts. I don't think I've ever
actually written a TSR before, so I may have some
technically impossible suggestions.
Also note that this is an extension for RM16 and
potentially PM16 and the Turbo 186 (8-bit segment
shift instead of 4-bit). It has no relation to 32-bit.
My main interest is C programs, so I would like a
TSR for genuine MSDOS that is similar to MSVCRT.DLL.
My main interest is in huge memory model, and I intend
for PDOS/86 (built as huge memory model) to export its
own C library, so that it will be able to run PDOS-generic
8086 applications, which assume the C and Pos* library
functions are provided via a parameter on the stack.
I'm not sure how you're supposed to hook MSDOS at the
point that it executes an app. Like HX does. Perhaps the
"exec" facility is hooked and then you switch the name of
the executable to a stub and let MSDOS execute that stub
so that you regain control and can load the original program,
with the required parameter on the stack this time.
So it sounds like PDOS-generic apps (which don't execute
the INT instruction) can be run. This allows a pseudo-bios
to run under genuine MSDOS that is able to redirect a
PDOS-generic application to use an emulated disk instead
of bypassing PDOS-generic itself and going directly to
MSDOS via INT 21H.
Note that I can't (or perhaps won't) attempt to stop a "badly
behaved" executable from bypassing PDOS-generic and
going directly to MSDOS (or the BIOS).
That should cover most of what I want.
But that would still require the user to load the TSR in
advance. Otherwise the app would attempt to access
the stack and have a wild pointer.
So I need to be able to access the stack, but only if I know
it is valid.
If it is not valid, then I need to either load the TSR at this
point, or print a message (using INT 21H) to say that this
is a PDOS-generic application running under genuine MSDOS
which won't work without the TSR.
And I need to find out whether the stack is valid, without
doing an INT which will bypass the PDOS-generic
environment.
So I was thinking of using a field in the PSP.
I can see at offset 40H is some sort of version.
I was thinking that PDOS-generic for 8086 and the TSR
could populate this with a minor version number of
x'80', such that minor versions >= 128 are actually
PDOS, with the minor version having 128 subtracted.
I could use an environment variable instead, but I'm not
keen on pointers that have only a segment. I want a
proper far pointer.
This (running PDOS-generic apps) would basically bypass
some other issues I had.
One is that I want to eliminate the hardcode 4-bit shift in
my DOS startup code, designed to release memory, since
the Turbo Linker asks for maximum memory. The shift
would potentially be 8-bit on a Turbo 186, and when running
under a PM16 version of PDOS, ie PDOS/286, the segment
manipulation is more complicated. I intended to provide
huge pointer manipulation facilities in PDOS/86, and only
if they weren't present (because it was genuine MSDOS),
would I fall back to 4-bit segment shift assumptions.
Note that Watcom C (not sure about Microsoft C), generates
function calls to manipulate huge pointers (which all pointers
are in the huge memory model). Those functions can use the
PDOS/86-provided manipulation functions (if available),
otherwise use code that assumes 4-bit segment shifts.
Also note that I use a 32-bit size_t in PDPCLIB for huge
memory model, even though Watcom's library doesn't.
So I can use INT 21H extension functions to see if these
manipulation functions are available.
This would be useful if I wanted a traditional MSDOS
application that uses INT 21H to start running on an
appropriate Turbo 186/80286 using a flavor of PDOS,
to continue to work and make use of the extra memory
available.
So long as the traditional MSDOS program obeyed some
rules. Those rules are not actually traditional, but could
have been created in the 1980s. Basically you need to be
careful before you manipulate a segment register.
Normally C programs don't actually manipulate segment
registers. They are loaded with values that were set at
load time.
The PDOS-generic app would still load DGROUP into the
segment registers at startup. ie the segmentation will
necessitate some assembler, unlike the simple scheme
I have for PDOS-generic for 32-bit.
Still mulling over what that startup assembler should
ideally look like.
BFN. Paul.
actually written a TSR before, so I may have some
technically impossible suggestions.
Also note that this is an extension for RM16 and
potentially PM16 and the Turbo 186 (8-bit segment
shift instead of 4-bit). It has no relation to 32-bit.
My main interest is C programs, so I would like a
TSR for genuine MSDOS that is similar to MSVCRT.DLL.
My main interest is in huge memory model, and I intend
for PDOS/86 (built as huge memory model) to export its
own C library, so that it will be able to run PDOS-generic
8086 applications, which assume the C and Pos* library
functions are provided via a parameter on the stack.
I'm not sure how you're supposed to hook MSDOS at the
point that it executes an app. Like HX does. Perhaps the
"exec" facility is hooked and then you switch the name of
the executable to a stub and let MSDOS execute that stub
so that you regain control and can load the original program,
with the required parameter on the stack this time.
So it sounds like PDOS-generic apps (which don't execute
the INT instruction) can be run. This allows a pseudo-bios
to run under genuine MSDOS that is able to redirect a
PDOS-generic application to use an emulated disk instead
of bypassing PDOS-generic itself and going directly to
MSDOS via INT 21H.
Note that I can't (or perhaps won't) attempt to stop a "badly
behaved" executable from bypassing PDOS-generic and
going directly to MSDOS (or the BIOS).
That should cover most of what I want.
But that would still require the user to load the TSR in
advance. Otherwise the app would attempt to access
the stack and have a wild pointer.
So I need to be able to access the stack, but only if I know
it is valid.
If it is not valid, then I need to either load the TSR at this
point, or print a message (using INT 21H) to say that this
is a PDOS-generic application running under genuine MSDOS
which won't work without the TSR.
And I need to find out whether the stack is valid, without
doing an INT which will bypass the PDOS-generic
environment.
So I was thinking of using a field in the PSP.
I can see at offset 40H is some sort of version.
I was thinking that PDOS-generic for 8086 and the TSR
could populate this with a minor version number of
x'80', such that minor versions >= 128 are actually
PDOS, with the minor version having 128 subtracted.
I could use an environment variable instead, but I'm not
keen on pointers that have only a segment. I want a
proper far pointer.
This (running PDOS-generic apps) would basically bypass
some other issues I had.
One is that I want to eliminate the hardcode 4-bit shift in
my DOS startup code, designed to release memory, since
the Turbo Linker asks for maximum memory. The shift
would potentially be 8-bit on a Turbo 186, and when running
under a PM16 version of PDOS, ie PDOS/286, the segment
manipulation is more complicated. I intended to provide
huge pointer manipulation facilities in PDOS/86, and only
if they weren't present (because it was genuine MSDOS),
would I fall back to 4-bit segment shift assumptions.
Note that Watcom C (not sure about Microsoft C), generates
function calls to manipulate huge pointers (which all pointers
are in the huge memory model). Those functions can use the
PDOS/86-provided manipulation functions (if available),
otherwise use code that assumes 4-bit segment shifts.
Also note that I use a 32-bit size_t in PDPCLIB for huge
memory model, even though Watcom's library doesn't.
So I can use INT 21H extension functions to see if these
manipulation functions are available.
This would be useful if I wanted a traditional MSDOS
application that uses INT 21H to start running on an
appropriate Turbo 186/80286 using a flavor of PDOS,
to continue to work and make use of the extra memory
available.
So long as the traditional MSDOS program obeyed some
rules. Those rules are not actually traditional, but could
have been created in the 1980s. Basically you need to be
careful before you manipulate a segment register.
Normally C programs don't actually manipulate segment
registers. They are loaded with values that were set at
load time.
The PDOS-generic app would still load DGROUP into the
segment registers at startup. ie the segmentation will
necessitate some assembler, unlike the simple scheme
I have for PDOS-generic for 32-bit.
Still mulling over what that startup assembler should
ideally look like.
BFN. Paul.