Hacker News new | past | comments | ask | show | jobs | submit login
32-Bit DOS Applications (2022) [video] (youtube.com)
57 points by mariuz on May 11, 2023 | hide | past | favorite | 46 comments



The 32-bit registers are accessible in real mode too, it only requires a prefix to each opcode (and the same is true when using the 16-bit registers in 32- or 64-bit mode). There is also no restriction on using the FS and GS registers in real mode, they work like any other segment register.

There really is surprisingly little difference between real and protected mode, it mainly affects how segment registers are loaded. Internally, each segment register has a base and limit field that is used the same regardless of mode.

Loading a segment register in real mode sets the base to the value shifted left by 4 bits, but leaves the limit unchanged. By briefly entering protected mode and loading descriptors with a limit of 4 GiB, it would remain that way after switching back to real mode, giving access to the full address space (this is called "flat real", "unreal", or "voodoo" mode).


Oh boy, when you see those game requirements. Today gamers would change GPUs not every year or so but kind of. Those software rendering engines are true gems because the guys who worked on them literally pushed CPU and RAM to their limits and beyond. Is also a reminder of how much you can do with so little. I highly respect and admire people that grew up chewing up assembly during the 80's and 90's, wished I had that pleasure.


I worked in the qualification department for a large memory company around y2k. We ran thousands of computers with samples of all our memory so we could spot issues early. One of our best tests was running Quake in a pre-recorded speed run mode. It could run through in about a minute or so. It torched the CPU and memory and was great at seeing if a system was going to have issues. =)


I guess that must be one of the most entertaining "unit tests" that you can imagine of!


It is never too late, you can do this any time today if you want to.


When you ran a game and saw "DOS/4GW Protected Mode Run-time", you knew you were in for a good time.


Or a bad time if, like me, you only had a 286.


Interestingly the 286 had a protected mode but very few applications ever used it. There were upgrade kits with then stupid amounts of memory, like 16MB, for then astronomical prices. I wonder how often those were used for anything.


I used Rational Systems' 286 DOS extender a lot. It was a great boon to writing programs, because it would seg fault on a bad pointer access.


Information about Rational System's 286 extender seems to be limited.

What I found: Rational System were later renamed to Tenberry and their DOS/4G and DOS/4GW extenders were very popular (due to the latter being bundled with Waycom C). But they were for the 386.

The version that worked on the 286 was called DOS/16M, because it supported 16MB of address space. Someone summarises the API here [1]. I was kind of hoping someone might have uploaded the manual to archive.org, but no luck.

[1] https://groups.google.com/g/comp.sys.ibm.pc/c/zkgdj84bRkE/m/...

Apparently it was called DOS/16M and the company was later renamed to


I think I have a copy of DOS/16M in the basement somewhere.

I have a copy of Pharlap's 32 bit extender, and their 16 bit extender.

Zortech C/C++ also shipped with a nice 32 bit extender written by Joe and Doug Huffman, which was my favorite.


Not many I guess; the reason you basically required a "protected runtime" in the first place is because real mode (or a even better thing, the shiny new 386 virtual 8086 mode aka virtual real mode) was very important.

Until the 386, leaving the protected mode was either completly unsupported (I think 186) or you needed heroics involving bugs in the keyboard irc handler (I think 286). Because the OS and most "normal" applications and libraries back them being real-mode only, it means you were locked out of most of the filesystem I/O, and a program with limited filesystem I/O is a very limited program indeed.


186 didn't have protected mode :)

On the 286, the only way out of protected mode was via a CPU reset. The keyboard controller (which was a separate chip on the motherboard, an 8042 microcontroller) had a documented command to do that, and one of the first things the BIOS entry point did was to check a flag indicating that the reset was intended to exit from protected mode, if so it gave control back to the application by jumping to a pointer it provided.

Another way to reset the CPU was to cause a "triple fault" - an exception that can't be handled will try to invoke the double fault handler, when that also fails the CPU shuts down, sending a special bus cycle that external hardware would detect and trigger the reset.

This actually became the preferred method since the keyboard controller was quite slow. So slow that it gives you enough time to run an undocumented instruction which dumps the entire CPU state:

https://rep-lodsb.mataroa.blog/blog/intel-286-secrets-ice-mo...


Not bugs. IBM literally wired up the keyboard controller to trigger the CPU's reset pin on request as a workaround for getting back to real mode. But not every system has that feature. Some motherboard chipsets had an even faster method for triggering reset; it was all very non-standard.

But the most compatible way to get back to real mode on a 286 was by triggering a triple fault.


When the 286 was designed, there was the idea that no one would like to return to real mode and would happily adopt OS/2 (1.x, not the later graphical one), Xenix and similar OSes, that of course didn't happen, thus 386 had to sort that out.


