Found EMX 0.8b

While cruising archive.org, I found this CD-ROM image, “OS/2 Archive CD-ROM Walnut Creek May 1992“, which included the following zoo files:

05/05/1992 09:46 AM 144,272 EMXDEV.ZOO
05/05/1992 09:44 AM 167,809 EMXINFO.ZOO
05/05/1992 09:46 AM 101,132 EMXLIB.ZOO
05/05/1992 09:46 AM 19,266 EMXTEST.ZOO
05/05/1992 09:46 AM 586,285 GNUDEV.ZOO
05/05/1992 09:40 AM 78,575 GNUPAT.ZOO
05/05/1992 09:41 AM 138,891 GNUSRC1.ZOO
05/05/1992 09:41 AM 184,671 GNUSRC2.ZOO
05/05/1992 09:45 AM 1,044,875 GNUSRC3.ZIP
05/05/1992 09:43 AM 1,015,692 GNUSRC3.ZOO
05/05/1992 09:42 AM 505,127 GNUSRC4.ZOO
05/05/1992 09:45 AM 3,178 README.DOC

And from the readme, the release is from Feburary of 1992.  Keeping in mind the GA release of OS/2 2.0 was released in April of 1992.

EMX 0.8b INTRODUCTION 22-Feb-1992

Welcome to emx, a common environment for creating 32-bit programs for OS/2 2.0
and MS-DOS. You can use the GNU C compiler to compile programs for EMX.

Included in the emx package are:

  • emx.dll dynamic link library for OS/2 2.0
  • emx.exe DOS extender for running 32-bit programs under MS-DOS
  • emxbind.exe for creating .exe files which work both under OS/2 2.0 and
    MS-DOS
  • C header files and a nearly complete C library, including source

Additionally, the following GNU programs are available compiled and with
sources (note that these files are not part of EMX):

  • gcc, the GNU C compiler
  • gas, the GNU assembler
  • gdb, the GNU debugger
  • ld, the GNU linker
  • ar, nm, size, strip, objdump: some GNU utilities for dealing with binary
    files
  • Patched source for gcc, gas, gdb, ld, ar, nm, size, strip, objdump. You can
    compile all these programs with the files that come with emx (but you also
    need a make utility, such as NMAKE)

So this pretty much sums it up.  I went ahead and extracted the ZOOs and placed a copy on my site: emx08b_extracted.7z  Although I don’t think anyone really cares about ancient versions of GCC on OS/2.

EMX 0.9d rehosted on Win32

EMX on Win32

I know it’s utterly pointless… But yeah GCC 2.8.1 + EMX 0.9d, hosted (running) on Win32.  The main reason is that I wanted to be able use use my substantially faster Win64 machines to build stuff for OS/2.  And since I have a 4 core (+4 hyper thread), I want to be able to use make with the -j 16 flag, and say compile QuakeWorld/2 in under two seconds.

I was able to get the binutils 2.6 derived stuff to compile, along with the ‘ancient’ binutils which is notably the linker that EMX depends on.  I would imagine this ought to be able to compile PDOS, although my own simple attempt at InfoTaskForce met with spectacular failure.  While it does compile fine using an older EMX 0.8h based release.

EMX 0.9d on Windows 10 x64

EMX 0.9d on Windows 10 x64

As you can see, it can compile the dhyrstone benchmark, and run the MS-DOS version via the MS-DOS Player.

Downloads

FOOTBALL Design Document

Over at pcjs.org, this interesting prototype version of OS/2 has been unearthed.  What this means is that not only was there prototypes of a 386 aware version of OS/2 in 1986, but by 1987 the base of cruiser AKA OS/2 2.0 was already in place.  With this now somewhat made public, it really is clear that IBM’s meddling in OS/2 prevented it from being a success.

Check out the design document below:
The following text is from an email titled “3xBox Design Document” sent to the football alias on Saturday, February 28, 1987, at 5:02pm.

Overview

The goal for this research project was to demonstrate the feasability of supporting multiple virtual DOS 3.x machines on a 286DOS-based kernel running on an 386 personal computer. Each “3xBox” would have its own virtual screen, keyboard, interrupt vectors, and address space. Furthermore, well- behaved DOS 3.x applications that do text (as opposed to graphic) screen output would run in the background.

In order to acheive this goal in a reasonable amount of time, we started from the 286DOS “sizzle” kernel and made the minimum amount of changes necessary, both in code and fundamental design. The resulting DOS will be referred to as “386DOS” in this paper.

386DOS provides up to four 3xBoxes, depending upon the available RAM. More 3xBoxes could be supported if a slight change is made to the method of allocating page tables.

Well-behaved DOS 3.x applications (i.e., MS-Multiplan, MS-Word, Lotus 1-2-3) can run in the background, multi-tasking against one another and against the foreground screen group. Lotus 1-2-3 (version 2.01) passes its floppy-based copy protection when in the foreground.

It should be noted that 386DOS, while functional, is not an optimal design/implementation of multiple 3xBoxes. In particular, interrupt management, the device driver model, and the existence of V86-mode kernel code should be modified before 386DOS is made a commercial product.

Unless stated otherwise, most of the concepts extant in 286DOS apply to 386DOS.

V86 Mode and the 386

The 386 CPU has three distinct execution modes: REAL, PROT, and V86. REAL
and PROT modes are largely compatible with the corresponding modes of an 286.
V86 modes is exactly the same as RING 3 PROT mode, with the following
differences:

o Memory Address Hierarchy
A 386 has three levels of memory addresses:
– Virtual (Intel refers to this as Logical)
This is either the selector:offset or segment:offset address used by unprivledged machine language code.
– Linear
This is the 32-bit address arrived at either via a GDT/LDT
selector lookup, or via the 8086-compatible (seg << 4 + offset).
– Physical
This is the 32-bit address arrived at by pushing a linear address
through the paging mechanism. This is the address that the CPU
sends out on the bus to select physical memory.

When in V86 mode, the CPU performs the 8086-compatible computation.

o I/O instructions are NOT IOPL-sensitive
Trapping of I/O is done using the IO Permission Map.

o All instructions which modify or expose the Interrupt Flag ARE IOPL-
sensitive.
This allows the OS to simulate the Interrupt Flag, if desired.

V86 IRETD Frame

When any interrupt, trap, exception, or fault occurs in V86 mode, the CPU
switches to PROT mode and switches to the TSS Ring 0 Stack and builds the
following stack frame:

[[code]]czoyNDA6XCIKICAgICAgICAgICAgKDApIChvbGQgR1MpCiAgICAgICAgICAgICgwKSAob2xkIEZTKQogICAgICAgICAgICAoMCkgKG97WyYqJl19bGQgRFMpCiAgICAgICAgICAgICgwKSAob2xkIEVTKQogICAgICAgICAgICAoMCkgKG9sZCBTUykKICAgICAgICAgICAgICAgKG9sZHtbJiomXX0gRVNQKQogICAgICAgICAgICAob2xkIEVGTEFHUykKICAgICAgICAgICAgKDApIChvbGQgQ1MpCiAgICAgICAgICAgICAgIChvbGQge1smKiZdfUVJUCkgJmx0Oy0gKFNTOlNQKQpcIjt7WyYqJl19[[/code]]

CPU Mode Determination

A new implementation of the WHATMODE macro was written in order to distinguish
between the three CPU modes: REAL, PROT, and V86. REAL mode is indicated by
a 0 PE bit in CR0 (a.k.a. MSW on a 286). If the PE bit is 1, then the mode
may be either PROT or V86. These two modes may be distinguished by attempting
to change the IOPL bits in the FLAGS word. At Ring 0 in PROT mode (the only
place WHATMODE is used), the IOPL may be changed. In V86 mode, IOPL cannot
be changed. So, we change IOPL and then check to see if it changed. If so,
PROT mode, else V86 mode.

CPU Mode Switching

The 286DOS kernel relies extensively on switching inbetween REAL and PROT.
This functionality is provided by the RealMode and ProtMode routines.
In 386DOS, RealMode is no longer needed. As soon as we switch to PROT mode
during SysInit, the CPU only uses PROT and V86 modes.

Two new routines, ProtToV86 and V86ToProt, that are analogous to RealMode and
ProtMode. ProtToV86 is quite straightforward. We build a V86 IRETD frame
on the stack with the VM bit set in the EFLAGS image. We set the SS:SP
image to be equivalent to the stack just above the V86 IRETD frame, and
set the CS:IP image to instruction following an IRETD. Then, we issue the
IRETD and the CPU continues processing following the IRETD and in V86 mode.

