• DOS extension proposal

    From mutazilah@gmail.com@21:1/5 to All on Sat May 20 21:07:07 2023
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mutazilah@gmail.com@21:1/5 to All on Sat May 20 22:46:59 2023
    Note that not directly doing an INT 21H has an analogy
    on the Amiga.

    On the Amiga, all system calls are vectored off a
    hardcoded address 4.

    Which prevents PDOS-generic or some other emulator
    from redirecting the syscalls to a different system.

    Unless you were to use hardware paging or whatever
    to redirect address 4 somewhere else. But I don't want
    to rely on such hardware existing, or able to be
    implemented (with privilege).

    So what I did was create a "new traditional standard"
    (basically something that could/should have been done
    in the 1980s) where Amiga apps first check register
    d6 (there's a bit more to it than that) to see what the
    base address is. If d6 is set to some value then use
    that, otherwise use the normal address 4. (something
    similar to that).

    So that gives the ability of a software override.

    So it seems I'm trying to construct the 8086 equivalent.
    Plus other things all lumped in to one big barrel of
    confusion.

    BFN. Paul.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mutazilah@gmail.com@21:1/5 to All on Sat May 20 23:36:18 2023
    Note that the direct equivalent of the Amiga on the 8086
    would be if I checked the size at offset 0x80 in the PSP
    and if the command length was greater than 0x80, which
    is impossible, then it is a fake length, and it means the
    caller is PDOS, and subtract x'80' from the length to get
    the actual length, and now you know whether it is a
    PDOS environment or not.

    On the Amiga, that would allow D6-aware programs to
    run on an Amigados semi-clone.

    But that's still using the Amigados API, not PDOS-generic.

    PDOS-generic doesn't care about D6/location 4 and the
    startup code of apps just assumes it is PDOS-generic.

    I guess the 8086 equivalent would be if I had an Amigados
    semi-clone that had enhancements and I wished to
    support both enhancement-aware apps and traditional
    apps.

    BFN. Paul.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mutazilah@gmail.com@21:1/5 to muta...@gmail.com on Sat May 20 23:56:01 2023
    On Sunday, May 21, 2023 at 2:45:25 PM UTC+8, muta...@gmail.com wrote:

    (*) I could still put in some checks in the PSP so that they
    could gracefully exit via INT 21H after reporting via 21H
    that this requires a PDOS environment.

    Another possibility would be to do what Windows does
    with PE and have a stub that terminates gracefully, and
    Windows bypasses the stub.

    But that requires a relatively expensive change in the tools.

    Getting the startup code to inspect the PSP is cheap.

    And setting a minor version number of 128+ is cheap too.

    Or some other appropriate field in the PSP.

    BFN. Paul.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mutazilah@gmail.com@21:1/5 to All on Sat May 20 23:45:24 2023
    And so the equivalent would be -

    PDOS-generic programs just assume that the
    required data is on the stack and carry on.

    But traditional programs are free to do INT 21H.

    So two different startup routines are required.

    Which I already have anyway.

    So PDOS-generic can be largely ignored (*).

    For traditional programs, I need them to do INT 21H
    calls to see if extensions are available before deciding
    to hardcode a segment shift of 4 bits.

    And continue to allow them to overcome the traditional
    issue with linkers asking for all memory.

    BFN. Paul.


    (*) I could still put in some checks in the PSP so that they
    could gracefully exit via INT 21H after reporting via 21H
    that this requires a PDOS environment.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From JJ@21:1/5 to muta...@gmail.com on Sun May 21 17:35:58 2023
    On Sat, 20 May 2023 21:07:07 -0700 (PDT), muta...@gmail.com wrote:
    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.

    If you're writing a system extension which are not compatible with MS-DOS,
    you can't tell MS-DOS programs to obey by the extension's rules, because
    most MS-DOS programs already built to obey MS-DOS rules. Otherwise none of MS-DOS program will work with that extension.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mutazilah@gmail.com@21:1/5 to All on Sun May 21 14:23:19 2023
    On Sunday, May 21, 2023 at 6:35:59 PM UTC+8, JJ wrote:

    Still mulling over what that startup assembler should
    ideally look like.

    If you're writing a system extension which are not compatible with MS-DOS, you can't tell MS-DOS programs to obey by the extension's rules, because most MS-DOS programs already built to obey MS-DOS rules. Otherwise none of MS-DOS program will work with that extension.

    Sure. And even today, in 2023, my own executables fall into
    this category, as they have for about 3 decades.

    My own executables have zero chance of working on a
    Turbo 186 because the startup code assumes segment
    shifts will be 4 bits.

    Back circa 1987 I should have sat down and prepared
    for the introduction of the Turbo 186 (8-bit segment shifts).

    As the saying goes "better late than never".

    So I'm hoping that by 2024, whenever I build an executable,
    the executable is prepared for the Turbo 186. And a similar
    scheme (lots of selectors lined up) for PM16.

    I can't "fix" everyone else's executables, but I at least want to
    fix my own.

    That's my question.

    How do I fix my executables? The number 4 (seen below) is out
    (for starters).

    BFN. Paul.


    ; It seems that even compact/large/huge require the same thing -
    ; they expect DS=SS and may use near pointers and the stack is
    ; in the DGROUP for this reason. I haven't actually observed
    ; near pointers being used though.

    mov bx,ss
    mov ax,ds
    sub bx,ax
    mov cl,4
    shl bx,cl

    mov bp, sp
    add bp, bx
    mov ss, dx
    mov sp, bp

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)