I think the 286 was designed way before any of that was a consideration. It was first released in 1982, just a couple of months after the IBM PC.


From its Wikipedia article,

"The problems led to Bill Gates famously referring to the 80286 as a "brain-dead chip",[25][when?] since it was clear that the new Microsoft Windows environment would not be able to run multiple MS-DOS applications with the 286. It was arguably responsible for the split between Microsoft and IBM, since IBM insisted that OS/2, originally a joint venture between IBM and Microsoft, would run on a 286 (and in text mode).

Other operating systems that used the protected mode of the 286 were Microsoft Xenix (around 1984),[26] Coherent,[27] and Minix.[28] These were less hindered by the limitations of the 80286 protected mode because they did not aim to run MS-DOS applications or other real-mode programs. In its successor 80386 chip, Intel enhanced the protected mode to address more memory and also added the separate virtual 8086 mode, a mode within protected mode with much better MS-DOS compatibility, in order to satisfy the diverging needs of the market."


386 got trapping privileged accesses wrong, not fixed in 486. Problem is Protected Mode programs (CPL 3) executing CLI and expecting POPF to restore interrupt flag - its ignored AND doesnt trap. Afaik no x86 CPU ever fixed it completely.

Microsoft had some hacks trying to detect and patch known common problem patterns:

Getting MS-DOS games to run on Windows 95: The interrupt flag https://devblogs.microsoft.com/oldnewthing/20160411-00/?p=93...

Virtualbox switches to software tricks: https://docs.oracle.com/en/virtualization/virtualbox/6.0/adm...

"In particular, the recompiler is used when guest code disables interrupts and Oracle VM VirtualBox cannot figure out when they will be switched back on. In these situations, Oracle VM VirtualBox actually analyzes the guest code using its own disassembler."

ReactOS didnt even try. "ReactOS' NTVDM on the other hand, is a software emulator just like DOSBox": https://web.archive.org/web/20170723164052/http://community.... https://web.archive.org/web/20151216085857/http://community....

https://xem.github.io/minix86/manual/intel-x86-and-64-manual...

"When the PVI flag is set to 1, the CPL is 3, and the IOPL is less than 3, the STI and CLI instructions set and clear the VIF flag in the EFLAGS register, leaving IF unaffected. In this mode of operation, an application running in protected mode and at a CPL of 3 can inhibit interrupts in the same manner as is described in Section 20.3.2, “Class 2—Maskable Hardware Interrupt Handling in Virtual-8086 Mode Using the Virtual Interrupt Mechanism”, for a virtual-8086 mode task. When the application executes the CLI instruction, the processor clears the VIF flag. If the processor receives a maskable hardware interrupt, the processor invokes the protected-mode interrupt handler. This handler checks the state of the VIF flag in the EFLAGS register. If the VIF flag is clear (indicating that the active task does not want to have interrupts handled now), the handler sets the VIP flag in the EFLAGS image on the stack and returns to the privilege-level 3 application, which continues program execution. When the application executes a STI instruction to set the VIF flag, the processor automatically invokes the general-protection exception handler, which can then handle the pending interrupt. After handing the pending interrupt, the handler typically sets the VIF flag and clears the VIP flag in the EFLAGS image on the stack and executes a return to the application program. The next time the processor receives a maskable hardware interrupt, the processor will handle it in the normal manner for interrupts received while the processor is operating at a CPL of 3."

Pentium got Protected Mode Virtual Interrupts to half ass mitigate some of the symptoms, but doesnt fix the problem. https://www.felixcloutier.com/x86/popf:popfd:popfq

"The protected-mode virtual-interrupt feature — enabled by setting CR4.PVI — affects the CLI and STI instructions in the same manner as the virtual-8086 mode extensions. POPF, however, is not affected by CR4.PVI"


I was so happy with my Watcom C compiler after Borland. Made me feel like a pro.


We really did have everything, didn't we? I mean, when you think about it.


With 32-bit DOS extenders, VESA VGA BIOS extensions and Gravis Ultrasound, we really did have everything — except an operating system. Who needs one anyway.


Yeah. Until we wanted multitasking. Separate address spaces, shared resources, protection, eventually security. That's when the "operating system" came in. DOS was allowed to live as a virtualized task, but it wasn't the same.

I did get tambourine_man's reference, though. Nice!


Though, there’s a way we can enjoy a minimal operating system yet also have security, protection, and resource management:

https://en.m.wikipedia.org/wiki/Exokernel


Turns out they just get in the way, and in-between showing ads, sell your usage data to advertising companies.

We were better off without them.


Don't be trite in a technical conversation. While I agree that those things are bad, it adds nothing here, and besides only a minority of Operating Systems does what you say.


All it was missing was an (optional) network stack, IMHO


NDIS was available for DOS, and so was ODI (used for IPX and Netware)