V86ToProt is a bit trickier. The only way to get out of V86 mode is to
trap or fault or issue a software interrupt. We chose to use a software
interrupt, 30h, which we call the V86 Services interrupt. The INT 30h entry
in the IDT is a ring 3 interrupt gate, so issuing an INT 30 from V86 mode
causes a V86 IRETD frame to be built on the TSS Ring 0 stack and control
transfers to the INT 30h vector. The handler verifies that the INT 30h
was issued by the V86ToProt routine (checks CS:IP on the stack). If not,
the interrupt is reflected back to the requesting 3xBox (See Interrupt
Reflection). If it was V86ToProt, we clean off the stack frame and return to
the caller. NOTE: V86 Services is also used for completing the 386 LOADALL
used by PhysToVirt to map “high” memory in “REAL” mode.

Stack Switching

In order to maintain the 286DOS mode switch and stack switch semantics
when V86 mode is used, we have a new stack (the V86 Stack) in the 3xBox PTDA.

286DOS Modes and Stacks

The RealMode and ProtMode procedures in 286DOS are the only ways to switch
the CPU execution mode. These routines both maintain SS:SP, allowing
RealMode and ProtMode to be reentrant. The TSS Ring 0 stack is always the
current TCB stack in the current PTDA. The only other stacks in the system
are the Interrupt Stack and user stack(s).

386DOS Modes and Stacks

In 386DOS, any interrupt or exception while in V86 mode causes a switch to
PROT mode and the TSS Ring 0 Stack. So we have a new way to mode switch with
an incompatible stack semantic. We had to fix this mode switch to make it
compatible with 286DOS.

Observation

In V86 mode, the current stack must not be the TSS Ring 0 Stack. The CPU
only leaves V86 mode via an interrupt/exception, which causes a stack switch
to the TSS Ring 0 Stack. If the current stack was the same as the TSS Ring 0
Stack, then the stack might get corrupted. In 286DOS, the Ring 0 Stack is
the PTDA. Since we run on this stack in V86 mode, we need a new Ring 0 stack
when a 3xBox is running.

Approach

1) When a PMBox is running, the TSS Ring 0 Stack is a PTDA TCB stack.
+ This is consistent with the 286DOS model.

2) When a 3xBox is running, the TSS Ring 0 Stack is the “V86 Stack”.
+ The V86 Stack is allocated in the 3xBox PTDA.
+ If the cause of the mode switch can be handled without enabling
interrupts (e.g., interrupt reflection, IN/OUT trapping), we stay
on the V86 stack.
+ Otherwise, copy the V86 IRETD frame to the previous stack and
switch back to the previous stack.

Details

1) Leaving V86 mode
a. V86ToProt (analog of ProtMode)
+ Issue special V86ToProt software interrupt. If the interrupt
gate is DPL=3 (and it must be a 386 Interrupt Gate), then the 386
switches to Ring 0 (and the TSS Ring 0 stack) and transfers
control to the handler.
+ To ensure that 3xBox apps don’t use this feature, the interrupt
handler checks that CS=DosGroup and IP is in the correct range.
If not, then the interrupt is reflected (see below).
+ To make V86ToProt compatible with ProtMode, the interrupt handler
switches to the old stack (we get SS:ESP from TSS Ring 0 stack,
which is where we are running).
+ Finally, V86ToProt restores saved registers and flags from the
stack and returns to caller.

b. Software interrupt
+ GP-Fault handler reflects to 3xBox IVT handler in V86 mode.
o Add IRET frame on old stack, taking IP, CS, FLAGS from
TSS Ring 0 Stack.
o Look up handler in 3xBox IVT.
o Edit TSS Ring 0 Stack EIP and CS to point to IVT handler.
o IRETD
+ IVT interrupt handler IRET uses IRET frame we built on old stack.

c. Hardware interrupt
+ To make this operation compatible with 286Dos, the interrupt
handler copies the V86 stack from the TSS Ring 0 stack to
the old stack, then switches stacks to the newly modified old
stack. This allows the Interupt Manager to do an IRETD to
get back to the correct mode.

d. Exception
+ Remain on V86 stack, process exception, and IRETD.

2) Entering V86 mode
a. ProtToV86
+ Build V86 IRETD frame on current stack and IRETD.
b. LinToVirtDM_HANDLE
+ Execute 386 LOADALL with VM bit set in EFLAGS image in loadall
buffer.

