• Please review our updated Terms and Rules here

1990 - coming ready or not

kerravon

Experienced Member
Joined
Oct 31, 2021
Messages
136
Sometime around 1987 when I was about 20 years old, someone advised me to program in C if I wanted my program to last forever.

C was standardized internationally in 1990. I was there, waiting to see if ISO was going to change anything that ANSI had done, but they didn't. Finally we had a decent standard language.

I was using BBSes at the time, and I wrote BBS-related public domain (not GPL etc) software, and in 1994 I started writing my own version of MSDOS.

I have mainly focused my efforts on "what made sense in 1990" especially with the transition from the 8086 to 80386. I want to know, with the benefit of hindsight, what should have been done in 1990 and even earlier, from a programming perspective. Especially I wanted a 32-bit version of MSDOS, whatever that looked like.

27 years after I started, I am now armed with PDOS/386, a 32-bit version of MSDOS (my vision) and also a mini Windows console mode clone. You can get it from http://pdos.org

There is another version of PDOS, called PDOS-generic, which is designed to run under some other OS, so e.g. you can have an MSDOS-like environment running on an Amiga, using 68000 instructions. That is still in proof of concept stage, but you can get it from the bottom of the same place.

I have been developing some concepts, e.g. if 16-bit MSDOS software had been written without assuming segment shifts were 4 bits (and generated code typically doesn't), the segment shift could have been emulated as selectors such that you could have 16-bit software that had an address space of 512 MiB on an 80386 (maxing out the selectors in PM32), while the same executable, unkludged, could have run on an 8086 with its 1 MiB address space.

If anyone else would like to join me in making 1990 as good as it can be, please let me know!
 
Welcome to the forum, kerravon! This looks like a really interesting DOS-analogue. I’ll have to check it out and play around with it,

- Alex
 
I have been developing some concepts, e.g. if 16-bit MSDOS software had been written without assuming segment shifts were 4 bits (and generated code typically doesn't), the segment shift could have been emulated as selectors such that you could have 16-bit software that had an address space of 512 MiB on an 80386 (maxing out the selectors in PM32), while the same executable, unkludged, could have run on an 8086 with its 1 MiB address space.

I'm not following, exactly. Care to elaborate?

The benefit of 32-bit mode is that you can have (almost) arbitrarily large data structures without resorting to segment/selector voodoo. In Windows 3.1, it was a badly-kept secret that all one had to do was increment the handle of a large allocated memory block to get at successive 64K parts of it. In any case, in 16-bit mode, taking an item index into a large table involves lots of segment fu-fu.

The 64K segment limit was a principal reason that I advocated for the 68K in 1980, when we were choosing a new CPU for our system. We even wire-wrapped up 68K prototype to demonstrate the idea--successfully. Executive management however, overruled the choice and we were stuck with buggy 80186 sample steppings. Lots of wasted effort in that one.

The pitch made by the Intel guys was that our existing x80 code could be auto-converted into x86 code and run faster as a bonus. I personally blew that one out of the water with a simple, documented test case that had the folks at Intel grinding their gears for two weeks. While probably true that you could do a manual line-by-line conversion with good results, one might as well rewrite the code in an HLL, which is precisely what ended up happening.
 
I'm not following, exactly. Care to elaborate?

The benefit of 32-bit mode is that you can have (almost) arbitrarily large data structures without resorting to segment/selector voodoo.
Sure. Ideally you would simply recompile and produce 2 versions of every application, one 16-bit and one 32-bit. But I'm talking about making 16-bit as good as it can be.

The first thing to note is that there is nothing magical about a 4-bit segment shift. It's a completely arbitrary number. And as I noted, if you look at generated code, it doesn't actually hardcode the number 4. What that means, is that with an appropriate executable and loader, you can load an executable into memory on an 8086 with a 4-bit shift assumption, and into memory on an 80386 with an upto 16-bit shift assumption. At least, that's my theory - I haven't implemented it yet, but it is on my list of things to do with PDOS. What I have in mind is to max out the GDT followed by the LDT, each mapping 64k of memory, with the D bit set to select 16-bit. This will address 512 MiB of memory (you run out of selectors after that). You still have the 64k limit per segment (selector) that you get on the 8086, but depending on your application, that may not be an issue, and you can have up to 512 MiB of memory for your application.

The executable will need to be laid out so that no function crosses a 64k boundary. And in huge memory model (rarely used), the OS will need to provide the executable (at startup) what number to add to the segment whenever you cross a 64k boundary. Then with huge memory model you can have a 512 MiB array instead of 1 MiB.

Please let me know if this is still not clear.
 
Welcome to the forum, kerravon! This looks like a really interesting DOS-analogue. I’ll have to check it out and play around with it,

- Alex

Thanks Alex! I look forward to hearing any feedback you have.

I'm particularly interested in any comments on the PDOS-generic design. Do you think it is a suitable model for a theoretical 32-bit version of MSDOS? Actually I have 3 visions for what a 32-bit MSDOS should look like:

1. PDOS/386 handles INT 21H, but with 32-bit registers and quantities. I provide C wrappers to these INT calls for easy rebuilding for 16-bit vs 32-bit.

2. PDOS/386 provides Win32 console mode application support.

3. PDOS-generic takes the C wrappers I introduced in (1) above, but avoids doing the actual INT 21H in application code. If it is to be added, it can be done outside the application. In addition, a C library is provided by the OS, so that application executables can be small.

Probably 16-bit MSDOS could have used any of these 3 methods to allow application portability at the source level. Or do you think it wouldn't have been feasible in 1983 when MSDOS 2.0 came out? I'm not interested in MSDOS 1.0 which is basically just rebadged CP/M with a different API to follow.
 
I have a question, but not about the 386 version.

For your plain, 8088 PDOS, do you have a list of which INT 21 calls it supports? Does it have DOS 3 calls? Or only DOS 2? (As in, programs that say "minimum DOS version 3.3" will work.) Alternatively, do you have a list of which INT 21 calls that are not supported? And when drivers are added do they work?

I was interested before, but got lost in the source trying to see how much it supported, and therefore how much it would be worth it to just use as a daily DOS for PC XT level.

https://www.vcfed.org/forum/forum/t...t-tests-for-ms-dos-compatibility-int-21-calls
 
I think the best way of implementing the new API set would be to take a page from some of the DOS extenders and implement a subset of the NT character mode API. 32-bit functions over an INT 21h base would require the same amount of work to change existing code but the final result can't be shared with anything else.

MS had been working towards a portable API layer for DOS and whatever higher price OS MS would offer but didn't get one released until the Family API for OS/2. Some DOS extenders supported the Family API resulting in one code base that could run on DOS, DOS extender, OS/2, and NT.
 
I think the best way of implementing the new API set would be to take a page from some of the DOS extenders
There is only one that I know of that fits your description, and that is HX.

and implement a subset of the NT character mode API. 32-bit functions over an INT 21h base would require the same amount of work to change existing code but the final result can't be shared with anything else.
I do exactly that already. I actually have 2-3 types of 32-bit binaries that I support. One of them is Win32 console mode (subset).

MS had been working towards a portable API layer for DOS and whatever higher price OS MS would offer
Thanks for the info.

but didn't get one released until the Family API for OS/2. Some DOS extenders supported the Family API resulting in one code base that could run on DOS, DOS extender, OS/2, and NT.
That would be a good thing to target for 16-bit programming. Thanks for the info. Actually I have a question about Family API. If my 16-bit programs had conformed to Family API, would they still run on Windows 10 64-bit? I know that real mode programs stopped working, but I don't know about PM16 which is what the Family API was capable of. If they run, how much memory can they address?
 
I have a question, but not about the 386 version.

For your plain, 8088 PDOS, do you have a list of which INT 21 calls it supports? Does it have DOS 3 calls? Or only DOS 2? (As in, programs that say "minimum DOS version 3.3" will work.)
Yes, here:
https://sourceforge.net/p/pdos/gitcode/ci/master/tree/src/pos.h
or
https://sourceforge.net/p/pdos/gitcode/ci/master/tree/src/pos.c

There is no particular version of DOS that is supported. It is unlikely to do all of DOS 2 and it is unlikely to do nothing of DOS 3. But things were added as required, not because I was aiming for a particular DOS version to be complete. The focus is on being good enough to support my C library, PDPCLIB so that C90-compliant programs built with PDPCLIB work.

Alternatively, do you have a list of which INT 21 calls that are not supported? And when drivers are added do they work?
There is no list of unsupported calls. Actually, I just remembered this:

https://sourceforge.net/p/pdos/gitcode/ci/master/tree/refer.txt

but it's probably a bit out of date. It was created by someone else. The people who used to work on that are no longer on the project.

There is no support for drivers.

I was interested before, but got lost in the source trying to see how much it supported, and therefore how much it would be worth it to just use as a daily DOS for PC XT level.

https://www.vcfed.org/forum/forum/t...t-tests-for-ms-dos-compatibility-int-21-calls
I wouldn't advise using PDOS/86 to run existing MSDOS. Is there a problem with Freedos+HX+doslfn+PDPCLIB-msvcrt.dll? That is what I would recommend, and what I use myself when I need DOS. PDOS is for when you need public domain code for some reason.
 
The first thing to note is that there is nothing magical about a 4-bit segment shift. It's a completely arbitrary number. And as I noted, if you look at generated code, it doesn't actually hardcode the number 4.

I don't follow that--exactly what "generates" the code? Your own compiler or whose compiler?
 
The following site shows the list of Family API calls. Most are implemented as simple wrappers to the matching DOS or OS/2 calls. Character mode only and fairly limited. http://www.edm2.com/index.php/Family_API The Family API seems to have largely disappeared from use by the mid-90s. I don't know if any compiler processed them to be a full 32-bit application that could run in the 32-bit mode of 64-bit Windows.

Pharlap had extenders that used the OS/2 derived Family API and with TNT, a DOS extender using the 32-bit NT API.
 
I don't follow that--exactly what "generates" the code? Your own compiler or whose compiler?
All the C compilers. Take a look at the generated code. The number 4 or equivalent is not coded, even in large memory model. Not for normal, C90-compliant code, anyway.
 
The following site shows the list of Family API calls. Most are implemented as simple wrappers to the matching DOS or OS/2 calls. Character mode only and fairly limited. http://www.edm2.com/index.php/Family_API The Family API seems to have largely disappeared from use by the mid-90s. I don't know if any compiler processed them to be a full 32-bit application that could run in the 32-bit mode of 64-bit Windows.
Windows used to support OS/2 1.0 programs. Which was 16-bit. I know they dropped support for 16-bit real mode with 64-bit Windows, but this would have been 16-bit protected mode, which is still a thing that is supported by the x64 processor in long mode. I don't need a full 32-bit mode program, I just need a way of coding 16-bit programs that works on everything from MSDOS to 64-bit Windows, and the Family API may fit the bill.

Pharlap had extenders that used the OS/2 derived Family API and with TNT, a DOS extender using the 32-bit NT API.
Thanks for the Pharlap TNT reference. I have contacted the new owners of Pharlap to see if they can release this, but I'm not hopeful. HX has a bug in it that affects me, and I'd like to remove the kludge to work around it from PDPCLIB.
 
PDOS/386 has hit a major milestone. I have created a 40 MB hard drive image (only 9 MB populated) that is entirely public domain, and includes all the tools (linker etc) required to develop in a subset of C90 (SubC), so that if you are restricted to public domain code, you can now code in C instead of machine code. See "University Challenge" at http://pdos.org
 
All the C compilers. Take a look at the generated code. The number 4 or equivalent is not coded, even in large memory model. Not for normal, C90-compliant code, anyway.
I lost the thread back last year, but to respond to your statement, a "huge" model C program does indeed have the 4 hard-coded (well, as 12 anyway). the following program:
Code:
#include <stdio.h>
#include <string.h>

long bigarray[32767];
long *p = bigarray;

void main( void)
{
  *p = 0;
  p[30000] = 1;
}  // end of main

generates, for the second statement:

Code:
;   p[30000] = 1;
; Line 13
        *** 00001c      b8 c0 d4                mov     ax,OFFSET -11072
        *** 00001f      ba 01 00                mov     dx,OFFSET 1
        *** 000022      8b 0e 00 00             mov     cx,WORD PTR _p
        *** 000026      8b 1e 02 00             mov     bx,WORD PTR _p+2
        *** 00002a      03 c1                   add     ax,cx
        *** 00002c      83 d2 00                adc     dx,OFFSET 0
        *** 00002f      b9 00 00                mov     cx,OFFSET __AHSHIFT
        *** 000032      d3 e2                   shl     dx,cx
        *** 000034      03 d3                   add     dx,bx
        *** 000036      8b d8                   mov     bx,ax
        *** 000038      8e c2                   mov     es,dx
        *** 00003a      26 c7 07 01 00          mov     WORD PTR es:[bx],OFFSET 1
        *** 00003f      26 c7 47 02 00 00       mov     WORD PTR es:2[bx],OFFSET 0
__AHSHIFT is an absolute constant filled in by the linker and is 12.
 
Interesting project.

I prefer 1990 to stay exactly the way it was. I was only just gettng interested in computers an enjoyed the whole experience learning about them and the various operating systems available at that time, early 1990s.


It's also great to see a rekindled interest in that era of computers in general ;)
 
I lost the thread back last year, but to respond to your statement, a "huge" model C program does indeed have the 4 hard-coded (well, as 12 anyway). the following program:

__AHSHIFT is an absolute constant filled in by the linker and is 12.

I said "large", not "huge". "huge" is rare, and an exception. To solve that problem I am planning on having all huge pointer manipulations done via an OS-provided function so that it can do different segment shifts, or more practically, selector and offset changes.
 
There is only one that I know of that fits your description, and that is HX.
WDOSX also does it. More specifically, it will build an EXE with some small libs tacked on that implement the Win32 calls.
 
Back
Top