14

IO.SYS is an essential part of MS-DOS that contains the default MS-DOS device drivers.

IBMBIO.COM is a system file in PC-DOS. It contains the built-in device drivers.

Based on the answers of the question Why did CP/M and MS-DOS use the BIOS instead of their own drivers to access hardware? asked here, MS-DOS initially communicated with the hardware using the BIOS module. But eventually applications started generating graphical interfaces and when they tried to use BIOS graphical routines in the original IBM PC BIOS they found that the routines were so slow (they were badly written) that they had no choice but to write into video memory directly to achieve acceptable performance.

So, the question is what are the drivers in the IO.SYS file for?

Based on the argument of slow routines for video memory access the only drivers in the IO.SYS file should be for video memory access (That is, if the drivers are used at all. Writing to video memory directly would mean bypassing the OS all together).

Is that the case?

If not, what was the need for the IO.SYS or the IBMBIO.COM file to include drivers for a device when BIOS already provided functionality to access that device(other than video memory)?

There is a comment to the question linked above which claims that not all of BIOS was in ROM and a part of it might have instead been stored in the IO.SYS file. Is that accurate?

10
  • 2
    Because stuff changes, and a new driver is needed for that new interface board that uses a different chip, etc.
    – Jon Custer
    May 14 at 15:02
  • 10
    MS-DOS was available for many non-IBM PCs; Microsoft's original thinking was to become the 8086 equivalent of CP/M, and the BIOS was the only part of a PC that IBM had any intellectual property rights over. So best not to wed yourself to that.
    – Tommy
    May 14 at 15:35
  • 3
    I want to point out that the routines in the BIOS weren't necessary written poorly nor slow, but access to the BIOS ROM itself was much slower than RAM. It wasn't a code issue. The concept of 'shadow ram' was created where parts of the bios were copied in ram for faster access speed (roughly 2x).
    – Thomas
    May 15 at 21:37
  • @Thomas: MS-DOS was written years before anyone would have imagined that access to BIOS ROM would be any slower than access to ROM. In many cases, the big problem with BIOS performance is that they had to perform each and every operation from scratch. If one wants to write a line of text to the screen, one could compute the address of the start of the line, build a buffer that interleaves the character codes with the attribute values, wait for vertical retrace, and then copy 160 bytes, writing 80 characters in one frame. BIOS routines, however, were limited to writing one byte at a time...
    – supercat
    May 16 at 16:09
  • 1
    @Thomas: ...which meant that it was necessary to perform row address calculations for each individual byte to be written. Serial ports posed a different but related issue: many tasks require that serial communications be buffered, but some tasks require a larger buffer than others. Using a serial port driver (e.g. FOSSIL) makes it possible to buffer serial port data in a manner which is agnostic to the running application, and can thus allow buffers to be maintained even when switching applications.
    – supercat
    May 16 at 16:12

4 Answers 4

34

TL;DR: MS-DOS is a vendor independent DOS and IO.SYS is its abstraction layer encapsulating all machine dependent parts.

If DOS would direct access the ROM BIOS it would be specific to the IBM-PC, unable to be ported to any other machine - at least not without emulating the IBM PC-BIOS.


The Details

IO.SYS is an essential part of MS-DOS that contains the default MS-DOS device drivers.

No, not really. DOS was made before 'device drivers' were a thing. IO.SYS contains the machine dependent part of DOS while MSDOS.SYS is the device independent part. Since the IBM-PC provides a ROM-BIOS, IO.SYS is barely a wrapper for ROM routines. On other computers the ROM only contained a boot-loader (and sometimes some diagnostics), so the IO.SYS was much larger, containing all low level services DOS needs.

But eventually applications started generating graphical interfaces and when they tried to use BIOS graphical routines in the original IBM PC BIOS they found that the routines were so slow (they were badly written) that they had no choice but to write into video memory directly to achieve acceptable performance.

These are routines of the ROM-BIOS the PC provided. Also, not really slow either (*1). DOS does not provide any graphical services, nor does it direct hardware access. After all, DOS is designed as a machine independent layer to allow portable programs (*2), thus covering all hardware dependent details for the services it provides.

So, the question is what are the drivers in the IO.SYS file for?

For all services DOS provides:

  • Memory Management
  • Disk access
  • File system services
  • File handling
  • Console interface
  • Serial interface(s)
  • Printer interface (*3)
  • Date/Time

Based on the argument of slow routines for video memory access the only drivers in the IO.SYS file should be for video memory access

IO.SYS does not provide video memory access. It provides a console (text) interface (*4) and a screen handling akin to a dumb terminal (*5).

If not, what was the need for the IO.SYS or the IBMBIO.COM file to include drivers for a device when BIOS already provided functionality to access that device(other than video memory)?

ROM-BIOS is an IBM-PC specific item. MS-DOS is device independent. It was developed on a different machine than the PC (*6) and intended to run on any 8086 compatible. MS-DOS never provided any graphics interface

There is a comment to the question linked above which claims that not all of BIOS was in ROM and a part of it might have instead been stored in the IO.SYS file. Is that accurate?

