DOS v5.0, released in 1991, introduced the concept of DOS loading “high”. That is, into the high memory area – that special 64kb area at the top of the first megabyte of memory.
As a result of this change, programs now loaded to a much lower address in memory than they did before. This change also exposed a previously unknown bug that exists in the code produced by certain versions of the Exepack utility, or Link* with the “/EXEPACK” option. The bug caused memory corruption, which usually resulted in the process hanging during start-up.
There were a number of workarounds that involved forcing an allocation of 64kb (e.g. using loadfix) to ensure that the program loaded above the 64kb block – the usual “black box” solution. By that point, there were so many ExePacked files that “please update your software” was not an option.
What made me think to solve it now? It’s my nature – I can’t leave a mystery unsolved, no matter how long it takes me.
These days DOS viruses are extinct, but DOS games live on with the help of DOSBox.
I was working on a patch for DOSBox in my spare time. The program worked in DOSBox if loadfix was run first, but it worked in all cases in real DOS. Ah, the mystery deepens.
What’s more interesting is that I saw the issue only by luck. I needed EMM386.EXE to be running and providing access to the Upper Memory Block area; I needed to load my debugger into the Upper Memory Block area; I needed to be debugging a program that was so large that it would not fit into the Upper Memory Block area along with the debugger; and, of course, I needed that program to be packed by ExePack.
It wasn’t likely, but it happened.
So, on the left is the code as it would be found on disk. On the right is the code that I saw on that day, 20 years ago, in my debugger (and shortly thereafter, I found two other variations).
Wow, quite different. What happened there?
Well, DOS went and rewrote that unpacking code for me, on-the-fly, as the file was loaded into memory.
That’s right – DOS went and “hot-patched” my code to avoid a bug. No warning, and no explanation – at the time, I didn’t have an Internet connection, but it seems likely that even if I had, it would never have occurred to me to search for an answer. Or if I did, the answer would not have been documented anywhere yet, anyway. As you can see, Windows 95 was not the first platform to implement an application compatibility layer.
The mystery is finally solved. As for DOSBox, you just have to use loadfix, but now you know why.
(*) Specifically, Link 3.x where x is 51 or larger, all 4.x, and 5.x where x is 15 or smaller.