• PSP

    From mutazilah@gmail.com@21:1/5 to All on Sun Mar 28 03:57:14 2021
    Does anyone have the exact bytes in a MSDOS PSP as documented here:

    INTERRUP.F:

    Format of Program Segment Prefix (PSP):
    Offset Size Description (Table 01378)
    00h 2 BYTEs INT 20 instruction for CP/M CALL 0 program termination
    the CDh 20h here is often used as a signature for a valid PSP
    02h WORD segment of first byte beyond memory allocated to program
    04h BYTE (DOS) unused filler
    (OS/2) count of fake DOS version returns
    05h BYTE CP/M CALL 5 service request (FAR CALL to absolute 000C0h)
    BUG: (DOS 2+ DEBUG) PSPs created by DEBUG point at 000BEh
    06h WORD CP/M compatibility--size of first segment for .COM files
    08h 2 BYTEs remainder of FAR JMP at 05h

    It's just offset x'05' and x'08' and x'09' that I am
    interested in. How did they (allegedly) organize
    a call to 0000:00C0? And they're claiming both a
    CALL and a JMP. Which one is it?

    Thanks. Paul.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From JJ@21:1/5 to muta...@gmail.com on Sun Mar 28 19:03:12 2021
    On Sun, 28 Mar 2021 03:57:14 -0700 (PDT), muta...@gmail.com wrote:

    Does anyone have the exact bytes in a MSDOS PSP as documented here:

    INTERRUP.F:

    Format of Program Segment Prefix (PSP):
    Offset Size Description (Table 01378)
    00h 2 BYTEs INT 20 instruction for CP/M CALL 0 program termination
    the CDh 20h here is often used as a signature for a valid PSP
    02h WORD segment of first byte beyond memory allocated to program
    04h BYTE (DOS) unused filler
    (OS/2) count of fake DOS version returns
    05h BYTE CP/M CALL 5 service request (FAR CALL to absolute 000C0h)
    BUG: (DOS 2+ DEBUG) PSPs created by DEBUG point at 000BEh
    06h WORD CP/M compatibility--size of first segment for .COM files
    08h 2 BYTEs remainder of FAR JMP at 05h

    It's just offset x'05' and x'08' and x'09' that I am
    interested in. How did they (allegedly) organize
    a call to 0000:00C0? And they're claiming both a
    CALL and a JMP. Which one is it?

    Thanks. Paul.

    Both. It's just a splitted FAR CALL instruction.
    i.e. @05h= instruction, @06h= operand.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mutazilah@gmail.com@21:1/5 to All on Sun Mar 28 19:10:52 2021
    On Sunday, March 28, 2021 at 11:03:49 PM UTC+11, JJ wrote:
    On Sun, 28 Mar 2021 03:57:14 -0700 (PDT), muta...@gmail.com wrote:

    Does anyone have the exact bytes in a MSDOS PSP as documented here:

    INTERRUP.F:

    Format of Program Segment Prefix (PSP):
    Offset Size Description (Table 01378)
    00h 2 BYTEs INT 20 instruction for CP/M CALL 0 program termination
    the CDh 20h here is often used as a signature for a valid PSP
    02h WORD segment of first byte beyond memory allocated to program
    04h BYTE (DOS) unused filler
    (OS/2) count of fake DOS version returns
    05h BYTE CP/M CALL 5 service request (FAR CALL to absolute 000C0h)
    BUG: (DOS 2+ DEBUG) PSPs created by DEBUG point at 000BEh
    06h WORD CP/M compatibility--size of first segment for .COM files
    08h 2 BYTEs remainder of FAR JMP at 05h

    It's just offset x'05' and x'08' and x'09' that I am
    interested in. How did they (allegedly) organize
    a call to 0000:00C0? And they're claiming both a
    CALL and a JMP. Which one is it?

    Thanks. Paul.

    Both. It's just a splitted FAR CALL instruction.
    i.e. @05h= instruction, @06h= operand.

    @06 on CP/M is the address of the BIOS in high
    memory (within 64K) but that is sort of not
    possible with MSDOS.

    So @06 on MSDOS is instead the segment size
    according to RBIL above.

    It is @08 that has what is required for MSDOS.

    I'm curious as to what exactly that is. A split
    instruction that skips the word at @06? That's
    a pretty strange split.

    BFN. Paul.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From JJ@21:1/5 to All on Tue Mar 30 00:26:16 2021

    Both. It's just a splitted FAR CALL instruction.
    i.e. @05h= instruction, @06h= operand.

    @06 on CP/M is the address of the BIOS in high
    memory (within 64K) but that is sort of not
    possible with MSDOS.

    So @06 on MSDOS is instead the segment size
    according to RBIL above.

    Oops. That should be @08h. Not @06h. Sorry.

    I'm curious as to what exactly that is. A split
    instruction that skips the word at @06? That's
    a pretty strange split.

    BFN. Paul.

    Not sure, but I'm guessing that @05h and @08 were a later CP/M
    implementation. i.e. @05 was initially used for different purpose or was reserved.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mutazilah@gmail.com@21:1/5 to All on Tue Mar 30 02:20:09 2021
    On Tuesday, March 30, 2021 at 4:26:50 AM UTC+11, JJ wrote:

    Both. It's just a splitted FAR CALL instruction.
    i.e. @05h= instruction, @06h= operand.

    @06 on CP/M is the address of the BIOS in high
    memory (within 64K) but that is sort of not
    possible with MSDOS.

    So @06 on MSDOS is instead the segment size
    according to RBIL above.

    Oops. That should be @08h. Not @06h. Sorry.

    I'm curious as to what exactly that is. A split
    instruction that skips the word at @06? That's
    a pretty strange split.

    Not sure, but I'm guessing that @05h and @08 were a later CP/M implementation. i.e. @05 was initially used for different purpose or was reserved.

    I assume that under CP/M the instruction was
    3 bytes - @05, @06, @07 - which resulted in a
    jump to the BIOS.

    What I want to know is how MSDOS managed to
    make @05, @08 and @09 a far call to 00C0. If
    we can see a PSP from MSDOS for a .com file
    it should have the answer. If we can disassemble
    that, anyway.

    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 Tue Mar 30 12:50:08 2021
    On Wednesday, March 31, 2021 at 6:47:54 AM UTC+11, muta...@gmail.com wrote:

    Running under MSDOS 5.0 gives this PSP:

    Sorry. Forgot to mention I ran it as:

    dumppsp Abc Def Ghi

    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 Tue Mar 30 12:47:53 2021
    On Tuesday, March 30, 2021 at 8:20:10 PM UTC+11, muta...@gmail.com wrote:

    What I want to know is how MSDOS managed to
    make @05, @08 and @09 a far call to 00C0. If
    we can see a PSP from MSDOS for a .com file
    it should have the answer. If we can disassemble
    that, anyway.

    I wrote this program:

    C:\devel\develop>type dumppsp.c /*********************************************************************/
    /* */
    /* This Program Written by Paul Edwards. */
    /* Released to the Public Domain */
    /* */ /*********************************************************************/ /*********************************************************************/
    /* */
    /* dumppsp - dump a PSP to psp.dat */
    /* probably works best for a .com file */
    /* */ /*********************************************************************/

    #include <stdio.h>
    #include <stdlib.h>

    int main(void)
    {
    FILE *fq;

    fq = fopen("psp.dat", "wb");
    if (fq == NULL)
    {
    printf("failed to open psp.dat\n");
    return (EXIT_FAILURE);
    }
    fwrite(NULL, 1, 256, fq);
    fclose(fq);
    return (0);
    }

    And compiled it like this:

    C:\devel\develop>wcl -mt dumppsp.c
    Open Watcom C/C++16 Compile and Link Utility Version 1.6
    Portions Copyright (c) 1988-2002 Sybase, Inc. All Rights Reserved.
    Source code is available under the Sybase Open Watcom Public License.
    See http://www.openwatcom.org/ for details.
    wcc dumppsp.c -ms
    Open Watcom C16 Optimizing Compiler Version 1.6
    Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved.
    Source code is available under the Sybase Open Watcom Public License.
    See http://www.openwatcom.org/ for details.
    dumppsp.c: 30 lines, included 1349, 0 warnings, 0 errors
    Code size: 65
    wlink @__wcl__.lnk
    Open Watcom Linker Version 1.6
    Portions Copyright (c) 1985-2002 Sybase, Inc. All Rights Reserved.
    Source code is available under the Sybase Open Watcom Public License.
    See http://www.openwatcom.org/ for details.
    loading object files
    searching libraries
    creating a DOS .COM executable


    And you can see it created a .com file automatically.


    Running under MSDOS 5.0 gives this PSP:

    C:\devel\bochs>hexdump psp.dat
    000000 CD20C09F 009AF0FE 1DF0DC01 F70E4B01 . ............K.
    000010 F70E5601 F70EF70E 01010100 0203FFFF ..V.............
    000020 FFFFFFFF FFFFFFFF FFFFFFFF 0E10A837 ...............7
    000030 24101400 18002410 FFFFFFFF 00000000 $.....$.........
    000040 05000000 00000000 00000000 00000000 ................
    000050 CD21CB00 00000000 00000000 00414243 .!...........ABC
    000060 20202020 20202020 00000000 00444546 .....DEF
    000070 20202020 20202020 00000000 00000000 ........
    000080 0C204162 63204465 66204768 690D726F . Abc Def Ghi.ro
    000090 6D0D0000 00000000 00000000 00000000 m...............
    0000A0 00000000 00000000 00000000 00000000 ................
    0000B0 00000000 00000000 00000000 00000000 ................
    0000C0 00000000 00000000 00000000 00000000 ................
    0000D0 00000000 00000000 00000000 00000000 ................
    0000E0 00000000 00000000 00000000 00000000 ................
    0000F0 00000000 00000000 00000000 00000000 ................


    The "rom" you see mentioned there is leftover junk from
    this in my autoexec.bat:

    rem mscdex /d:cdrom


    Here are all the PSP offsets from INTERRUP.F:

    Format of Program Segment Prefix (PSP):
    Offset Size Description (Table 01378)
    00h 2 BYTEs INT 20 instruction for CP/M CALL 0 program termination
    the CDh 20h here is often used as a signature for a valid PSP
    02h WORD segment of first byte beyond memory allocated to program
    04h BYTE (DOS) unused filler
    (OS/2) count of fake DOS version returns
    05h BYTE CP/M CALL 5 service request (FAR CALL to absolute 000C0h)
    BUG: (DOS 2+ DEBUG) PSPs created by DEBUG point at 000BEh
    06h WORD CP/M compatibility--size of first segment for .COM files
    08h 2 BYTEs remainder of FAR JMP at 05h
    0Ah DWORD stored INT 22 termination address
    0Eh DWORD stored INT 23 control-Break handler address
    12h DWORD DOS 1.1+ stored INT 24 critical error handler address
    16h WORD segment of parent PSP
    18h 20 BYTEs DOS 2+ Job File Table, one byte per file handle, FFh = closed
    2Ch WORD DOS 2+ segment of environment for process (see #01379)
    2Eh DWORD DOS 2+ process's SS:SP on entry to last INT 21 call
    32h WORD DOS 3+ number of entries in JFT (default 20)
    34h DWORD DOS 3+ pointer to JFT (default PSP:0018h)
    38h DWORD DOS 3+ pointer to previous PSP (default FFFFFFFFh in 3.x)
    used by SHARE in DOS 3.3
    3Ch BYTE DOS 4+ (DBCS) interim console flag (see AX=6301h)
    Novell DOS 7 DBCS interim flag as set with AX=6301h
    (possibly also used by Far East MS-DOS 3.2-3.3)
    3Dh BYTE (APPEND) TrueName flag (see INT 2F/AX=B711h)
    3Eh BYTE (Novell NetWare) flag: next byte initialized if CEh
    (OS/2) capabilities flag
    3Fh BYTE (Novell NetWare) Novell task number if previous byte is CEh
    40h 2 BYTEs DOS 5+ version to return on INT 21/AH=30h
    42h WORD (MSWindows3) selector of next PSP (PDB) in linked list
    Windows keeps a linked list of Windows programs only
    44h WORD (MSWindows3) "PDB_Partition"
    46h WORD (MSWindows3) "PDB_NextPDB"
    48h BYTE (MSWindows3) bit 0 set if non-Windows application (WINOLDAP)
    49h BYTE unused by DOS versions <= 6.00
    4Ch WORD (MSWindows3) "PDB_EntryStack"
    4Eh 2 BYTEs unused by DOS versions <= 6.00
    50h 3 BYTEs DOS 2+ service request (INT 21/RETF instructions)
    53h 2 BYTEs unused in DOS versions <= 6.00
    55h 7 BYTEs unused in DOS versions <= 6.00; can be used to make first FCB
    into an extended FCB
    5Ch 16 BYTEs first default FCB, filled in from first commandline argument
    overwrites second FCB if opened
    6Ch 16 BYTEs second default FCB, filled in from second commandline argument
    overwrites beginning of commandline if opened
    7Ch 4 BYTEs unused
    80h 128 BYTEs commandline / default DTA
    command tail is BYTE for length of tail, N BYTEs for the tail,
    followed by a BYTE containing 0Dh


    It is interesting to see the first 2 of my command line
    arguments being converted into FCBs.

    Next, an attempt to disassemble!

    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 Tue Mar 30 12:57:40 2021
    On Wednesday, March 31, 2021 at 6:47:54 AM UTC+11, muta...@gmail.com wrote:

    What I want to know is how MSDOS managed to
    make @05, @08 and @09 a far call to 00C0. If
    we can see a PSP from MSDOS for a .com file
    it should have the answer. If we can disassemble
    that, anyway.

    05h BYTE CP/M CALL 5 service request (FAR CALL to absolute 000C0h)
    06h WORD CP/M compatibility--size of first segment for .COM files
    08h 2 BYTEs remainder of FAR JMP at 05h

    000000 CD20C09F 009AF0FE 1DF0DC01 F70E4B01 . ............K.

    So:

    05h = 9A
    06/07 = FEF0
    08h = 1D
    09h = F0

    So the 06/07 "segment size" of nearly 64k is basically
    just maxing out the memory available to the .com
    program.

    But how does 9A + 1D + F0 translate into a call to 00C0?

    Maybe it is relative to the load point. Let me see if I
    can extract that.

    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 Tue Mar 30 13:14:00 2021
    On Wednesday, March 31, 2021 at 6:57:41 AM UTC+11, muta...@gmail.com wrote:
    On Wednesday, March 31, 2021 at 6:47:54 AM UTC+11, muta...@gmail.com wrote:

    What I want to know is how MSDOS managed to
    make @05, @08 and @09 a far call to 00C0. If
    we can see a PSP from MSDOS for a .com file
    it should have the answer. If we can disassemble
    that, anyway.
    05h BYTE CP/M CALL 5 service request (FAR CALL to absolute 000C0h)
    06h WORD CP/M compatibility--size of first segment for .COM files
    08h 2 BYTEs remainder of FAR JMP at 05h
    000000 CD20C09F 009AF0FE 1DF0DC01 F70E4B01 . ............K.
    So:

    05h = 9A
    06/07 = FEF0
    08h = 1D
    09h = F0

    So the 06/07 "segment size" of nearly 64k is basically
    just maxing out the memory available to the .com
    program.

    But how does 9A + 1D + F0 translate into a call to 00C0?

    Maybe it is relative to the load point. Let me see if I
    can extract that.

    BFN. Paul.

    I couldn't get it to give up "cs", but I did get it to give up "ds":

    char buf[10];

    int main(void)
    {
    FILE *fq;

    printf("loaded at %lx\n", (unsigned long)(char far *)buf);

    dumppsp Abc Def Ghi
    loaded at 10242f0e

    And the PSP didn't change:
    C:\devel\bochs>hexdump psp.dat
    000000 CD20C09F 009AF0FE 1DF0DC01 F70E4B01 . ............K.

    I can't see how to convert 1D/F0 and 1024 into 00C0.

    BFN. Paul.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mutazilah@gmail.com@21:1/5 to All on Thu Apr 1 22:06:06 2021
    I tried seeing what wdis thought of those bytes, by doing this:

    dosstart.asm:

    nop
    nop
    nop
    nop
    nop

    db 09ah
    db 0f0h
    db 0feh
    db 01dh
    db 0f0h

    But somehow wdis knew those were db not instructions,
    and showed them as db (also it knows whether I coded
    "db 090h" instead of "nop").

    So I changed them all to nop then ran this:

    zap dosstart.obj 0x160 0x09a
    zap dosstart.obj 0x161 0x0f0
    zap dosstart.obj 0x162 0x0fe
    zap dosstart.obj 0x163 0x01d
    zap dosstart.obj 0x164 0x0f0

    But still wdis didn't like it:

    C:\devel\pdos\pdpclib>wdis dosstart.obj >temp.txt
    Ran out of memory in during initial reading of the object file or bad object file record


    Note that my object file was built like this:

    wasm -q -DWATCOM dosstart.asm

    BFN. Paul.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marc 'BlackJack' Rintsch@21:1/5 to muta...@gmail.com on Mon May 3 11:46:52 2021
    On Tue, 30 Mar 2021 12:57:40 -0700, muta...@gmail.com wrote:

    On Wednesday, March 31, 2021 at 6:47:54 AM UTC+11, muta...@gmail.com wrote:

    What I want to know is how MSDOS managed to
    make @05, @08 and @09 a far call to 00C0. If
    we can see a PSP from MSDOS for a .com file
    it should have the answer. If we can disassemble
    that, anyway.

    05h BYTE CP/M CALL 5 service request (FAR CALL to absolute 000C0h)
    06h WORD CP/M compatibility--size of first segment for .COM files
    08h 2 BYTEs remainder of FAR JMP at 05h

    000000 CD20C09F 009AF0FE 1DF0DC01 F70E4B01 . ............K.

    So:

    05h = 9A
    06/07 = FEF0
    08h = 1D
    09h = F0

    So the 06/07 "segment size" of nearly 64k is basically
    just maxing out the memory available to the .com
    program.

    But how does 9A + 1D + F0 translate into a call to 00C0?

    Let's fire up debug.exe and see what those bytes look like disassembled:

    ```
    debug
    -e 1000 9a f0 fe 1d f0
    -u 1000 1004
    07D7:1000 9AF0FE1DF0 CALL F01D:FEF0
    ```

    So it is not a distributed instruction but all bytes together are the (far) CALL. Does it lead to address 000c0h? Yes it does:

    ```
    hex((0xf01d << 4) + 0xfef0)
    '0x1000c0'

    hex((0xf01d << 4) + 0xfef0 & 0xfffff)
    '0xc0'
    ```

    Apparently DOS puts the size at 06h/07h and calculates a segment for 08h/09h that gives an effective address of 000c0h, taking into account that the number ”wraps” at 20 bits back to zero.

    Ciao,
    Marc 'BlackJack' Rintsch
    --
    “It is well known that a vital ingredient of success is
    not knowing that what you're attempting can't be done.”
    -- Terry Pratchett, Equal Rites

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mutazilah@gmail.com@21:1/5 to Marc 'BlackJack' Rintsch on Mon May 3 05:38:44 2021
    On Monday, May 3, 2021 at 9:46:55 PM UTC+10, Marc 'BlackJack' Rintsch wrote:

    Thanks so much for resolving that mystery!

    05h BYTE CP/M CALL 5 service request (FAR CALL to absolute 000C0h)
    06h WORD CP/M compatibility--size of first segment for .COM files
    08h 2 BYTEs remainder of FAR JMP at 05h

    It's a FAR CALL, not a FAR JMP.

    But how does 9A + 1D + F0 translate into a call to 00C0?
    Let's fire up debug.exe and see what those bytes look like disassembled:

    ```
    debug
    -e 1000 9a f0 fe 1d f0
    -u 1000 1004
    07D7:1000 9AF0FE1DF0 CALL F01D:FEF0

    Cool. I'd forgotten about debug, and forgotten how to use it too.

    So it is not a distributed instruction but all bytes together are the (far) CALL. Does it lead to address 000c0h? Yes it does:

    ```
    hex((0xf01d << 4) + 0xfef0)
    '0x1000c0'

    hex((0xf01d << 4) + 0xfef0 & 0xfffff)
    '0xc0'
    ```

    Wonderful.

    Apparently DOS puts the size at 06h/07h and calculates a segment for 08h/09h that gives an effective address of 000c0h, taking into account that the number
    ”wraps” at 20 bits back to zero.

    And that explains why so much care needed to be
    given to disable the A20 line. I was wondering who
    was coding stuff that relied on address wrap.

    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 Tue May 4 18:49:23 2021
    On Monday, May 3, 2021 at 10:38:46 PM UTC+10, muta...@gmail.com wrote:

    hex((0xf01d << 4) + 0xfef0 & 0xfffff)
    '0xc0'

    INT 30H has some documentation of the above 0xc0 too:

    http://www.ctyme.com/intr/int-30.htm

    Note that 30H = decimal 48, and 48 * 4 = 192, the
    position of INT 30H. 192 is 0xc0 as expected.

    Also the code extends to the INT 31H position:

    http://www.ctyme.com/intr/int-31.htm

    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 Fri May 7 18:11:38 2021
    On Monday, May 3, 2021 at 10:38:46 PM UTC+10, muta...@gmail.com wrote:
    On Monday, May 3, 2021 at 9:46:55 PM UTC+10, Marc 'BlackJack' Rintsch wrote:

    hex((0xf01d << 4) + 0xfef0)
    '0x1000c0'

    Apparently DOS puts the size at 06h/07h and calculates a segment for 08h/09h
    that gives an effective address of 000c0h, taking into account that the number
    ”wraps” at 20 bits back to zero.

    And that explains why so much care needed to be
    given to disable the A20 line. I was wondering who
    was coding stuff that relied on address wrap.

    Actually, the A20 line doesn't need to be disabled to
    solve this problem. What is needed is for MSDOS to
    install a JMP to 00C0 at 0x1000C0.

    BFN. Paul.

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