Sure. it contains everything DOS needs. How it's delivered depends on each implementation - after all, it is the implementation (hardware) dependent part of MS-DOS. But its job is only that, providing what DOS needs to deliver its services. If a machine (like the IBM-PC) contains ROMs with additional services, not used by DOS, then the IO.SYS for that machine will not contain any wrapppper. Likewise, all services where there are no ROM routines (or where they should be not used), are at whole or in part in IO.SYS

The important part stays: IO.SYS is the BIOS of DOS and encapsulates all machine specific code


In addition, all of that depends on your value of 'BIOS', as BIOS is a less sharp defined term, depending on the viewpoint taken when using it. For MSDOS.SYS IO.SYS is the file providing its BIOS. It had no assumption about another layer of BIOS in ROM (or where ever). When people talk about BIOS it usually means the ROM-BIOS. and so on.

Part of the confusion about this comes from CP/M days. Here the layers were clearly named.

  • BDOS is the machine independent DOS, supplied by Digital Research, while
  • BIOS is the machine dependent part, supplied by every manufacturer.

The convention was copied (like the whole DOS) by Paterson when creating 86-DOS. But then IBM named their ROM system as well BIOS, and confusion started.

In IBM's and Microsoft's defence it may be helpful to remember that IBM did develop this without telling Microsoft anything about - they created, in good faith, what they thought might be a good abstraction layer for all capabilities of the new machine. To ease adaption of an OS. Of course, as the hardware manufacturer they were, there was no intention to make this layer machine independent.


*1 - The ROM-BIOS routines were in them self not slow. They were only very basic. For graphics they provided nothing but

  • set graphics mode
  • clear screen
  • set colour
  • set pixel
  • test pixel

And while CS-theory makes no difference between a routine drawing a 10x20 square at once, or calling the set pixel routine 200 times, real life application do notice. Anyone who has ever replaced 200 OS calls by storing 40 bytes will agree :)) The same is true for text display as well, albeit to a way lower degree.

Bottom line: PC-BIOS wasn't slow, it just did not supply any operations past the bare minimum, thus not supporting higher level optimizations.

*2 - As long as there's an 8086 compatible CPU.

*3 - Not necessary parallel.

*4 - Char-out/char-in, test for input, collect a line

*5 - I.e. a type ahead buffer and CR/LF/FF/BS handling.

*6 - SCP developed the base for MS-DOS, later 86-DOS (ala QDOS), on one of their 8086 S100 Boards.

9
  • SetPixel is still present in Win32 API and even in Unity 3D engine. And indeed, every tutorial covering it discourages its use, for the same reason of inefficiency.
    – Ruslan
    May 15 at 10:02
  • @Ruslan Of course it is, otherwise it wouldn't be a complete API. Simple operations don't loose their usability just because more complex are available. After all, if the task is just to set a single pixel (think drawing some stars), it will be way more performant than calling a box draw with size 1x1. Isn't it?
    – Raffzahn
    May 15 at 10:05
  • Well maybe, it just seems so rare a task (even the stars are not rendered as single pixels in high quality simulators), so it seems ridiculous to have such a function. I guess it might be useful when you want an abstracted access to surfaces with all formats supported by the OS, without the need to support these formats explicitly in the app.
    – Ruslan
    May 15 at 10:09
  • @Ruslan Tue. But just because a function gets less utilized doesn't make it a bad idea. Nor does the ability of modern graphics processors to make up for using overly complex functions for simple things. I'd rather see it as another proof that today's programmers share a good part of the blame for modern games running way slower than expected.
    – Raffzahn
    May 15 at 11:27
  • @Raffzahn: Not really. I would have rather had a get canvas pointer function.
    – Joshua
    May 16 at 1:34
12

First, the terminology. In the context of DOS, the term ‘BIOS’ may refer to either one or sometimes both of two things: (a) the IBM PC firmware stored in the ROM, or (b) one of the halves of the DOS kernel, stored in the file IO.SYS/IBMBIO.COM/DRBIOS.SYS/etc., in which interrupt services provided by (a) were invoked to implement disk access and abstractions like character device drivers (the other half being BDOS, the Basic Disk Operating System stored in MSDOS.SYS/IBMDOS.SYS/DRDOS.SYS/etc., which provided file system services). One can conceptualise those two things either as completely independent, or as two halves of a single entity called ‘the BIOS’, with one half stored in the ROM and the other stored on boot media. As DOS faded into irrelevance, the meaning (a) came to dominate, but a few usages of (b) persist to this day, as in the name of the FAT/NTFS data structure, the BIOS Parameter Block.

With that out of the way:

Believe it or not, MS-DOS was initially envisioned as a portable operating system; as in, portable to any other 8086-based computer. IBM PC was only one platform supported, by the IBM-branded PC DOS. Microsoft licensed MS-DOS to other computer manufacturers (OEMs) as well, and not all of them made their machines perfectly compatible with the IBM PC or AT. This is what justified the abstractions provided by DOS, like the character devices CON, AUX, PRN, and system calls like get system date; though on a PC one could access the same hardware by invoking interrupt services built into the ROM, nobody has said you were running on an IBM-compatibble system in the first place. By using those abstractions instead of PC-specific ROM services, you could, if not guarantee portability to all MS-DOS versions, then at least have an easier time trying to run your software on non-IBM-compatible DOS systems. (Ever wondered why the 8-Bit Guy always speaks of ‘MS-DOS computers’ instead of ‘PCs’? This is why.)