Interrupt Management

All software interrupts, hardware interrupts, and CPU traps and exceptions
are vectored through a common IDT, regardless of whether the CPU is in PROT
or V86 mode.

NOTE: Background 3xBoxes get no hardware interrupts. In the commercial 386DOS,
this restriction can be relaxed so that interrupts, other than for the
keyboard and mouse (since those are implicitly for the foreground box),
can be given to background 3xBoxes.

Passing Hardware Interrupts to the Foreground 3xBox

In the interrupt manager:

IF a 3xBox is foreground -AND-
the current mapped 3xBox is background
THEN
MapIn foreground 3xBox;
Dispatch interrupt;

And to make things more interesting, from the later version of FOOTBALL, oddly enough version 4:

OS/2 FOOTBALL Boot Disk (v4.41.00)

This disk contained an updated version of OS/2 FOOTBALL Boot Disk (v4.41.00). It was built in December 1987, using final OS/2 1.0 sources merged with assorted FOOTBALL changes, and although it was originally assigned version number 1.3, this version of OS/2 would ultimately become 2.0.

It crashes on an 80286, jumping to invalid code immediately after performing a processor check. On an 80386, the following version banner is displayed:

[[code]]czoxNzU6XCJPcGVyYXRpbmcgU3lzdGVtLzIgIFZlcnNpb24gMS4zMAooQykgQ29weXJpZ2h0IE1pY3Jvc29mdCBDb3JwLiAxOTgxLCB7WyYqJl19MTk4NywgMTk4OC4KKEMpIENvcHlyaWdodCBJQk0gQ29ycC4gMTk4MSwgMTk4Ny4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KCkludGVybntbJiomXX1hbCByZXZpc2lvbiA0LjQxLjAwLCAxMi8wMi84NwpcIjt7WyYqJl19[[/code]]

The numbering of revisions must have been, um, revised, because despite the lower revision (4.41.00 vs. 7.68.17), it is newer than the 7.68.17 prototype. This is confirmed by the boot message (12/02/87), the file dates (12-23-87) and the higher version number (1.3).

Powered by OS/2

I think I’m the last one on the internet crazy enough to try this, but here goes…

powered by os2

So the VPS where I run my BBS came up, and they wanted more money.  And honestly, running a BBS from 1994 in 2015 just doesn’t cut it when it comes to system resources, and I’ve been looking for an excuse to bring it ‘home’ so I moved it inside.  The cool thing though is that I don’t have to use usermode nat anymore, so I can use FTP to shuffle files around, which is a nice thing to have.  I may have to investigate if there is an rsync as well, as reading files directly from the VM would be a bonus.  It’d be cool to read things like Tradewars scores, last user activity and whatnot.

While I was setting up HTTP, and repointing to a new address, I figured I’d go all in on OS/2, and load up Apache on OS/2 2.0, and let it host it’s own website.

Hosting on OS/2

Hosting on OS/2

The ‘hard’ thing to fight was updating the mime.types, and dealing with CR/LF issues moving my old pages from Linux to OS/2.  Luckily my C: drive is already HPFS, so I have long filenames already.

I guess the next thing to do is setup a RAM disk, and virtual servers so I can move Team OS/2 onto OS/2.  Someone named Kohtaro Shinya just snagged the original Team OS/2 page.  At least it’s not some forex scam, but now it’s tourism for Osaka.

But yes, my crappy BBS still lives, I think it’s moved hosts at least 7 times since 2011.

OS/2 and KVM don’t mix.

After I was able to run OS/2 2.11 on VMware with PCI drivers, I thought I’d try KVM.

KVM internal error. Suberror: 1 emulation failure EAX=00000720 EBX=00000050 ECX=fee10050 EDX=00400780 ESI=d02f004c EDI=ff3f0000 EBP=00000d88 ESP=00000d72 EIP=00006725 EFL=00013202 [-------] CPL=3 II=0 A20=1 SMM=0 HLT=0 ES =0047 00080000 00000f9f 0010f300 DPL=3 DS16 [-WA] CS =d517 1aa20000 0000672d 0000ff00 DPL=3 CS16 [CRA] SS =0017 00020000 00000fff 0000f300 DPL=3 DS16 [-WA] DS =bfcf 17f90000 0000033d 0000f300 DPL=3 DS16 [-WA] FS =0000 00000000 ffffffff 00000000 GS =bfff 17ff0000 00000fff 0000f300 DPL=3 DS16 [-WA] LDT=0028 7be57000 0000ffff 00008200 DPL=0 LDT TR =0010 ffe1f6e7 00000067 00008b00 DPL=0 TSS32-busy GDT=     7c7e5000 00001fff IDT=     ffe201e0 000003ff CR0=8001001b CR2=00080000 CR3=001b3000 CR4=00000000 DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 DR6=00000000ffff0ff0 DR7=0000000000000400 EFER=0000000000000000 Code=ca 76 0f 8b ca eb 0b 03 7e 22 8b ca 3b cb 76 02 8b cb 2b d1 <f3> ab 0b d2 75 ed 2b c0 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

