Subj : IOPL code with Watcom C
To   : All
From : Vitus Jensen
Date : Sun Nov 26 2000 06:55 pm

Hi All!

I'm trying to create a sample program for Watcom C 10.5 which demonstrates IOPL
code.  Usually I'm doing this with ALP and IBM Visual Age but this time it has
to be an all Watcom solution (16 bit C, 32 bit C(++), wlink).

Well, it doesn't work (obviously, that's why I'm writing this msg :-|).   The
problem isn't the 16 bit code (that's the same i used with VAC++), it's the
thunking which isn't working right.  Watcom keeps on calling the IOPL directly
from it's 16 bit thunking code instead of using a callgate.

Perhaps someone can tell me what I'm doing wrong...


Compilation:
       wcc -zq -ml -zl -zdf -zu -nt=R2CODE -2 -s -i=$(WATCOM)\h\os21x io16.c
       wpp386 -zq -bt=OS2 -3s -s -i=$(WATCOM)\h\os2 test16.cpp
       wcl386 -zq -l=OS2V2 -3s -fm @io16.lnk test16.obj io16.obj

io16.lnk:
       SEGment R2CODE IOPL
       EXP INB 2, INW 2, IND 2, OUTB 4, OUTW 4, OUTD 6


I'm using the following prototypes:

==================<io16.h>==================================
#if !defined(APIENTRY16)
# if defined(__WATCOMC__)
#  if defined(__386__)
#   define APIENTRY16 _Far16 _Pascal
#  else
#   define APIENTRY16 __far __pascal
#  endif
# elif defined(__IBMC__) || defined(__IBMCPP__)
#  define APIENTRY16 _Far16 _Pascal
# endif
#endif

extern unsigned char APIENTRY16 inb(unsigned short __port);
...
======================<end>=================================


The whole thing compiles to the following assembler code:

=====================<start>================================
`W?command_write$n(i)v`:
               push    esp
               push    00000004H
               push    00000024H
               call    near ptr __TNK
               push    esi
               sub     esp,00000018H
               mov     dword ptr +10H[esp],000003beH
               mov     ecx,00000002H
               lea     esi,+10H[esp]
               mov     eax,INB                ; 0x000E0000
               call    near ptr __Far16Func2
               and     al,0d0H
               movzx   edx,al
...
======================<end>=================================

This looks quite good (don't know nothing about __TNK), the address of INB is
indeed 000E:0000, selector 000E is ring 2 and '__Far16Func2' sounds like a
thunking call.
But when I run the executable, __Far16Func2 finally ends here:

=====================<start>================================
0017:0000        mov        cs,ss
0017:0002        mov        ds,cx
0017:0004        mov        es,cx
0017:0006        call       dword ptr [bp+0]        ; 0x000E0000
======================<end>=================================

The call fails (GPE) and IMHO because 0017 is ring 3 and 000E is ring 2 and you
can't call ring 2 directly from ring 3.
Again, where is my fault?

Bye,
  Vitus

PS: there is sample code for watcom floating around but it uses either IOPL
code or 32->16 bit calls not both combined.
PPS: complete source code on request.

---
* Origin: COFFEED: Coffee Deamon startup (2:2474/424.1)