Looking at the maker community doing bare metal on Arduino and ESP32, a bunch of libraries is good enough for many tasks.


We even have HxDOS, which runs Win32 applications, including console applications. For example, even a modern version of 7-zip (console version) runs perfectly on ancient DOS computers.


This is something I was able to achieve independently back in 2001 by writing a small DOS program that switched CPU into 32-bit protected mode, loaded a PE (portable executable) exe file into the memory together with DLL modules it depended upon.

The next step was to write KERNEL32.dll etc modules that were used by executable files of interest. It turned out to be a relatively easy task - only a handful of Win32 modules and their API functions were actually used by the real programs I was trying to run under the DOS. And those API implementations were mostly stubs that translated, say, I/O calls from a program into corresponding DOS calls.

Having that trick upon my sleeve, I vividly remember of being able to run 32-bit Borland C++ compiler (bcc32.exe) and linker for Windows under the raw DOS environment. Don't ask why, I did it because I could.


Okay, I won't ask why you did it, but I know I would have liked to run their IDE under DOS instead of Windows. Back in that era, Windows was very slow and clunky, and I was pretty unhappy when I "upgraded" to Borland 4.0 (IIRC) which required Windows.

Fortunately, I switched to Linux around the same time.


I had similar intentions - I was deep into OS development back then, so I wanted to have a 32-bit C/C++ compiler that would effortlessly target 80386+ CPUs.

Borland C++ was my favorite one because it supported official x86 assembly syntax (Intel). In contrast, GNU tools of the day had their own kinky x86 syntax which made me uneasy. It so happened that the Borland compiler that was able to target a 32-bit CPU, required a 32-bit CPU itself to run. DOS only provided 16-bit environment. That's why I went to those lengths of writing a custom 32-bit PE loader that would allow me to run some 32-bit Windows applications right under the DOS.

DOS was a preferable environment because it was fast and allowed booting your own OS kernels without doing a full computer reboot - you just ran an executable loader and it took control away from the DOS and gave it to your OS. And then when you "exited" your OS, instead of rebooting, it was returning back to the DOS provided that the OS kernel you were running was careful enough to preserve/restore the RAM content upon exit.

It gave a huge productivity boost back then. Later, however, I switched to Windows and was using Bochs (open-source x86 PC emulator) to effortlessly run the OS I was working on.


I never could stomach the inline Assembly syntax from GNU tools, having been educated in Borland and Microsoft compilers.

Nowadays, if I would have to write that kind of code, I would rather use intrisics or go to the trouble of using an external Assembler.


I once asked GNU people why they had such weird non-standard syntax for inline x86 assembly. Their answer was that the GNU syntax was just easier to implement in their existing toolchain of the day. Their big idea was to have a semi-universal implementation of the assembler where a particular CPU syntax was just a small, mostly declarative piece of code and configuration. The support of the canonical Intel syntax for x86 assembly would require significantly more efforts. As far as I know, the idea of a weird but universal assembly syntax came from the original Unix developed by AT&T. My take was: come on, it's just a syntax, a relatively miniscule effort required to implement the idiomatic x86 assembly support is nothing compared to pains a custom non-standard syntax may give to people.


> Don't ask why, I did it because I could.

The most amusing was when you start something and by some minor things you understood what the thing is doing something weird, in a good sense.

Later it was when a win32 app announce what it has a merit just by being not a square one.

Good times.


Now apparently just called HX, for those (like me) looking for it: https://pmwiki.xaver.me/drdoswiki/index.php?n=Main.HX-DOS


Now I just want HX running directly on UEFI! ;-)


If you have UEFI you can develop against the UEFI interface... its a more sophisticated OS than DOS on its own.


I know, but it can't run Win32 console executables nor DOS programs directly... although it uses a variant of the same EXE format as Win32 ;)


Today, "DOS/32" replaces DOS/4G and can even patch out the older runtime in binaries.

https://github.com/yetmorecode/dos32a-ng


I'm pretty sure you could do the same with PMODE/W back in the day (/W = Watcom of course). However, not 100% on the patching, my memory is rusty.

http://www.sid6581.net/pmodew/


Free but unfortunately not open source.


Aside from the software, I’d love a modern version of this laptop too. Sturdy keys with lots of travel, just the right screen size. Imagine a unibody built of this form factor, with modern SSD and RAM. The amount of battery one could fit in at that thickness would last you a week in a single charge.


Microsoft c/c++ 7.0 compiler/linker is a 32bit application. I still have it and hope to see if I can get it working under FreeDOS. The docs are great.


https://winworldpc.com/res/img/screenshots/29213296f35729c46...

Man this is good time. I wish nowadays we has such documentations.


As historical note, it was also the last MS-DOS compiler to add support for C++, among all compiler vendors.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: