I have been wondering this question recently. Why does PE images have to be executable in MS-DOS? I’ve read on the topic and most of the answers I’ve seen simply explain it with compatibility. But what this compatibility actually means and targets?
If it was intended to allow a single executable both to run on DOS and Windows – what was the problem to include two executables for each OS instead?
Some of the answers I’ve read explaining it with compatibility states that if “.exe” files were purely formatted in the COFF format with the PE signature this would lead to a crash in the system when executed on DOS. But I was wondering if that’s actually true. Wasn’t the MS-DOS checking for “MZ” starting signature and if not would it have been so expensive to include such check and also perhaps another to print message similar to the DOS-stub if the image was starting with “PE” (and so it was a PE executable instead)?
Yes, MS-DOS included a check for the “MZ” signature.
I believe it (the stub) was originally included because the was a fair amount of time that Windows ran entirely as a “shell” around MS-DOS and early versions of Windows (before 3.0) were nearly unusable for running MS-DOS programs. As such, it was fairly routine for people to have Windows installed, and have Windows programs installed, but not run Windows most of the time–they’d only start up Windows when they ran the (few) particular programs they had that needed it (e.g., Excel).
I think Microsoft expected that to be the case (and were correct), and believed that under such circumstances it was probably more friendly to print out a readable error message than to just die with “not a valid executable”, or something on that order.
There was also at least some idea of having actual hybrid executables–i.e., an executable that contained a real MS-DOS program, so if you invoked it from MS-DOS, it would run a DOS program to do what you’d asked, and if you ran it from Windows, it would run a native Windows program. Note that support for this was fairly limited though–the stub program couldn’t be very large, so if you’d decided to use it this way in most cases the stub would probably have had to just spawn the program DOS program, rather than the DOS program really being contained in the stub itself.
I don’t know of that happening commercially, but I do know of another variant that was sometimes used, and worked fairly well: an MS-DOS stub program that, instead of just printing an error message and exiting, actually executed Windows with itself (i.e., this executable) on the command line, so invoking the program from a DOS command prompt still executed it under Windows.