Notes on Creating a 16-bit .COM binary with Turbo C
Considered using a “native” MS-DOS compiler, using a more “modern” virtual computer to compile and code to the IBM 5150 PC.
Why I abandoned this approach:
- Turbo C text editor is limited to 64KB (can’t edit .h or .c files that are larger than 64KB) – typically no single source file should be that large, but once you start adding lot of comments, it quickly adds on.
- MS-DOS limited to 8.3 filenames, a big pain
- Jumping through hoops to extract the .COM file using WinImage (or similar) and getting it copied to where you actually want to run it.
Still, here are notes on how I was able to use Turbo C to create a .COM file that worked for PC-DOS 1.0:
I used 86BOX (IBM PC emulator) to model a 486DX machine and booted to MS-DOS 6.0 (approximately the machine I would have had in 1993). These steps are as follows:
- 86BOX (IBM PC emulator)
- MS-DOS 6.0 DOWNLOAD
86BOX was configured as follows:
- Machine type: 386/486, CPU type 486DX and 50 MHz, and give it 1MB RAM
- Disk drives: give the system a couple of 1.44MB 3.5″ (high-density) disk drives, which become the A: and B: drives. Two drives is good for letting A: be the boot drive, then having an application or utility disk be the B: drive. At least until a hard drive operating system is installed.
- Hard drive: Starting simple, use a 20MB hard drive configured as 306 cylinders, 8 heads, 17 sectors.
- BIOS: This was all before WYSIWYG, USB, and auto-detecting equipment was taken for granted. So you had to tell the BIOS what equipment you had. Boot the machine (with or without a disk) but press DEL (delete) before anything starts loading. If you miss it, CTRL-ALT-DEL (reset the machine) and try again. Each BIOS software was slightly different. In this AMIBIOS, use PGUP and PGDN to change actual settings.
- Install MS-DOS: MS-DOS 6 is nice enough to format the hard drive and install itself. Earlier version, you might need to SYS the drive, or use FDISK, and FORMAT it yourself. MS-DOS 6.0 is three disk, so in 86BOX you click on the disk image and swap to each disk image as they are asked for.
- MS-DOS 6.0 DOWNLOAD
- Install a compiler: I chose Turbo C 2.01 since I believe it came out around 1989. That should mean more modern C syntax is supported. I don’t keep up with all the specific C standard language changes over the years, but there is a K&R C, C89, C99, etc. I do a full installation, since my hard drive is fully dedicated to this purpose of software development.
- Borland Turbo C 2.01 DOWNLOAD
- Borland Turbo Assembler 1.01 DOWNLOAD
Once all that is installed, then Turbo C includes a main.c example with comments on how to do a real-mode 16-bit build (they use __SMALL__ but you need to change it to __TINY__). The command line goes like this:
- tcc -c -ms main
- tasm c0 /D__TINY__ /D__NOFLOAT /t/mx;
- tasm setargv /D__TINY__ /t/mx; (this is why you need TASM)
- tlink c0 main setargv /c/m,main
- exe2bin main.exe main.com (obtain EXE2BIN from MS-DOS 3.21, or it is on PC-DOS 2.10; it was removed in later releases of MS-DOS)
- del main.exe (this is important since DOS has a priority order on EXE vs COM that have the same name – in any case, to avoid confusion, remove the one you don’t need)
NOTE: MS-DOS 2.0 source code is on github and it has an EXE2BIN.ASM, would be a great project to convert that to a regular C program.
A quick note on an alternative C compiler, the one from Intel (iC-86).
Why I abandoned this:
- It is truly a compiler only, no linker (and no editor, no IDE)
- That’s fine, it’s just you need to manually use other tools (TLINK?) to assemble and link the final code.
- In theory, the Intel compiler is very fast, compact, and “good” compiled code. Once code is compiled, it’s fairly mechanical to link it all together, which is why they can delegate to essentially any linker to get that job done.
- But good to keep this in mind, in case run into something odd that can’t be compiled, then there is an alternative C compiler to try to parse it.
Still, here are notes about the experience:
- Install a compiler (#2): An additional compiler is optional. But I believe this Intel iC-86 compiler is from 1992 and may also support more modern C syntax.
- NOTE: Apparently this is strictly an x86 optimizer compiler, as it appears no actual LINK86.EXE is included. So while I was able to compile and produce a .OBJ file, I’ll probably have to use some other existing linker. I’ll come back to this once I have an initial working solution.