I continue to explore assembly language and how to call functions from C. This time we travel back in time to the mid 80s and leave the 64-bit arena that I described here: https://matspetterss.wordpress.com/2023/01/02/silly-explorations-in-assembly-part-1/.
OS/2 1.3 – 16-bit
I start with OS/2 1.3 that was released somewhere in 1990. It’s a 16-bit operating system, so it differs a lot from the 64-bit operating systems. This is how it looks.
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/os213.png?w=1024)
I reuse the C program from earlier post, and in order to recompile it I used Microsoft C 5.1, which has support for OS/2, and IBM MASM/2 for assembling the assembly code.
The helloint.asm file
It’s not really a big difference in comparison to the 64-bit masm version. What (mostly) differs is the way parameters are passed. Assuming that the small memory model is used, the first parameter is found in [sp+4], and the next in [sp+6] and so on.
PUBLIC _helloint
PUBLIC _helloints
_TEXT SEGMENT BYTE PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT WORD PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT WORD PUBLIC 'BSS'
_BSS ENDS
DGROUP GROUP CONST, _BSS, _DATA
ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
_TEXT SEGMENT
_helloint PROC
push bp
mov bp, sp
mov ax,[bp+4] ;a1
and ax, 1
jz even16
mov ax, 1
jmp finish16
even16:
mov ax, 0
finish16:
mov sp,bp
pop bp
ret
_helloint ENDP
_helloints PROC
push bp
mov bp,sp
mov ax,[bp+4] ;a1
add ax,[bp+6] ;a2
add ax,[bp+8] ; ...
add ax,[bp+10]
add ax,[bp+12]
add ax,[bp+14]
add ax,[bp+16]
add ax,[bp+18]
add ax,[bp+20]
pop bp
ret
_helloints ENDP
_TEXT ENDS
END
Compiling, assembling and linking
The -Dhelloos216 is used in the C program to print out a Hello World message, expanding the message as follows:
#ifdef helloos216
#define hellostr "Hello, world! OS/2 16-bit :-)"
#endif
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/os2-cc-masm.png?w=1024)
Linking is a straight-forward task.
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/os2-link.png?w=1024)
And here you see the Hello World-message as well as the output from running the program.
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/os2-helloc.png?w=1024)
OS/2 2.11 – 32-bit
Let’s now explore the 32-bit version of OS/2. I picked the 2.11 version that was released in 1994. The first 32-bit version (2.0) was released in 1992.
This is how it looks.
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/os221.png?w=1024)
The helloint.asm file
The 32-bit version introduces a flat memory model instead of the segmented 16-bit model. The flat model is easier to use from a programming perspective.
The first three parameters are passed in the EAX, EDX and ECX registers, and the following are passed on the stack (ESP+08H, ESP+0CH and so on). Each integer now occupies 32 bits, compared to 16 bits as in the previous example.
.386P
.MODEL flat
CODE32 SEGMENT DWORD USE32 PUBLIC 'CODE'
CODE32 ENDS
DATA32 SEGMENT DWORD USE32 PUBLIC 'DATA'
DATA32 ENDS
CONST32 SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST32 ENDS
BSS32 SEGMENT DWORD USE32 PUBLIC 'BSS'
BSS32 ENDS
DGROUP GROUP CONST32, BSS32, DATA32
ASSUME CS:FLAT, DS:FLAT, SS:FLAT, ES:FLAT
.STACK 4096
CODE32 SEGMENT
ALIGN 04H
public helloint
public helloints
helloint PROC
PUSH EBP
MOV EBP,ESP
SUB ESP,04H
MOV [EBP+08H],EAX; a1
MOV [EBP+0cH],EDX; a2
MOV [EBP+010H],ECX; a3
mov eax, [ebp+8h] ;a1
and eax, 1
jz even32
mov eax, 1
jmp finish32
even32:
mov eax, 0
finish32:
mov esp,ebp
pop ebp
ret
helloint ENDP
helloints PROC
PUSH EBP
MOV EBP,ESP
SUB ESP,04H
MOV [EBP+08H],EAX; a1
MOV [EBP+0cH],EDX; a2
MOV [EBP+010H],ECX; a3
mov eax,[ebp+08H] ;a1
add eax,[ebp+0CH] ;a2
add eax,[ebp+10H] ;a3
add eax,[ebp+14H]
add eax,[ebp+18H]
add eax,[ebp+1CH]
add eax,[ebp+20H]
add eax,[ebp+24H]
add eax,[ebp+28H]
mov esp,ebp
pop ebp
MOV [EBP-04H],EAX
ret
helloints ENDP
CODE32 ENDS
END
Compiling, assembling and linking
I used the IBM C/C++ Tools version 2.0 to compile the C code.
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/os2-32-icc.png?w=1024)
I had a hard time to find a 32-bit macro assembler. Finally I understood that the Microsoft MASM version 6.0 had support for 32-bit OS/2.
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/os2-32-masm.png?w=1024)
Finally linking the object modules together using link386.
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/os2-32-link386.png?w=1024)
Here you have the output from the 32-bit OS/2 world 🙂
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/os2-32-helloc.png?w=1024)
DOS (3.3) – 16-bit
If you look at the details, you will actually see that this source is very similar to the 16-bit OS/2. I made some adjustments in the code because I wanted to test small and large memory models, because of the differences in the locations for the parameters. Otherwise it is the same.
The helloint.asm file
I introduce a constant in order to conditionally assemble the source depending on the memory model (hellodos_l).
PUBLIC _helloint
PUBLIC _helloints
hellodos_l equ 1
_TEXT SEGMENT BYTE PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT WORD PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT WORD PUBLIC 'BSS'
_BSS ENDS
DGROUP GROUP CONST, _BSS, _DATA
ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
_DATA SEGMENT
_DATA ENDS
_TEXT SEGMENT
ifdef hellodos_l
_helloint PROC FAR
else
_helloint PROC NEAR
endif
push bp
mov bp, sp
ifdef hellodos_l
mov ax,[bp+6] ;a1
else
mov ax,[bp+4] ;a1
endif
and ax, 1
jz even16
mov ax, 1
jmp finish16
even16:
mov ax, 0
finish16:
mov sp,bp
pop bp
ret
_helloint ENDP
ifdef hellodos_l
_helloints PROC FAR
else
_helloints PROC NEAR
endif
push bp
mov bp,sp
ifdef hellodos_l
mov ax,[bp+6] ;a1
else
mov ax,[bp+4] ;a1
add ax,[bp+6] ;a2
endif
add ax,[bp+8]
add ax,[bp+10]
add ax,[bp+12]
add ax,[bp+14]
add ax,[bp+16]
add ax,[bp+18]
add ax,[bp+20]
ifdef hellodos_l
add ax,[bp+22]
endif
pop bp
ret
_helloints ENDP
_TEXT ENDS
END
Compiling, assembling and linking
For DOS I use the old C compiler from 1985 and the IBM Macro assembler from 1981. It feels ancient to run this code 🙂
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/dos_masm-cc-small.png?w=1024)
I use a more modern linker for linking the modules. It is actually from OS/2, but also runs on DOS.
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/dos_link.png?w=1024)
Running it, compiled and linked with the large memory model.
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/dos_helloc_l.png?w=1024)
And with the small memory model. I’m happy to see the output is the same and the calculations are correct.
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/dos_helloc_s.png?w=1024)
The helloint.asm file (nasm version)
Having been so deep into all this old stuff, I wondered if nasm could be used in DOS to produce the object module. It has a different syntax than masm, so here is the code for that. Here is the version for the small memory model, that I later linked with the C code.
global _helloint
global _helloints
section ._text
_helloint:
push bp
mov bp, sp
mov ax,[bp+4] ;a1
and ax, 1
jz even16
mov ax, 1
jmp finish16
even16:
mov ax, 0
finish16:
mov sp,bp
pop bp
ret
_helloints:
push bp
mov bp,sp
mov ax,[bp+4]
add ax, [bp+6]
add ax,[bp+8]
add ax,[bp+10]
add ax,[bp+12]
add ax,[bp+14]
add ax,[bp+16]
add ax,[bp+18]
add ax,[bp+20]
; add ax,[bp+22]
pop bp
ret
Linking it gave warning messages, but the actual executable worked fine. I never understood how to solve these warnings. I save that task for another day.
![](https://matspetterss.wordpress.com/wp-content/uploads/2023/01/dos-fixup.png?w=604)
To summarize
It was fun to explore these differences, but what was even more fun was the actual journey back in time. I used all these tools at the time, and it was a true pleasure to get them running again.
I used Linux tools to actually write the code, because I’m just to more modern editors nowadays. To get a setup that worked for my workflow was quite interesting as well.
Running dosbox on Linux helped me a lot with the DOS versions.
I had some concerns with how carriage return/line feeds were handled in the DOS environment. But there are tools available for that.
If you have read this far, I hope that you enjoyed it.
Leave a comment