Those abstractions, however, were pretty limited, and came at a performance cost which at the time some applications deemed significant. And since DOS and 8086 provided no memory protection, programmers eventually started invoking ROM routines and performing port I/O directly. Soon enough, this created market pressures that made PC compatibility a necessity, and non-IBM-compatible systems died out.

In a way, you could have asked the same question about a modern OS: ‘Why should I bother with Vulkan/OpenGL if I can get access to graphics card registers directly?’ and the answer would have been largely the same. The ROM BIOS services are implementation details of the DOS device drivers in much the same way as addresses of hardware registers are implementation details of your graphics card driver. This was hardly appreciated at the time, however. The concept of a ‘stable API surface’ was a very hard-won one in computing, with gnashing of teeth continuing to this day.

1
6

In DOS architecture, DOS kernel can only use DOS drivers for all I/O. So to access disk, or to print to screen, or to read from keyboard, everything goes via DOS drivers. DOS kernel never needs to know anything about the hardware it is running on, or how to access something, as the hardware is handled by the drivers.

So to allow DOS to run on different hardware, you only need different DOS drivers that can access the different hardware, and it requires no changes to DOS kernel itself.

The IO.SYS (or IBMBIO.COM) is a file which contains the DOS device drivers that the DOS kernel can use.

The DOS drivers are the ones that can then use whatever is available on the hardware platform to perform the requested IO to peripherals. But on an IBM PC, the DOS drivers also don't need to access the physical hardware directly, as they can be accessed very easily via the BIOS, as it provides the functionality to do so. So the DOS drivers actually call the BIOS functions to write to screen or to read keyboard, or to send something to printer or modem, or to read and write disks, via the BIOS interface.

The BIOS code in ROM then does the lowest level accessing of IO ports and memory to control floppy disk controller, or to put letters to screen, or to react on received keyboard scancode data and converting that into ASCII letters which can be read from keyboard buffer handled by BIOS.

If a DOS kernel requires a feature from the DOS driver that the BIOS does not directly offer, it can be implemented in the DOS driver.

So, DOS itself does not access BIOS or hardware directly. DOS does not even know that a graphics card or a sound card exists.

It's the DOS programs such as games that are started using DOS that can do whatever they want to the hardware, such as control hardware directly or to access their features, such as communicate over Ethernet, or to initiate a Super VGA graphics mode with 24-bit colors, or to play 16-bit CD quality audio via sound card.

Another example is how ANSI terminal codes are implemented. The standard DOS console driver does not understand ANSI terminal codes, even if CGA and later video cards can be used to display characters in color. Loading ANSI.SYS to replace the default console driver makes it understand ANSI terminal codes and it can call BIOS function with the selected color, for example.

1
  • 1
    Interrestingly MSDOS.SYS includes calls to interrupt 10h functions: 0F: Get video state (check for mode 7) 00: Set video mode (mode 2, if not mode 7 previously) 05: Set video page number (selects page 0) 0E: TTY output (with hardcoded gray on black color)
    – user21618
    May 15 at 13:37
1

To view this question from the point of view of application developers...

In those times, a program could use 3 methods to generate (for example) screen output:

  • It could call a high level DOS routine.
  • It could call a low level BIOS routine.
  • It could directly access the video buffer/hardware by writing to RAM and/or manipulating hardware registers.

All of these methods had pros and cons, or in other words, reasons for existing:

  • The point of the DOS API was that it was much more expressive and powerful than the BIOS or direct access methods. DOS was nothing like today's OS'ses (with memory protection, multitasking etc.), basically it was just a very, very small set of instructions in memory, called through a common interrupt, which could be relied on to exist, by programs written for the DOS environment. This made software development much easier than directly accessing the BIOS or hardware, especially for "important" areas like, well, disks (floppy disks and later hard drives). It was not able to restrict programs from doing whatever they wanted, there was neither memory protection nor pre-emptive multitasking nor the concept of "rings" (or "privileges") and so on.
  • The BIOS was still always important since it offered routines that were available before DOS was even loaded (famously in the "BIOS setup" where internal hardware features like which disks were accessed in which order, to know which DOS to load, and so on). Its routines were also a little more close to the hardware and could "know" things about the mainboard or CPU which were maybe hidden to more abstract layers. The BIOS was, after all, baked in by the manufacturer, and was not an optional/changeable part.
  • Hardware access was regularly used by, for example, games, which either required functionality that was just not contained in DOS or BIOS, or where performance dictated to have direct control over the hardware. Remember that there was no multitasking back then (certainly no pre-emptive multitasking as the CPUs of the time had no provisions for it), so it was perfectly safe for a program to take complete control, as it could regularly assume that it was the only thing running right now, and could do whatever it wanted to/with the machine without disturbing other programs.

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.