Saying 'Hello World' in the PC-DOS 1.0 Operating System
I like spending some of my time learning more about the architecture of retro computers. That’s an interest that comes from a very early love for computers in my life and that includes video games. From time to time I read about this topics and some time ago I was interested in the IBM PC (IBM 5150), launched in 1981.
That’s a very important device in the history modern computers, as it gave origin to the x86 architecture and also the MS-DOS/PC-DOS (Disk Operating System) family of operating systems. Note that DOS is a term that can refer to other operating systems of the time, but throughout this post, DOS will refer to MS-DOS/PC-DOS.
After seeing a video of someone writing assembly code on DOS using the DEBUG.COM
application, I thought it would be a nice little exercise, really, just a classic “Hello world”, but in a very old school way.
In this post I’ll talk briefly about the architecture of these early machines and show you how to write a Hello world in machine code for the IBM PC in DOS 1.0.
The IBM PC architecture in a nutshell
Understanding the system architecture in depth is not really needed to write a “Hello World”, but the whole point of writing it in assembly (actually direct machine code) is to do it as close as possible to the hardware and experience some of the nitty gritty of these architectures.
In general the architecture of 8-bit microcomputers that era would look like in the diagram below:
Specific to our scenario:
- the CPU is an Intel 8088,
- the RAM ranges form 16 to 640 KB,
- the Video will be a Monochrome Display Adapter (MDA), although this does not specifically affect our task, and
- the Read and Write Storage will be a 360 KB floppy disk, from where the operating system is load, and where we will store our program.
Looking into the software architecture, this is how it looks like:
At start up, the CPU will fetch instructions directly from the BIOS. The BIOS, Basic Input and Output System, will load the Operating System (OS) and provide an abstraction layer for it so that it can interface with the hardware. The OS, in turn, will provide some higher level features directly to the user, like interacting with file systems and loading and running programs, as well as providing some basic reusable routines and serving as yet another abstraction layer for the programs it loads and runs.
Now, to the action
I don’t have IBM PC or DOS 1.0 disk at hand, and I assume you don’t have one either.
Luckily, it is very easy to emulate this device today. I’ll be using the excellent site PC pcjs.org (here is a direct link to the IBM PC emulator), which emulates devices directly in the browser.
PCem is also a good option to emulate it on your PC.
Before we go on, let’s check what our program is going to do. We need to do basically two things:
- Tell the operating system to show a message on the screen,
- Tell the operating system we are done.
We are going to do that with the DOS API. To consume this API we need to invoke software interrupts with the INT
instruction. That will divert the flow of the code being executed by the processor to code that belongs to the operating system, which will bring the flow back to our program once it is ready (or not, if we are done).
The main DOS API uses interrupt vector 21h
, and the function to display the message is selected by setting the register AH
to 09h
and the DX
register to the memory address where the message is located. This function considers that messages end in the $
character. To end the program, we call the interrupt after setting register AH
to 00h
.
Now, some nitty gritty about the DEBUG
version in DOS 1.0:
- it does not assemble (unlike the avengers), so we need to “code” using machine code directly - later versions can create machine code from assembly commands,
- it does not save your program to disk, unless the file already exists.
So, first, lets create the empty file HELLO.COM
with the following command:
copy con hello.com
then press CTRL+Z (you will see ^Z
on the screen) and press ENTER, you will see the message 1 File(s) copied
.
Let’s get to the fun part. We’ll start using DEBUG
, type the following command:
debug hello.com
You will be greeted by a simple -
followed by a blinking cursor.
We will add the following instructions in machine code, starting from the memory address 100h
:
Memory address (in hex) Instruction Machine code (in hex)
100 MOV AH,09 B4 09
102 MOV DX,010B BA 0B 01
105 INT 21 CD 21
107 MOV AH,00 B4 00
109 INT 21 CD 21
I have converted those instructions to machine code manually using this opcodes list: https://www.pastraiser.com/cpu/i8088/i8088_opcodes.html
Notice that on memory address 102h
we are setting the register DX
to 10Bh
, it is exactly the address that comes after our last instruction, we will place our message there later.
To enter those instructions, use the following command (remember we are still inside DEBUG
):
e 100 B4 09 BA 0B 01 CD 21 B4 00 CD 21
Now check if you did it correctly with the u 100
(unassemble) command. DEBUG
will print the instructions and you can compare it with the ones above.
Great! Now, let’s enter the message! use the command below:
e 10B "Hello world!$"
All right, we are ready to test! Use the following command:
g=100
With this, debug will run the code you have written, starting on the memory address 100h
, you should see the message Hello world! Program terminated normally.
All there is left to do now is to save our program to disk. For that, we need to write the program size to the register CX
. Use the command RCX
and enter the value 18
(it is the size of our program in bytes, 24, converted to hex), then use the command w
. This will write your program to disk. Now quit debug with the command q
and run your program by typing its name in the command prompt!
hello
Did you get your message on the screen? Thrilling, isn’t it??
I hope you enjoyed this retro “Hello world” experience!
Bonus - more on the PC-DOS / MS-DOS history
If you would like to learn more about the history behind PC-DOS and MS-DOS, I recommend the following videos:
- Why DOS Was (and Is) a Thing - YouTube - 32 minutes long
- What is IBM PC DOS 2000? - History and Unboxing - YouTube - 26 minutes long