In the question How did Windows ME "cripple" DOS? Ross Ridge's answer showed a section of his disassembly.

I would like to know, a) what disassembler was used and b) what adjustment or setting had to be used for the file to be disassembled.

I have tried IDA Freeware version 5 with various input sources, such as DOS EXE, DOS SYS, Binary, etc but have nor been able to obtain the desired result of a disassembly of the whole file.

If anyone can help with advice I would be most appreciative.

Thaks, Steve

  • 1
    The author of that post appears to be quite active on the Retrocomputing SE. Have you asked him directly? (If you get an answer and no one else has replied, make sure to come back and answer your own question!) – RETRAC Jul 5 at 16:15
  • Disassembly is still an art form. Especially with modern tools on old software. And DOS/IO is based on handwritten assembly. Si it might be more than just some settings. – Raffzahn Jul 5 at 17:26
  • 1
    I haven’t managed to work out how to contact contributors individually yet so I thought that I would post a question in the meantime. – Steven Jul 6 at 19:13

Windows 95 and 98 IO.SYS/WINBOOT.SYS consists of three parts: the initial loader, the payload and the device configuration manager executable.

  • The initial loader (MSLOAD) comprises the first three (Windows 95 ‘OSR0’, OSR1) or four (Windows 95 OSR2 and later) 512-byte sectors of the file; the first sector begins with the signature MZ, the second starts with the signature BJ and the last ends with the signature MS. The FAT boot sector puts the initial loader at real mode address 0070:0000, checks the first two of these signatures, then starts execution at address 0070:0200. The job of the loader is to copy boot sector variables into its data area (the first sector), relocate itself to a higher memory address, load the rest of the file starting at segment 0x70 again and then transfer control to 0070:0000.
  • The loader is immediately followed by the payload, which is the DOS kernel proper, loaded as described above. Although it is loaded into a single contiguous region of memory, it is too large to fit into a single 64 KiB real-mode segment, and so the DOS kernel is further split into regions addressed using different segment bases; discovering those will be up to you.
  • The device configuration manager (MSDCM) is a small executable whose purpose is to read the Registry and prompt the user to pick a hardware configuration if there are multiple configurations defined. As it turns out, it is no accident that IO.SYS begins with the signature MZ, just like DOS executables; the file is simultaneously a regular EXEPACK-compressed DOS executable, and the values in the MZ header at the beginning of the file allow it to be executed using interrupt 0x21 service 0x4b, which will load the third part of the file. If the real-mode kernel detects that it is booting a Windows installation, the kernel will do just that early in the boot process, before even CONFIG.SYS is processed. In interactive boot, this step can be skipped by answering N to the prompt ‘Process the system Registry [Enter=Y,Esc=N]?’; it is also controlled by the SystemReg= setting in MSDOS.SYS/WINBOOT.INI.

In Windows Me, the IO.SYS file has a similar structure, with the following differences:

  • The device configuration manager has been integrated into the payload as a subroutine; it is no longer independently executable. The MZ signature remains where it was, but the rest of the executable header is filled with dummy data.

  • The payload may be compressed; this is indicated by the signature CM. If the loader sees the payload starting with that signature, it looks for the end for the compressed stream and will then use the decompression routine located at a 16-byte-aligned offset right after the payload (also preceded by a signature CM, and some headers). If the compression signature is not found, the payload is loaded directly, like in previous versions.

    The compression format itself is a rather unremarkable LZSS-ish bitstream split into chunks. Rudolph Loew’s IO8DCOMP can decompress the file in-place, or you may see how GRUB4DOS accomplishes it. As it turns out, this compression format was only slightly altered from the one used to store the embedded boot-up splash screen (LOGO.SYS) in earlier versions of Windows.

To recap:

  • The loader can be disassembled by loading it as a raw binary at address 0070:0000 and placing the entry point at 0070:0200;
  • The payload can be disassembled by cutting it out of the file, decompressing it (if compressed), loading it starting at segment 0x70, placing the entry point at the beginning of that segment (i.e. at 0070:0000), and discovering other segments by trial and error;
  • The device configuration manager (before Millenium) can be disassembled by using an EXEPACK decompressor and disassembling the output as an MZ executable.

As it happens, the Windows Me ‘crippling’ code is located entirely within the initial loader; there is no need to decompress the file. In fact, taking a copy of IO.SYS from the Emergency Boot Disk and overwriting the code in its first four sectors with the initial loader from the hard disk’s copy of IO.SYS would accomplish the same thing as applying the patch. (In fact, a somewhat well-known patch by ‘Manifest Destiny’ goes exactly that route.)

| improve this answer | |
  • WOW! what fantastic and knowledgeable response to my question. There's a lot of information to take in and absorb. Thank you so much. I f I may I might have more questions as I'm on a steep learning curve with 80x86 code particularly relating to MS-DOS. Cheers for now. – Steven Jul 13 at 16:21
  • 1
    "The FAT boot sector puts the initial loader at real mode address 0070:0000, copies the BPB into the first loaded sector, then sets up registers and starts execution at address 0070:0200." -- This seems incorrect. The initial loader (up to 2048 bytes) is indeed loaded to 0_0700h and entered at 70h:200h, yes. But according to my sources (tested to work) the BPB is pointed to by ss:bp; the iniload uses that pointer to locate it. Part of the "first sector" is used as a buffer for the boot sector loader's message table. – ecm Jul 16 at 8:35
  • The BPB is probably copied to the first sector's variable area too, I would have to check, but (like for the message table) this copying is done by the iniload after it is being entered, not by the boot sector loader before entering the iniload. – ecm Jul 16 at 8:43
  • 1
    Yes, it seems like I misremembered where this happened. Fixed. – user3840170 Jul 16 at 9:24

I have tried IDA Freeware version 5 with various input sources, such as DOS EXE, DOS SYS, Binary, etc but have nor been able to obtain the desired result of a disassembly of the whole file.

Windows ME io.sys is compressed, so a disassembly will look like random junk. To decompress it use IO8DECOMP by Rudolph R. Loew.

| improve this answer | |
  • Thank your response. – Steven Jul 6 at 18:57
  • I know about io8dcomp, which is very good and, like you, I was given to understand that Me’s io.sys is compressed. This is not strictly true, first 2948 bytes are code. This is shown by the post referred to in my question that showed a part disassembly by Ross Ridge. – Steven Jul 6 at 19:03
  • 1
    There is a small bit of code (~1580 bytes) at the start which (I presume) includes the decompression routine, just like in other self-extracting executables. IDA should be able disassemble that part, but (as you found out) it can't disassemble the whole file. You could could get a full disassembly by first running the decompression code in a debugger and then disassembling the memory it decompressed to. IDA freeware V5 might have debugging functions that can do it, but io8dcomp decompresses the file automatically so... – Bruce Abbott Jul 6 at 23:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.