OS/2 2.11 crashing on KVM


No go.  Also Qemu 2.1.2 on Linux didn’t fare much better.  Must be something about HPFS and raw disk images.  The funny thing is that even once a disk became corrupted, I quit Qemu, restore the disk, and start again, and it’s still behaving like it’s corrupt.  Qemu 0.15.X has been the most stable branch I’ve found to run OS/2, but it’s so obsolete now.

BBS down. again.

LOL Maybe I’m just cursed at this point.

This is an email to follow up on the update on our social network accounts (twitter and facebook: @hosthatch) that we are investigating an issue on SSDNode15. Instead of fixing this server, we have chose to restore from 1 hour old backups to some of our other stable servers running for 3+ months with no downtimes. SSDNode15 has unfortunately had very bad luck and has failed 3 times in the past month, which is why we are going to take it out of production, replace most of the parts, burn test it and then put it back into production.

Although I had time to check the log, it turns out I had over 250 users, but a good 150 of them couldn’t figure out the synchronet mandatory send a letter to sysop thing so they abandoned the process.

I don’t know why, but I still liked the idea of being the last OS/2 sysop on the planet, but this year has been ridiculous.  Now that I have it running on VMWare, maybe it’s time I just buy a UPS, and run it on ESX from now on.  But at the same time, I did like the idea of it running in a datacentre.

OS/2 2.0 on VMware Player

Well this has been driving me crazy for the longest time.  The ‘latest’ drivers for the AMD Pcnet card I can find for VMware is 4.08.  They load up on VMware like everything is normal but it doesn’t work.  But now I have my super awesome GNS3 test bed, so I can take a deeper look.

NDIS2 Driver for OS2 MSLANMAN
December 2000
NDIS2 driver for OS2 – Readme
Version 4.08

Changes made in this version 4.08:
The receive buffer size has been increased from 1518 to 1536.
Changes made in this version 4.07:
Slow network performance when using Interrupt Sharing has been fixed.
After heavy stress for a few hours, a drastic reduction in data transmission was observed. This problem has now been fixed.
The maximum number of Transmit Buffers that the driver can support has now been increased from 16 to 32.

I’m using OS/2 2.0 with the XR06100 fix, along with TCP/IP 2.0 with UN64092 fix and MPLS WR06000 (I never did find a fixpack for this).

I installed AMD’s MSLANMAN OS2 driver, as MPLS picks this up, and lets me use the nice UI to add in the network card.  But it never seemed to matter, as the blasted thing didn’t work.

MPLS

MPLS all configured

Which is a pretty simple configuration.  It’s just a simple lan adapter with TCP/IP.  I’m not even going to try to do anything fancy, like trying to get the wildly incompatible NetWare client working

ARP

ARP

Now much to my surprise the machine does send gratuitous arp on the wire, to assert it’s ip address.  Well that is interesting.

Pinging the gateway

Pinging the gateway

And as you can see, there is no ARP reply. Very strange.

Broken Arp

Broken Arp

So messing around with every possible option, I tried changing “PermaNet Server feature” in the network card settings.

fix

Set PermaNet Server feature to TRUE

And much to my surprise, it worked!

 

h

Yay!

So yeah, this is pretty awesome!  Now I just have to decide what to do with my BBS, maybe bring it home, and run it on ESXi.

Talking to the SIMH Vax through GNS3

Talking to the SIMH Vax through GNS3

As a strange update, I upgraded from OS/2 2.0 to 2.11 and then applied XR_B108 update to OS/2 2.11, and amazingly the value psfeature in protocol.ini had to be set to false.  Obviously this later kernel in the XR06200 fixpack better supports PCI hooks.

