Bret wrote: ↑Fri 25 Mar, 2022 7:52 pm
I think disabling A20 at the beginning of the program and then enabling it shortly afterwards might be related to the LOADFIX issue. Supposedly, there are a very small number of programs that "play games" with memory address mathematics and rely/depend on the "wraparound" that happens when the memory offset goes below 0 or above FFFFh. If a program is in the first 64k of memory the program can crash. This problem is exacerbated (or maybe only occurs) when A20 is enabled since the program can accidentally access the HMA. I am not 100% certain of the details, and have not encountered the problem myself.
MS-DOS included the LOADFIX program starting with version 5, which makes sure a program doesn't load in the first 64k of memory. Apparently, the problem was common enough and important enough for MS to create a special program (LOADFIX) to address it. I THINK the reason DOS disables A20 when a program first starts is somehow related to the LOADFIX/wraparound issue, but am not sure. I can't think of any other logical reason for DOS to disable A20 when a program starts.
Yes, this is an interesting issue. Enabling A20 line can indeed make some programs not work, or even crash the entire system by clobbering memory they don't own, if these programs rely on the so called "1Mb address wraparound". One very interesting blog, www,os2museum.com , has done some great detective work in finding such programs. Basically, according to that blog, there are several well-known groups of programs relying on the wraparound: for example,
first group: programs using the CP/M-like "CALL CS:0005" method for calling DOS functions, instead of int 21h; such programs are very rare, but apparently one example is the spell-checker utility coming with some early versions of MS Word for DOS; it's also likely that some early versions of programs ported to DOS from CP/M-80 belonged to this group, but for now it seems that they all have been lost to the sands of time. It's the call to CS:0005 itself that uses the wraparound to route to the DOS function handler. Luckily, only few bytes need to be made the same between HMA and low memory to make the call work properly, even when A20 is enabled.
second group: programs built with some early versions of MS/IBM Pascal; this group includes versions of MASM and the Pascal itself, as well as possibly numerous other programs, commercial or not, made before MS/IBM Pascal faded. It's the Pascal startup code that uses the wraparound.
third group: programs built with some early versions of the EXEPACK executable-compressing utility - either standalone or built in the Microsoft LINK. And this group seems to be the most numerous, and the latest of the three. It's the initial uncompressing code that uses the wraparound.
And, of course, there might be programs which rely on the wraparound, without belonging to any of the three groups, although they must be exceptionally rare. When Microsoft created XMS and HIMEM.SYS, the potential problem with this type of software undoubtedly popped up, MS solved this incompatibility problem by requiring in the XMS specification that everyone who touches the A20 line (for using HMA or extended memory, or entering protected mode) must ensure that legacy programs (unaware of A20) run with A20 disabled.
But soon the problem was exacerbated by the appearance of the new DOS 5.0, and more specifically, its new "DOS=HIGH" mode, which moved parts of DOS itself to HMA, and consequently, forced DOS to control the A20 line. Now, in this mode, a mere call to DOS would require A20 to be enabled (so DOS would be even available). As XMS specification states, A20 switching can be rather slow, so constantly turning it on and off before and after every DOS call was out of question for performance reasons, at least. Hence, the user programs had to spent most of their time with A20 enabled (so DOS could work). But how are the aforementioned compatibility problems solved then? It seems that while developing DOS 5.0, Microsoft made sure that they have several lines of defense, some of them created specifically for the DOS=HIGH" mode.
first, when "DOS=HIGH", the aforementioned few bytes needed for correct "CALL CS:0005" execution are set up. Helps the first group.
second, LOADFIX helps the second and the third group, when it's applied manually.
third, when "DOS=HIGH", an arcane technique (exepatch) patches certain programs in memory after they're loaded, but before they're executed, to make them compatible.
fourth, DOS makes sure to start programs with A20 disabled, although later A20 gets enabled; this might help third and maybe second group, if the wraparound-using code is at the very beginning, before using any DOS functions. Perhaps this gives an answer to one of your questions.
All these multiple lines of defense obviously worked well, because DOS 5 is regarded as a highly stable and compatible version, unlike its predecessor, DOS 4.