Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to the board
Thread view  Mix view  Order
rr

Homepage E-mail

Berlin, Germany,
08.07.2026, 21:24
 

Trubo Oberon (Announce)

User DosWorld asked to make you aware of his recent "self-hosting Oberon-07 compiler for 16-bit MS-DOS real mode".

From README.MD:

===== WHY THIS EXISTS =====

There is no free, modern, actively-usable Pascal-family compiler that targets (and works) 16-bit MS-DOS real mode. Borland stopped at Turbo Pascal 7 / Borland Pascal 7 in the early '90s and never open-sourced it. FreePascal — the natural place to look — has supported 16-bit i8086 code generation since around 2014, but it was always the neglected back corner of the project: undermaintained, thin on runtime support, and never treated as a first-class target the way its 32/64-bit backends are. I had been waiting since the late 1990s for a serious free 16-bit target from the Pascal world (i8086-msdos in FreePascal was the closest anyone got, decades after the fact), and it never became something you could really build on.

So this project doesn't try to be that. It picks Wirth's other, smaller language — Oberon-07, Pascal's own successor — and builds a compiler for it from scratch, purpose-built for 16-bit DOS real mode, with no inherited 32-bit assumptions to work around. The compiler, linker, dependency scanner, archive manager, and test tools are all written in Oberon-07 and compile themselves, on the target architecture (8086 real mode), from a single checked-in bootstrap binary. Feed it its own source and it reproduces itself byte-for-byte — a full fixpoint, verified on every change.

That means:

* No hidden C runtime. SYSTEM.MOD + a small SYS.ASM are the entire foundation.
* No 32-bit protected-mode escape hatch. Real segmented 8086 memory, real 64 KB segments, real far pointers.
* A compiler that could, in principle, have been built in 1987 — but with the discipline of zero-heap-leak, byte-reproducible modern engineering practice behind it.

===== HIGHLIGHTS =====

* Self-hosting, byte-stable. toc /ENTRY=Run TOC.MOD rebuilds the whole compiler in a single process; two consecutive generations are byte-identical. See TESTS/test_selfhost.sh.
* Zero heap leaks, guaranteed. Every compile and every link reports 0 leaked paragraphs — enforced by LeakGuard instrumentation and regression tests, not just hoped for.
* All-in-one driver. toc.exe is the dep-scanner, incremental compiler, and smart linker in one binary and one command — no makefiles required to build an Oberon program.
* Real DOS constraints, handled properly. Per-module 64 KB code segments, far pointers (segment:offset), a large memory model, EMS-backed temp files, and a linker that streams instead of holding everything in RAM.
* 272-row regression manifest plus DOS-side executable and unit-test suites — every codegen change is checked against real compiled/linked/run output, not just "it compiled."
* Turbo Debugger-compatible debug info. Compile with (*$D+*), link with /G, and get a Borland TDS/TDINFO v2.08 block appended straight onto the .EXE — inspect with the included tdinfo.exe.
* Linkable with external assembly. The linker consumes standard RDOFF2 object files, so hand-written assembly modules assembled with NASM, YASM, or MSA2 (-f rdf) can be linked directly alongside Oberon-compiled .rdf/.om modules — no C shim required.

(…) Read more at https://github.com/DosWorld/toc/

---
Forum admin

Rugxulo

Homepage

Usono,
15.07.2026, 03:18

@ rr

Trubo Oberon

> User DosWorld asked to make you aware of his recent "self-hosting Oberon-07
> compiler for 16-bit MS-DOS real mode".
>
> (…) Read more at https://github.com/DosWorld/toc/

Incredible goal. Very impressive. :cool:

Version 07-07 didn't seem to like native DOS (FD or MS 7), but DOSBox-X was fine.

Having said that, I still haven't converted one tiny project of mine, but it seems quite capable (or will be very soon). In other words, I have to double-check if it's my mistakes or his.

Rugxulo

Homepage

Usono,
16.07.2026, 20:54

@ Rugxulo

Trubo Oberon

> > https://github.com/DosWorld/toc/

Trying again with Version 07-12 (under DOSBox-X 2024.07.01 SDL1):

95 line project in three modules (reads a text file, modifies it, spits out two text files).

* doesn't like old (*$MAIN+ *) pragma I used for XDS, conflict with $M memory
- I changed it to (*$M 8192,32768,32768*) since I didn't need much

* needs entry procedure (my main module had none, did it all in BEGIN END)
- I just wrapped it in PROCEDURE Main*;