I updated OS/2 because things like Qbasic were able to hang the system.  I even tried the MS-DOS version of Qbasic thinking that somehow it was trying some weird hook to the BIOS for ROMBASIC, but that wasn’t the case, as both Qbasic from MS-DOS 5.0 and 6.22 hung the system by hitting alt+f.  So with the upgrade in place it seems to be working fine now.

A sneak peak at Microsoft OS/2 2.0

No really!  It’s an article from PC Magazine, 29th of May, 1990.  And it’s authored by Ray Duncan, before the infamous split.

Of course the thing that stands out from the screen shot is that OS/2 2.0 looks more like OS/2 1.2.  And of course it’s ability to run tow MS-DOS VDM’s in a window at the same time!

Flight Simulator, in a Window!

Flight Simulator, in a Window!

Although this was a feat that Windows/386 was capable of doing, going far back as far as 1987.

Windows 2.1/386 running Flight simulator 3.0 in a window

Windows 2.1/386 running Flight simulator 3.0 in a window

But as you can see, OS/2 did it better.  Windows/386 was unable to run EGA graphics in a window, instead I was forced to run Flight simulator 3 in CGA mode.  While the OS/2 2.0 beta could give over 620kb to a MS-DOS session, Windows/386 could only give me 550kb.

And when it came time to ship, well here is IBM OS/2 2.00 0xr6100 running Flight simulator 3.0 in a window, and showing a MS-DOS box with about 600kb free.

IBM OS/2 running Flight Simulator 3.0

IBM OS/2 running Flight Simulator 3.0

The real shame is that MS OS/2 2.0 was looking really promising in 1990, but thanks to the split the world didn’t get to try it out until 1992.

The article is a good read to get an idea of the state of development back in 1990.  And of course all of PC Magaine’s 1990’s magazines are up on google books.  I’ve managed to find 2/3rd of the Beta since I started looking (from 1990… been looking a long long time), and I have reviewed the SDK/toolkit earlier, and here.

PC Magazine, May 29th 1990

PC Magazine, May 29th 1990 Pages 387-388

PC Magazine, May 29th 1990

PC Magazine, May 29th 1990 Pages 389

Power Programming part 2

Power Programming part 2

Power Programming Part II, contd.

Power Programming Part 2, contd.

Power Programming pt3 1-2

Power Programming pt3 1-2

Power Programming pt3 3-4

Power Programming pt3 3-4

Power Programming pt3 5

Power Programming pt3 5

Power Programming pt4 1-2

Power Programming pt4 1-2

Power Programming pt4 3-4

Power Programming pt4 3-4

Microsoft OS/2 2.0 SDK Beta

Something interesting crossed my desk today.  The much fabled Microsoft OS/2 2.0 SDK beta.

OS/2 2.0 SDK in action

OS/2 2.0 SDK in action

Sadly this does *NOT* include the operating system, just the C compiler and the SDK bits.  As you can see, the C compiler is version 1.00.075, a full year+ before the WindowsNT 3.1 1991 pre-release which had 6.00.080.  An interesting thing is that the C compiler can be run from 16bit OS/2.  Unfortunately, the EXE’s produced by the SDK will not run on a production OS/2 system.  The fault lies with the linker & resource compiler.  However swapping those two components out for production versions seems to remedy this and produce working executables.  The only SDK examples that don’t work correctly involve the creation of DLL’s.  I’m sure it is again related to either the linker again, or from some gem I saw in the SDK saying you should always link by ordinal, and never by name.  Apparently a bunch of function calls were going to change name from OS/2 1.2 to 2.0.  It is interesting to me that going from the old Windows 3.1 to NT days we always had so much issues with people calling by ordinal vs the function name.  It broke all the time, but it is funny to see possibly where this bad habit started.

Import and link by Ordinal? What were they thinking!?

Import and link by Ordinal? What were they thinking!?

For those who don’t know DLL’s contain a table of functions sorted by NAME, and NUMBER.  The names have to be unique but the number depends on the order in which the DLL is linked together.  And it is very easy for someone to accidentally change the link order, and next thing you know the ordinal are all wrong.

Otherwise, yeah the tools from the MS OS/2 2.0 beta working in 2013.  I do believe that the object files can also be strung together with some DOS Extenders from the era to produce DPMI exe’s.

But I’ll save that exercise for later.