It is hard to believe there is anything left to say about the controversy over MS-DOS (including its predecessor 86-DOS) being a “CP/M lookalike”. By now it is clear that MS‑DOS replicated the CP/M API but did not copy or directly translated any of its source code.
I still think there is one piece of the puzzle that has received little attention: how much of the CP/M design beyond the API was adopted by MS-DOS? In this article, we will look at the design side of the controversy. As you will see, the most frustrating part was determining which design aspects were actually being disputed, despite years of vague accusations about copying “the internals”.
Readers of my earlier posts know I admire both Dr. Gary Kildall, the author of CP/M, and Tim Paterson, the author of 86‑DOS. It is unfortunate that two great programmers ended up on opposite sides of this argument, and I hope this post is a small step toward closing it for good.
Gary Kildall was never very specific when he claimed that MS‑DOS borrowed CP/M’s internal design. For example, in his 1982 interview with PC Magazine he said:
Basically, you know the history of PC-DOS—where it came from, and so forth. It's one of the variety of operating systems we call CP/M lookalikes. It arrived on the scene between CP/M version 1.4 and CP/M 2.2, so it has characteristics of CP/M 1.4 and extensions toward the CP/M 2.2-style file system1, but with differences because they were kind of simultaneous in design. There are subtle differences but PC-DOS is fundamentally the same as the 8-bit version of CP/M as far as the user is concerned, and also as far as the program interface. Most of the interface differences between PC-DOS and CP/M are misunderstandings of the CP/M calls by the person who wrote the original PC-DOS implementation, simple things like returning FF rather than 1, things that are of no consequence but just weren’t done specifically the same.
This is mostly a complaint about PC-DOS appropriating CP/M’s interface and behavior. The only possible reference to the internal design is his mention of the file system, which I cannot explain, as 86-DOS/MS-DOS/PC-DOS used the FAT file system, which is very different from the CP/M’s.
Toward the end of his life, Kildall wrote a memoir: Computer Connections: People, Places, and Events in the Evolution of the Personal Computer Industry in which he was apparently much less diplomatic. Only the first part of the manuscript is publicly available2, and that portion contains nothing relevant to this investigation.
However, the book They Made America: From the Steam Engine to the Search Engine: Two Centuries of Innovators contains a chapter on Gary Kildall. The author Sir Harold Evans had access to the full memoir and interviewed some of the people close to Kildall. His coverage of the MS-DOS controversy can be described, to put it mildly, one-sided but still contains several quotes from the unpublished part of the memoir that matter for our purposes.
Most of these reiterate the API argument:
The first twenty-six function calls of the API in Gates’s PC-DOS are identical to and taken directly from the CP/M proprietary documents [CP/M manuals].”
…
If you think Bill Gates invented those function calls, ask him why print string (function 9) ends with a dollar sign. He will not know.”
There is one place where Kildall actually uses the word “design”:
Paterson’s Seattle DOS was yet another one of the rip-offs of the CP/M design. The CP/M machine code was taken apart, using CP/M’s own DDT [its debugger], to determine the internal workings of CP/M in order to make a clone of CP/M’s operation.
Here Kildall speculates that Paterson reverse-engineered CP/M using the DDT debugger to “determine the internal workings of CP/M". I wish he had been more specific, but it is clear he meant something other than the published system API.
To find some more concrete and still credible accusations, we will turn to one of Digital Research’s early leaders: Tom Rolander3. In 2007, Rolander spoke to Robert Scoble in the podcast episode The rest of the story: How Bill Gates beat Gary Kildall in OS war, Part 1. Among many topics, he offered some concrete claims about MS-DOS appropriating CP/M design. Let’s start with the most direct one:
Whether Tim Paterson ever looked at a line of code or copied the code is not the issue to me. What he really did is he took it as an architecture. In fact, Gary, if anything, the supreme accomplishment he made was to make it easy to be copied, because Gary used this INT 21 (sic), this interface from an application program through to the operating system that made it transparent. It basically made it so that you couldn't see the actual organization of the data on the disk itself physically. So whether it was a CP/M file system or whether it was a FAT file system, the application program at one level couldn't see that at all, because it just used the int to open a file, read and write a file, and so forth.
At first glance, this is yet another complaint about Paterson using the copyrighted API from Digital Research. But there is an internal architecture aspect of using a single entry for an API. From Evans’ book:
What Paterson essentially did was rewrite the bottom part of the software—improving the way files were stored and adapting the program to a 16-bit machine—while copying most of the top part of Kildall’s operating system interfacing mechanisms. Even if QDOS and CP/M were 80 percent different, as Paterson has insisted, he took almost unaltered Kildall’s interrupt mechanism—the key innovation.
The “interrupt mechanism” refers to the jump instruction into the BDOS dispatch table that made CP/M adaptable to computers with various amounts of memory.
There is another controversial aspect of the “architecture” we should not forget. In the same podcast, Tom Rolander said:
I think if there's anything that I really think Gary should be remembered for, is being creator, the originator of that layering of the software, so that you were able to take the application program and run it on any piece of hardware. I mean, we all take it for granted right now. At the time that Gary wrote CP/M, people that had little accounting packages or whatever, whether it was the mini-computers or certainly the mainframes at the time, you would have a box of your software that was to run on a Data General Eclipse. You had another box of the software to run on a DEC PDP-11, but the point was that every single application program was specific to a piece of hardware, a hardware vendor, and Gary removed that layer.
Here Rolander is clearly talking about the component layout of the CP/M, specifically the division of the “kernel” into the hardware-independent BDOS and hardware-specific BIOS. This separation allowed manufacturers to easily adapt CP/M to their hardware, as long as it was based on a supported CPU.
Both of these design elements are about internal workings of CP/M. We will discuss them in some depth after we look at Tim Paterson’s side of the story.
Tim Paterson defended his work on multiple occasions. Two of his texts that we are going to quote here are The Origins of DOS published in 1994 in response to accusations raised by John Wharton, and his 2007 blog entry Is DOS a Rip-Off of CP/M?
Let’s start with the blog post. In it, Paterson openly acknowledges that he intentionally implemented the CP/M API:
What may be most surprising about the issue is that there is no significant dispute on the actual relationship between DOS and CP/M. The relationship is simply this: DOS implements the same Application Program Interface (API) as CP/M. The API is how an application program (such as a word processor) asks the operating system to perform a task, such as to read or write a disk file.
Then he reiterates that no CP/M code was copied:
There is no suggestion that I copied any CP/M code when I wrote DOS. (To this day, I have never seen any CP/M code.) And the internal workings of DOS are quite different. For example, unlike CP/M, DOS used the FAT (File Allocation Table) system for organizing disk files, which made it much faster but meant floppy disks were not interchangeable between CP/M and DOS.
I have little to add here. There are no credible claims that Paterson actually copied any CP/M code or directly translated it. There were two $100K rewards for anyone who would prove the existence of copied code, and they remain uncollected. Nowadays, when the source code for both operating systems is available, this issue can safely be considered settled4.
Paterson also addresses the part most relevant to our investigation:
One point of disagreement: In his memoirs (quoted by Evans), Kildall claims that I dissected CP/M to learn how it worked. This is not true, and it doesn’t even make sense. Since DOS worked so differently, there would have been nothing I could learn from CP/M’s internal workings to help in writing DOS.
Based on the previous quote, it seems clear that by “internal workings” Paterson referred to the file systems of the two operating systems. They are indeed completely different and there was no reason for him to debug or disassemble CP/M to learn about them5. Then again, it is not obvious that Kildall wrote about the file systems when he accused Paterson of reverse-engineering CP/M “internals”.
Now, let’s turn to The Origins of DOS. Just as in the blog post, he acknowledges the API compatibility:
So 86-DOS generally had all the same application visible elements as CP/M—the function codes, the entry point address, part of the File Control Block layout, etc. I used the 1976 CP/M Interface Guide for my description of the requirements. I also provided some similar commands from the console—such as DIR, RENAME, ERASE—although any system would have such functions, regardless of name chosen.
The function codes were necessary for API compatibility. The entry point address (assuming he means the 0005h call) is related to the “interrupt design” we mentioned earlier - more on that shortly. File Control Blocks are part of the API, and Paterson openly acknowledged DOS took them (at least partially) from CP/M, so there is no purpose discussing them here. Console commands fall more under “look and feel” than software design.
In the same text, Paterson emphasizes that his file system (80% of the code) was completely different from CP/M’s and that he never used any CP/M source code or disassembly. Near the end of the article, he writes:
BIOS (for Basic Input/Output System) was the name given to CP/M’s hardware dependent layer so that the BDOS (Basic Disk Operating System) and all applications could be hardware independent.
…
I used the term I/O System (never abbreviated) to describe the hardware-dependent layer of 86 DOS, and Microsoft even keeps this layer in a separate file on the disk (IO.SYS) from the machine-independent code (MSDOS.SYS).
My interpretation is that Paterson implicitly acknowledges that his “I/O System” (later referred to as the “MS-DOS BIOS” in Microsoft documentation) was conceptually inspired by CP/M BIOS. He does not mention it in the paragraph where he lists the similarities between the two operating systems - perhaps because it is not an “application visible element”.
Let’s have a closer look at the two design decisions that we identified as potentially controversial: the component layout (especially the BIOS) and the system call “interrupt” mechanism with a single-point entry.
Based on the CP/M 1.4 Interface Guide (which Paterson likely used as a reference) and a combination of the 86-DOS Programmer’s Manual and The MS-DOS Encyclopedia, the following diagram can be drawn to describe the major components of the operating systems:
In both cases:
Applications, including command line shells, invoke a collection of system calls to talk to the operating system kernel.
The hardware-independent part of the kernel contains the implementation of those system calls and the file system.
The hardware-dependent part of the kernel isolates the hardware components, such as console, disk, serial I/O and printers from the rest of the system. This component is customized for a particular hardware configuration, but its interface to the rest of the kernel is fixed.
In very early versions of CP/M (before 1.3), the entire kernel was a single component. Kildall later split it into the hardware-independent part BDOS, written in PL/M until CP/M 2.0, and the hardware-specific BIOS, written in assembly for each computer model.
The division between BDOS and BIOS was one of the most important reasons for the popularity of CP/M. Kildall wrote:
I designed a general interface, which I called the BIOS (BASIC I/O System) that a good programmer could change on the spot for their hardware. This little BIOS arrangement was the secret to the success of CP/M.
In his blog post The Contributions of CP/M, Tim Paterson sounds a little dismissive of the novelty of the idea:
Certainly the idea of these layers of interfaces was not new to the computer industry. For example, UNIX (like all operating systems) provided an API for application programs, and connected to the hardware with an interface to low-level device driver software. These are equivalent layers to the CP/M’s BDOS and BIOS, but much more sophisticated. So I am a bit mystified as to what is so revolutionary about CP/M’s design.
I cannot agree with Paterson here: UNIX (at least the early versions that appeared around the same time or before CP/M) did include low‑level hardware‑interfacing code, but it was compiled directly into the kernel and did not expose a standardized interface. Adding new hardware required modifying the kernel source and recompiling it. Adapting CP/M to new hardware did not require any changes to either BDOS or CCP - only the BIOS had to be re-written and recompiled6.
Paterson’s argument about non-originality of BIOS would have been more convincing if he had compared it to the RT-11 operating system, which was obviously an inspiration for CP/M. Like CP/M, RT-11 separated the hardware-dependent parts into modules called device handlers. However, BIOS is not the same as RT-11 device handlers: it is a monolithic module that contains a static jump table with 16 entries that are directly called by BDOS. Device handlers were more similar to modern device drivers - they were device-specific, reloadable and relocatable. BIOS is intentionally simpler than the device handlers - it was designed for more primitive hardware and less memory.
86-DOS was initially developed for the SCP S-100 8086 board which could more accurately be described as a collection of S-100 plug in cards than an integrated computer. It is pretty clear how the operating system would benefit from clean separation of hardware-interfacing code. Therefore, the “I/O Section” - more or less the same thing as CP/M BIOS - was adapted. Their APIs are not identical but are very similar and the process of adapting 86-DOS to new hardware was not that different from CP/M’s.
In this respect, 86-DOS did adopt the CP/M internal design, and this decision was not driven by API compatibility.
Now we will look at the “interrupt mechanism” that Paterson allegedly copied “almost unaltered”.
Advanced operating systems, including UNIX and nowadays Linux and Windows, run the kernel in a high-privilege mode. User‑mode code invokes system calls via a trap instruction, which raises a software exception and transfers control to a kernel handler. The term “interrupt” is usually associated with exceptions caused by hardware but sometimes is used for both hardware and software exceptions.
For example, UNIX on the DEC PDP-11 computer used the EMT (emulator trap) instruction to invoke system calls from user mode. That instruction caused a kernel-mode handler to run and execute a system call based on the current state of the CPU registers.
CP/M ran on the 8-bit Intel 8080 CPU which had neither privilege levels nor a trap instruction. The obvious way to implement system calls in such environment would have been to place the system routines at fixed memory addresses and call them directly from the application code. That’s for instance, how Apple DOS was implemented.
The problem was - CP/M had to run on systems with varying amounts on RAM and therefore be relocatable while still providing a fixed entry point for system calls, so that application software would not need to be recompiled for each hardware configuration.
To achieve this, Kildall introduced a “trap-like” mechanism. Instead of a software exception which did not exist on Intel 8080, he placed a fixed entry point at address 0005h. CP/M at boot time put the following instruction there:
0005: JMP FBASEFBASE value was set by the BIOS boot routines (BOOT and WBOOT, “cold” and “warm” boot respectively) to the memory address of the BDOS entry. This way the application code did not need to know the actual address or size of BDOS which could be different on different machines - it just called 0005h with the system call number in register C. Within BDOS there was a simple dispatch table that called the appropriate system call.
A diagram from CP/M 1.4 Interface Guide gives some insight into this mechanism:
Obviously, CP/M still required the memory space from 0000h to 0100h to be available for its “low storage area” which prevented some computer models from running the operating system unmodified7. But overall, the solution was effective.
I think we can all wholeheartedly agree with Rolander and Evans that this design was smart and innovative. But did Paterson actually take it “almost unaltered”?
The Intel 8086 still did not provide privilege levels, but it did introduce the INT instruction which causes a software interrupt, like the above mentioned EMT on PDP-11 computers. This made Kildall’s smart design unnecessary, and Tim Paterson took advantage of the instruction: the entry point to 86-DOS and all of its descendants is INT 21h8. There was no need to patch the jump target at address 0006h from BIOS.
There is still a “compatibility” CALL 5 mechanism that was not recommended for new code and indeed pretty much was never used in DOS programming. The implementation of that compatibility shim is very different than the original CP/M one and perhaps even too clever9.
Unsurprisingly, the INT 21h handler within DOS kernel contains a dispatch table that is equivalent to the BDOS one, but this is simply the straightforward way to implement a system‑call dispatcher; there is no indication Paterson reverse‑engineered CP/M’s table10.
In short, while there is some similarity in design, the claim that Patterson “took almost unaltered Kildall’s interrupt mechanism” is not accurate. The 8086 provided a built‑in facility for software interrupts, and Paterson used it.
Our little investigation shows that MS‑DOS did adopt CP/M’s BIOS‑style component layout, but not the internals of CP/M’s system‑call mechanism. The 8086 made Kildall’s CALL 5 indirection unnecessary, and Paterson used the processor’s built‑in interrupt instruction instead.
Not that it really matters. Software designs get reused all the time and borrowing them is far less controversial than copying source code. CP/M itself took a lot from DEC operating systems such as TOPS-10 and especially RT-11. Tracing where the design ideas originate is interesting, but it should not be used to stir up old disputes.
At this point, CP/M and MS-DOS are part of computing history, and we should be able to compare them and give credit to both of their authors.

