The cool thing about OS/2 2.1 was that you could easily boot off of a single 1.44 Mb floppy disk, and run multitasking operations, without the need for the GUI.
I had (and likely have lost forever) a Boot disk with OS/2, and my Forth/2 system on it that could do directory listings while playing Toccata and Fugue in D minor in a different thread.
I wrote Forth/2 out of pure spite, because somehow I heard that it just wasn't possible to write OS/2 applications in assembler. Thanks to a copy of the OS/2 development kit from Ward Christensen (who worked at IBM), and a few months of spare time, Forth/2 was born, written in pure assembler, compiling to directly threaded native code. Brian Matthewson from Case Western wrote the manual for it. Those were fun times.
kevindamm · 1h ago
Preemptive multithreading is better than cooperative multithreading (which windows 3 used) but then it's de-fanged by allowing the threads and process to adjust their own priority and set arbitrary lower bounds on how much time gets allotted to a thread per thunk.
Then there's this:
> All of the OS/2 API routines use the Pascal extended keyword for their calling convention so that arguments are pushed on the stack in the opposite order of C. The Pascal keyword does not allow a system routine to receive a variable number of arguments, but the code generated using the Pascal convention is smaller and faster than the standard C convention.
Did this choice of a small speed boost over compatibility ever haunt the decision makers, I wonder? At the time, the speed boost probably was significant at the ~Mhz clock speeds these machines were running at, and Moore's Law had only just gotten started. Maybe I tend to lean in the direction of compatibility but this seemed like a weird choice to me. Then, in that same paragraph:
> Also, the stack is-restored by the called procedure rather than the caller.
What could possibly go wrong?
mananaysiempre · 53m ago
16-bit Windows used the Pascal calling convention, with the documentation in the Windows 1.0 SDK only listing Pascal function declarations. (Most C programs for 16-bit Windows use FAR PASCAL in their declarations—the WINAPI macro was introduced with Win32 as a porting tool.) The original development environment for the Macintosh was a Lisa prototype running UCSD Pascal, and even the first edition of Inside Macintosh included Pascal declarations only. (I don’t know how true it is that Windows originated as a porting layer for moving Excel away from the still-in-development Mac, but it feels at least a bit true.) If you look at the call/return instructions, the x86 is clearly a Pascal machine (take the time to read the full semantics of the 80186’s ENTER instruction at some point). Hell, the C standard wouldn’t be out for two more years, and function prototypes (borrowed early from the still-in-development C++, thus the unhinged syntax) weren’t a sure thing. C was not yet the default choice.
>> Also, the stack is restored by the called procedure rather than the caller.
> What could possibly go wrong?
This is still the case for non-vararg __stdcall functions used by Win32 and COM. (The argument order was reversed compared to Win16’s __far __pascal.) By contrast, the __syscall convention that 32-bit OS/2 switched to uses caller cleanup (and passed some arguments in registers).
Uvix · 4m ago
I don't know if Windows started as a porting layer but it certainly ended up as one. Windows was already on v2.x by the time Excel was released on PC, but the initial PC version of Excel shipped with a stripped-down copy of Windows so that it could still run on machines without Windows. https://devblogs.microsoft.com/oldnewthing/20241112-00/?p=11...
maximilianburke · 59m ago
Callee clean-up was (is? is.) standard for the 32-bit Win32 API; it's been pretty stable now for coming up on 40 years now.
to11mtm · 48m ago
For 32 bit yes, although IIRC x64 convention is caller clean-up.
maximilianburke · 42m ago
That's why I said 32-bit Win32 :-)
flohofwoe · 42m ago
> Did this choice of a small speed boost over compatibility ever haunt the decision makers,
...in the end it's just another calling convention which you annotate your system header functions with. AmigaOS had a vastly different (very assembly friendly) calling convention for OS functions which exclusively(?) used CPU registers to pass arguments. C compilers simply had to deal with it.
> What could possibly go wrong?
...totally makes sense though when the caller passes arguments on the stack?
E.g. you probably have something like this in the caller:
push arg3 => place arg 3 on stack
push arg2 => place arg 2 on stack
push arg1 => place arg 1 on stack
call function => places return address on stack
...if the called function would clean up the stack it would also delete the return address needed by the return instruction (which pops the return address from the top of the stack and jumps to it).
(ok, x86 has the special `ret imm16` instruction which adjusts the stack pointer after popping the return address, but I guess not all CPUs could do that back then)
rep_lodsb · 53m ago
On x86, the RET instruction can add a constant to the stack pointer after popping the return address. Compared to the caller cleaning up the stack, this saves 3 bytes (and about the same number of clock cycles) for every call.
There is nothing wrong with using this calling convention, except for those specific functions that need to have a variable number of arguments - and why not handle those few ones differently instead, unless you're using a braindead compiler / language that doesn't keep track of how functions are declared?
pjmlp · 40m ago
After all these years COM is still now as cool as SOM used to be.
With meta-classes, implementation inheritance across multiple languages, and much better tooling in the OS tier 1 languages.
mananaysiempre · 8m ago
Cool, yes. Useful or a good idea, I dunno. Reading through the (non-reference) documentation on SOM, I’m struck by how they never could give a convincing example for the utility of metaclasses. (Saying this as someone who does love metaclasses in Python, which are of course an inferior interpretation of the same academic sources.) The SOM documentation is also surprisingly shallow given its size: with a copy of Brockschmidt, Box, the COM spec, and the Platform SDK manual, you could reimplement essentially all of COM (not ActiveX though), whereas the IBM’s documentation is more like “here’s how you use our IDL compiler and here are the functions you can call”. (This is in contrast with the Presentation Manager documentation, which is much tighter and more detailed than the one for USER/GDI ever has been.) From what I can infer of the underlying principles, I feel SOM is much more specific about its object model, which, given the goal is a cross-language ABI, is not necessarily a good thing. (I’d say that about WinRT too.)
And of course COM does do implementation inheritance: despite all the admonitions to the contrary, that’s what aggregation is! If you want a more conventional model and even some surprisingly fancy stuff like the base methods governing the derived ones and not vice versa, BETA-style, then WinRT inheritance[1] is a very thin layer on top of aggregation that accomplishes that. Now if only anybody at Microsoft bothered to document it. As in, at all.
> OS/2, Microsoft’s latest addition to its operating system line
Wasn't it mostly an IBM product, with Microsoft being involved only in the beginning?
mananaysiempre · 1h ago
The article is from December 1987, when nobody yet knew that it would end up that way. The Compaq Deskpro 386 had just been released in 1986 (thus unmooring the “IBM PC clones” from IBM), the September 1987 release of Windows/386 2.01 was only a couple of months ago (less if you account for print turnaround), and development of what would initially be called NT OS/2 would only start in 1988, with the first documents in the NT Design Workbook dated 1989. Even OS/2 1.1, the first GUI version, would only come out in October 1988 (on one hand, really late; on the other, how the hell did they release things so fast then?..).
p_l · 24m ago
While NT OS/2 effort started earlier, Windows 3.0 was apparently an unsanctioned originally rogue effort started by one developer, initially masquerading as update to "Windows-as-Embedded-Runtime" that multiple graphical products were shipping with, not just Microsoft's
Even when marketing people etc. got enthused enough that the project got official support and release, it was not expected to be such a hit of a release early on and expectation was that OS/2 effort would continue, if perhaps with a different kernel.
zabzonk · 1h ago
Microsoft unwrote a lot of the code that IBM needlessly wrote.
I worked as a trainer at a commercial training company that used the Glockenspiel C++ compiler that required OS/2. It made me sad. NT made me happy.
fredoralive · 1h ago
This is from 1987, the IBM / Microsoft joint development agreement for OS/2 didn't fall apart until around 1990, and there was a lot of Microsoft work in early OS/2 (and conversely, non-multitasking MS-DOS 4.0 was largely IBM work).
rbanffy · 1h ago
If you count the beginning as the time between OS/2 1.0 up until MS released Windows 3, then it makes sense. IBM understood Microsoft would continue to collaborate on OS/2 more or less forever.
I had (and likely have lost forever) a Boot disk with OS/2, and my Forth/2 system on it that could do directory listings while playing Toccata and Fugue in D minor in a different thread.
I wrote Forth/2 out of pure spite, because somehow I heard that it just wasn't possible to write OS/2 applications in assembler. Thanks to a copy of the OS/2 development kit from Ward Christensen (who worked at IBM), and a few months of spare time, Forth/2 was born, written in pure assembler, compiling to directly threaded native code. Brian Matthewson from Case Western wrote the manual for it. Those were fun times.
Then there's this:
Did this choice of a small speed boost over compatibility ever haunt the decision makers, I wonder? At the time, the speed boost probably was significant at the ~Mhz clock speeds these machines were running at, and Moore's Law had only just gotten started. Maybe I tend to lean in the direction of compatibility but this seemed like a weird choice to me. Then, in that same paragraph: What could possibly go wrong?>> Also, the stack is restored by the called procedure rather than the caller.
> What could possibly go wrong?
This is still the case for non-vararg __stdcall functions used by Win32 and COM. (The argument order was reversed compared to Win16’s __far __pascal.) By contrast, the __syscall convention that 32-bit OS/2 switched to uses caller cleanup (and passed some arguments in registers).
...in the end it's just another calling convention which you annotate your system header functions with. AmigaOS had a vastly different (very assembly friendly) calling convention for OS functions which exclusively(?) used CPU registers to pass arguments. C compilers simply had to deal with it.
> What could possibly go wrong?
...totally makes sense though when the caller passes arguments on the stack?
E.g. you probably have something like this in the caller:
...if the called function would clean up the stack it would also delete the return address needed by the return instruction (which pops the return address from the top of the stack and jumps to it).(ok, x86 has the special `ret imm16` instruction which adjusts the stack pointer after popping the return address, but I guess not all CPUs could do that back then)
There is nothing wrong with using this calling convention, except for those specific functions that need to have a variable number of arguments - and why not handle those few ones differently instead, unless you're using a braindead compiler / language that doesn't keep track of how functions are declared?
With meta-classes, implementation inheritance across multiple languages, and much better tooling in the OS tier 1 languages.
And of course COM does do implementation inheritance: despite all the admonitions to the contrary, that’s what aggregation is! If you want a more conventional model and even some surprisingly fancy stuff like the base methods governing the derived ones and not vice versa, BETA-style, then WinRT inheritance[1] is a very thin layer on top of aggregation that accomplishes that. Now if only anybody at Microsoft bothered to document it. As in, at all.
[1] https://www.interact-sw.co.uk/iangblog/2011/09/25/native-win...
Wasn't it mostly an IBM product, with Microsoft being involved only in the beginning?
Even when marketing people etc. got enthused enough that the project got official support and release, it was not expected to be such a hit of a release early on and expectation was that OS/2 effort would continue, if perhaps with a different kernel.
I worked as a trainer at a commercial training company that used the Glockenspiel C++ compiler that required OS/2. It made me sad. NT made me happy.