How to do port I/O (IN/OUT) from OS/2

From EDM2
Jump to: navigation, search

by Stefan Zollner

A question often asked in the comp.os.os2.programming.misc newsgroup is the following: How can I do port I/O (using the Intel IN/OUT commands) from within OS/2? There are several possibilities, but I have found the following most useful: Port I/O in OS/2 should be done from a 16-bit segment running at ring 2. Therefore, you need a 16-bit assembler (or compiler) and you have to tell the linker (in the DEF file) that the segment should have I/O priviledge. Once you have the source code, you need to assemble (or compile) the source code. The resulting OBJ file can either be linked directly to your main program, or you can link the OBJ file into a DLL. (That's what I do.) Then, your programs can do port I/O by simply linking to your DLL.

Sample files:

  • Assembler source (io386.mac)
  • Include file for C++ main program (io386.hpp)
  • Include file for C main program (io386.h)
  • Object code (io386.obj)
  • Linker definition file for DLL (DEF) (io386.def)
  • Resulting DLL (io386.dll)
  • Resulting import library (LIB) (io386.lib)
  • The make file which builds it all (io386.mak)
  • A zip file containing all of the above, plus additional files you need. (
  • Current version: 1.02, dated 02/16/1996.


Tools you need: I use the following programming tools for doing port I/O:

  • VisualAge C++ for OS/2 (version 3.0) with CSDs.
  • Borland Assembler TASM (version 4.1), included in Borland C++ for OS/2, version 1.5.


Remarks: I was unable to create a DLL consisting ENTIRELY of routines written in assembly language. Therefore, I created a dummy C++ file (DLLINIT.CPP) which is supposed to initialize the C++ runtime environment.

 /* This dummy routine is needed to initialized the C/C++ runtime environment */
 /* in the DLL. Without this dummy function, the NMAKE will fail with an */
 /* error message LNK4038: No starting address. */
 int dummy;

Please note: Dr.-Ing. Holger Veit has pointed out to me that there is a different way to do port I/O without requiring ring switching and going to 32-bit. He recommended to use device driver for port I/O. I have not tried this and do not intend to make information about this method available. I merely want to disperse Dr. Veit's opinion that a 16-bit segment is NOT required for port I/O (although I find it convenient for my own purposes). Dr. Veit suggests to download from HOBBES and use the FASTIO$ device driver for port I/O. Also see Dr. Veit's article on 32-bit port I/O in the EDM/2 magazine (volume 4, number 1; January 1996).

Also, Eberhard Mattes from Stuttgart has recommended to me that I should stay away from calls to ring 2 DLLs in order to get better performance. He suggests that I should use EMXIO.DLL, or, for even better performance, xf86.sys (sp?).

I respect the opinions of these gentlemen (they are probably right), but what I describe here works just fine for me, therefore I keep using my ring 2 DLLs.

Acknowledgment: IO386.ZIP was originally downloaded from the internet. The original version was written by Keith Murray (Oregon State) with help from Joel Armengaud (IBM). We have modified the file and added some of our own routines. We also added documentation. This is a link to the original documentation which we downloaded from hobbes.

Disclaimer: This server is an experimental offering. Please send comments or complaints to Dr. Stefan Zollner, Department of Physics and Astronomy, A205 Physics Hall.

DISCLAIMER: This sample code is for your information only. Do not attempt to use this code on your equipment without first inspecting the source code and making sure it does what you want. This code is supplied as is without warranty or liability of any kind. Most of the brand names on this page are registered trademarks.