LockerGnomeTech news and nostalgia for today's technology professionals
Subscribe

Search

RetroBorland C++Turbo CDOSreverse engineeringsoftware preservation

Someone Rebuilt Borland C++ 2.0's 1991 DOS Compiler From Its Own Binaries, Byte for Byte

The author, who goes by abedegno, matched 298 files against the shipped 1991 executable, and the notes list the bugs Borland left in, including a string function that peeks before an empty string.

Chris, drawn in blocky DOS screen characters, sets the last block into a rebuilt wall that matches an old wall beside it exactly.
Illustration: LockerGnome

The last step of the build is a hash comparison. Compile 298 source files inside DOS, link them, and the program checks the resulting BCC.EXE against the one Borland shipped in 1991. If one byte is off, the gate fails. When it passes, you are holding the original compiler, rebuilt from source Borland never released.

Borland never published that source. A GitHub user named abedegno worked backward from the executable instead. The project’s README calls its output “Borland’s DOS compilers, rebuilt from their own binaries,” and the recovered C and assembly rebuild each program byte for byte with the original toolchain. Borland C++ 2.0’s BCC.EXE and its standalone preprocessor, CPP.EXE, both pass.

The scale is easy to underestimate. The Borland C++ 2.0 tree holds 298 sources across 15 subsystem directories: 265 C files, some from Turbo C 2.01, plus 33 hand-written TASM assembly modules. About 3,100 functions, globals and labels got real names, and the author added about 10,000 lines of comments, so the code reads like something a person wrote on purpose.

Getting there is a matching game. The how-it-works page says a function “only matches when the compiler, its version and every switch are right,” so the author first had to pin down the exact tools (Borland C++ 2.0, TASM 2.51 and TLINK 4.0). Each file is compiled and compared function by function, and differences in the instructions point at what to change in the source. Inline assembly and byte patches are banned, so original assembly stays assembly and original C stays C.

Some code could only be written one way. Borland’s code generator merges identical tails of code, and the notes say it removes unreachable jumps before that merging, so jumps left by the merging survive. To get the same bytes back, the source has to be shaped to suit the compiler’s habits, and those spots carry match: comments.

A comparison of raw bytes has blind spots, too. It can’t see the fields a linker fills in later, so a separate step checks that external references resolve and that data layouts and names agree. The page puts its philosophy plainly: “Byte-identical output is the only test that cannot be argued with.”

Then come the findings. The project’s notes say strrchr, the run-time library’s find-the-last-matching-character function, “reads before the string”: for an empty string it looks at string[-1]. The same entry’s verdict is “harmless in practice; a port should not copy it.” Borland shipped a bug that sat quiet through the whole DOS era (whoops, one byte short).

The notes also record that nothing ever calls three functions, RTL_ATOI, RTL_STRCHR and STRING_APPEND_N, and that the parser is recursive descent with an operator-precedence expression parser, “no yacc” in the README’s words. Writing a parser by hand, in 1991, was a choice.

There is a second build, bcc20-port, which turns BCC.EXE into a native compiler and library, aimed at decompiling games built with Borland’s tools. By the README’s count, it compiles 1,874 of 1,880 test files identically to Borland’s. A separate modding build lets functions change size and files get added, with a 1,836-compile suite comparing both compilers’ output.

You can’t just download it and go. The README says you have to obtain Borland C++ 2.0 and Turbo C 2.01 yourself from WinWorld, and you need DOSBox-X, Node and Python. The recovered sources derive from Borland’s copyrighted programs, and the project says it provides them “for study and preservation, with no rights claimed.” The repo’s scripts and documentation are MIT-licensed.

Matching decompilation, the practice of rebuilding source until it compiles to identical bytes, now has a 1991 compiler on its résumé. More is likely on the way: the README says more Borland and Turbo versions are planned as further top-level directories, sharing the same scripts and build tools. Each new version should be cheaper than the last, since the matching tools carry over and only the source has to be recovered again.

The legal question stays open. “No rights claimed” is a polite way to say the author has no license from Borland’s successors, and the project says the sources derive from copyrighted programs. Whether a rights holder ever objects is not something the repo can answer.

Same hash, thirty-five years later.

More Retro

Every Retro story →