* doesn't support CONST strings (yet?)
- easy to avoid

* HALT(255) needs to be SYSTEM.Halt(255)

* Files module is different
- filein := Files.Open("blah","r") needs to be IF Files.Reset(filein,"blah") THEN ... END;
- fileout := Files.Open("foo","w") needs to be Files.ReWrite(fileout,"foo");
- changed Files.WriteString + Files.WriteLn to Files.WriteLine
- no Eof(), Files.ReadLine stops on empty line (!)
-- this requires first trimming input text of such lines

* no string comparison operator = (yet?)
- for now, must use Strings.Equal (like Modula-2)

* some minor type compatibility quirks
- random fiddling to get that to work

But it does work (overall). Takes 9 secs. to run output (versus 7 secs. with Videki's Oberon-M 1.2).

Rugxulo

Homepage

Usono,
20.07.2026, 07:54

@ Rugxulo

Trubo Oberon

> Version 07-07 didn't seem to like native DOS (FD or MS 7), but
> DOSBox-X was fine.

I swear 07-12 (TOC.EXE) is giving me "Invalid Opcode" under FreeDOS, but it seems fine under MS-DOS 8. I tried running EMS Magic (TSR), but that didn't help ("not enough memory").

Laaca

Homepage

Czech republic,
21.07.2026, 23:05

@ Rugxulo

Trubo Oberon

> > Version 07-07 didn't seem to like native DOS (FD or MS 7), but
> > DOSBox-X was fine.
>
> I swear 07-12 (TOC.EXE) is giving me "Invalid Opcode" under FreeDOS,
> but it seems fine under MS-DOS 8. I tried running EMS Magic (TSR), but that
> didn't help ("not enough memory").


I tested Trubo Oberon under some environments.
Windows 98: Error message: "Not enough memory" (but MEM shows about 545Kb free)
standalone MS-DOS 7.1 (with HimemX+JEMM386): computer hangs
FreeDOS, kernel 2044 (with HimemX+JEMM385): it WORKS.

However I don't like how the compilation process is invoked.
Why "TOC CALENDAR.MOD" does not brew the CALENDAR.EXE? In place of that only some CALENDAR.OM is created.
But if that has some good reason, why it is not enough to just write something like "TOC /L CALENDAR.MOD"?

Why the hell I have to write "TOC /Entry=Run CALENDAR.MOD?"
How shall I know that the valid entry point is just Procedure Run?
It is not guarranted at all.

So i in theory I have to inspect every MOD file and have to analyze it and find some procedure which looks as a entrypoint.
It seems to be quite awful for me.

---
DOS-u-akbar!

Rugxulo

Homepage

Usono,
23.07.2026, 07:15

@ Laaca

Trubo Oberon

> I tested Trubo Oberon under some environments.
> Windows 98: Error message: "Not enough memory" (but MEM shows about 545Kb
> free)
> standalone MS-DOS 7.1 (with HimemX+JEMM386): computer hangs
> FreeDOS, kernel 2044 (with HimemX+JEMM385): it WORKS.

I tried a snapshot from today. FreeDOS (kernel 2046) still says "Invalid opcode" 9 times out of 10. I wish I knew how to "properly" debug that. For now, I stick to DOSBox-X.

> However I don't like how the compilation process is invoked.
> Why "TOC CALENDAR.MOD" does not brew the CALENDAR.EXE? In place of that
> only some CALENDAR.OM is created.

The .OM is a Tar file containing others. It's basically a linkable archive (mostly RDF).

> But if that has some good reason, why it is not enough to just write
> something like "TOC /L CALENDAR.MOD"?
>
> Why the hell I have to write "TOC /Entry=Run CALENDAR.MOD?"
> How shall I know that the valid entry point is just Procedure Run?
> It is not guarranted at all.

Oberon doesn't normally have a clearly-defined Main procedure.

XDS uses pragmas (or [obsolete] comments) to declare (*$MAIN+ *). IIRC, the Pow compiler used ProgMain*.

> So i in theory I have to inspect every MOD file and have to analyze it and
> find some procedure which looks as a entrypoint.
> It seems to be quite awful for me.

Well, presumably you know what you're trying to run! Note that TOC does handle module dependencies and linking for you.

I guess "toc module" is for standalone units that have been tested and will be shared. "toc /entry=Main myprog" is for runnable programs using those units. You know, several people can contribute to a project independently. It might even save time not recompiling everything all over again.

Having said that, "too /entry=Main myproga" always seems to rewrite MYPROGA.OM whether needed or not. (It will not, by default, compile myprogb or myprogc if their *.OM are not outdated.) You know, TPC has /c /m /b for those purposes.

N.B. He changed the way Strings.Pos() works.

Laaca

Homepage

Czech republic,
23.07.2026, 18:57

@ Rugxulo

Trubo Oberon

Do not use kernel 2046. It has some bugs. It even does not run Volkov commander 4.99. (the preious kernel 2044 has no problem with it)

---
DOS-u-akbar!

Rugxulo

Homepage

Usono,
24.07.2026, 21:34

@ Laaca

Trubo Oberon

> Do not use kernel 2046. It has some bugs. It even does not run Volkov
> commander 4.99. (the preious kernel 2044 has no problem with it)

Even using FD kernel 2044, it works like the first time and never again. And other binaries (e.g. his TASM, TLINK) seem picky too. For now, it's best to stick to DOSBox-X.

I did play with TASM and TLINK a bit. Granted, it's probably not meant to be generally useful, but a modified PSR Invaders (INV-MINI.ASM for MiniNasm, Start -> start, global start, comment out ORG 100h) will assemble with a pointless 3-byte JMP at the beginning (easily fixed with *nix dd). But I haven't worked around his lack of optimization for (CMP|SUB|ADD)word [myvar], signed byte. But it should (probably) match, if that is fixed. Seems to take 12 secs. to assemble under DOSBox-X. So that's cool.

Still an interesting project. I hope he keeps working on it.

Rugxulo

Homepage

Usono,
27.07.2026, 07:52

@ Rugxulo

Trubo Oberon

This is more just my curiosity to test rather than a bug report.

> I did play with TASM and TLINK a bit. Granted, it's probably not meant to
> be generally useful, but a modified PSR Invaders (INV-MINI.ASM for
> MiniNasm, Start -> start, global start, comment out ORG 100h) will assemble
> with a pointless 3-byte JMP at the beginning (easily fixed with *nix dd).

No, I sadly can't cut out the first three bytes, the addresses of everything else will be wrong.
It also adds a zero at the end. Still runs fine.

> But I haven't worked around his lack of optimization for (CMP|SUB|ADD)word
> [myvar], signed byte.

The three instructions that needed working around are indeed CMP, SUB, and ADD.

CMP BX,byte number ; 83h,0FBh
SUB BX,byte number ; 83h,0EBh
ADD DX,byte number ; 83h,0C2h

CMP word[myvar],byte number ; 83h,3Eh
SUB word[myvar],byte number ; 83h,2Eh
ADD word[myvar],byte number ; 83h,06h

EDIT: I also had to manually shorten jumps, but that's no big deal either.

So I just stubbed in the raw byte defines of those encodings instead (using Sed) and reassembled. Not counting the four byte added overhead, it does match exactly.

Not crucial, just fun.

Rugxulo

Homepage

Usono,
04.08.2026, 13:16

@ Rugxulo

Trubo Oberon

> > But if that has some good reason, why it is not enough to just write
> > something like "TOC /L CALENDAR.MOD"?

"toc calendar" only creates an .OM linkable library file, no linking or dependency scanning done.

> > Why the hell I have to write "TOC /Entry=Run CALENDAR.MOD?"
> > How shall I know that the valid entry point is just Procedure Run?
> > It is not guarranted at all.
>
> Oberon doesn't normally have a clearly-defined Main procedure.

Each module gets initialization via BEGIN END. In some dialects (Active? Component?) there is also CLOSE for finalization.

> Having said that, "too /entry=Main myproga" always seems to rewrite
> MYPROGA.OM whether needed or not. (It will not, by default, compile myprogb
> or myprogc if their *.OM are not outdated.)

It won't recompile dependencies unless empty or missing. Use /M for checking possibly outdated timestamps.

It still gives me errors natively, so I stick to DOSBox-X.

He did fix the VAR ARRAY OF CHAR alias problems.

TASM + TLINK /l=texe makes a tiny model .EXE which lets me "dd skip=32" to omit that part to get an exact .COM (via workarounds, as already mentioned). However, TASM reports a memory leak now (131 bytes), but it still works.

RDFLOAD dynamic loading seems very interesting, but it may only be for leaf functions, dunno.

The new Tetris example is cool (CGA!).

I did convert another two tiny projects of mine (both just read text file and write modified text file), worked fine.

Back to the board
Thread view  Mix view  Order
23491 Postings in 2218 Threads, 408 registered users (0 online)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum