Is there some simple method for determining if a DOS binary (.exe or .dll) is 16-bit or 32-bit?
For one, DOS doesn't know about 32 bit, it's a strict 16 bit system. Second, .DLL are not DOS executables but Windows libraries.
The Linux file command just says "executable".
Because all EXE start out as 16 bit programs, marked by the magic number "MZ" in the first two bytes. DLLs as well, as they carry a stub header of a 16 Bit EXE. This is done to enable a warning (*1) in case someone tries hard enough to start it under DOS. So for all practical purpose they are 16 bit executables.
Clarification: I want to distinguish between programs that run on any "x86" processor, and those that "require a 386", in a way that is simpler than setting up the two environments and attempting to run the program.
For real DOS programs, that is not windows programs, there is no simple to detect such, as DOS does simply not support 32 Bit. Any DOS program starts out as a 16 bit program, marked an MZ header. 32 Bit usage under DOS is custom made by the program itself and invisible to DOS. Of course, one could search for signatures of common DOS extenders, but that would still only cover part of all 32 Bit programs. Nor would it be decisive, as programs may include 32 bit support for memory access, but not being 32 bit themself.
Now, if this is about a 32 bit Windows EXE programs. Here, much like with DLL or any other file for Windows containing code, the file starts out with a PE-Header - which in turn starts out with a 16 bit EXE stub able to issue a warning (*1) if started under DOS.
Any detector looking for a (16 Bit) DOS program will find that EXE files as well as DLLs are exactly that, a DOS program.
After that stub (*2), the PE header contains several sections, foremost the COFF (Common Object File Format) chunk, which, after it's magic number, contains a machine type, telling what machine the code is intended for. Common values are
- 00000h for 16 bit
- 0014Ch for 32 Bit (Decimal 332 for 386-32)
- 08664h for 64 bit
This is followed by more fields defining other characteristics, including word size and so on. For all practical purpose a machine type of 0014Ch is the most significant indicator for 32 Bit Windows applications. This is followed by an optional PE+ header, denoting different formats for headers in 64 bit versions.
Last but not least Windows DLL work exactly like Windows EXE featuring the same PE header.
While the PE format is nowadays the most common one, there are some variations. The most common are
- New Executable (NE), introduced by Windows 1.0 / MSDOS, 16 bit
- Linear Executable (LE), for mixed 16/32 bit in Windows 9x, OS2 and some DOS extenders
- Linear Executables for OS2 2.0 (LX)
- MP used with Phar Lap DOS extender.
*1 - The well known "This program cannot be run in DOS mode" message.
*2 - Consisting of the DOS header, a pointer to the PE header and the stub itself. Ignoring the pointer is a common error of programs trying to decode a PE format.