23

I have a simple C program, and I would like to compile it targeting MS-DOS. Can this be achieved with Clang?

I would like to produce the following formats:

  1. COM executable
  2. 16-bit MZ executable
  3. 32-bit protected mode MZ executable (for use with extender)

To my understanding, the biggest problem with these formats comes from the lack of support by the linker (lld in my case). Can an alternative linker be used? What other challenges can possibly be faced?

7
  • Wouldn't linking to ELF format and using 'strip' leave the raw a raw binary aka a .COM? Otherwise, why not using GNU linker which should be able to output COM or EXE. Ofc, this only works if you're using fitting compiler producing the right DOS-Calls or at least a CLIB made for DOS.
    – Raffzahn
    Commented May 22, 2023 at 8:03
  • 9
    "Code for MS-DOS" is a broad field ranging from simple tiny-model .COM applications on 16-bit CPUs to stuff like DJGPP that assume at least a 32-bit CPU and have to link half an OS into the binary. You should definitly be more specific.
    – tofro
    Commented May 22, 2023 at 9:34
  • 4
    @tofro I specifically mentioned the 3 targets that I am trying to build for.
    – tpimh
    Commented May 22, 2023 at 12:07
  • 1
    ... which cover the complete field of view. Implementations of C compilers not specific to MSDOS might be able to cover the MSDOS use cases that assume a linear address space: The tiny COM model and the linear 32-bit model. But nothing in-between.
    – tofro
    Commented May 22, 2023 at 13:33
  • 3
    Are no actual MS-DOS compilers available?
    – dave
    Commented May 22, 2023 at 13:35

2 Answers 2

23

There’s more to it than the linker, especially if you want to support real mode. You need a DOS C library, and a compiler which can output 16-bit code. If you want to produce binaries in anything other than the tiny model, you also need a compiler that’s aware of segmentation.

As far as I’m aware, clang doesn’t have the necessary features. There are a few other possibilities:

  1. Open Watcom can produce 16-bit real-mode and 32-bit protected-mode DOS programs (if you’re interested in Open Watcom, you probably want the unofficial v2 fork)

  2. DJGPP produces 32-bit protected-mode DOS programs

  3. gcc-ia16 produces 16-bit real-mode DOS programs

For the latter two, I recommend jwt27’s build scripts which will install complete ia16 and DJGPP toolchains, including a DOS C library.

Most modern C compilers targeting DOS 8086, running on DOS 8086 (16-bit) gives a comprehensive list of DOS-targeting compilers; most of them require a DOS or Windows host.

6
  • 1
    Thank you! jwt27's toolchain seems like a very good starting point for me. From this thread I get that ia16 support in clang is very limited, nevertheless projects like this and this exist.
    – tpimh
    Commented May 22, 2023 at 12:26
  • 3
    Right, clang has an -m16 flag but what you end up with is “16-bit” binaries that are really 32-bit binaries with 32-bit prefixes emitted everywhere necessary (effectively, 32-bit real-mode programs). Commented May 22, 2023 at 12:35
  • You should be able to build small model executables without knowing about segmentation just so long as the compiler is new enough to know about .rodata (merge .data and .rodata at link time and keep .text separate).
    – Joshua
    Commented May 23, 2023 at 2:37
  • 3
    @Ruslan I think they meant programs that run in Real or Virtual 86 Mode but use 32-bit operand size, using the o32 or a32 prefixes to access 32-bit features in the 16-bit cs.
    – ecm
    Commented May 23, 2023 at 7:44
  • 2
    @Ruslan: clang -m16 is like x86 GCC's -m16 - they emit the same asm as -m32 in all(?) cases, except they slaps a .code16gcc at the top. e.g. godbolt.org/z/eecb3Ed6M shows them using the same stack offsets, because .code16gcc (unlike .code16) gets it to assemble call foo with a 66h prefix to make it push a 4-byte return address, making stack offsets the same as in 32-bit code (first arg at [esp+4]). The result ends up in a 32-bit .o so Godbolt's "binary mode" disassembles it wrong. All of this is different for gcc-ia16, which isn't just a quick & dirty hack. Commented May 23, 2023 at 15:19
3

Digital Mars claims to compile for MS-DOS. I have used it for Windows and it is quite good and generate small and fast executables.

This page might help too.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .