How do interrupts in wine work?

Nog nog at sdf.lonestar.org
Sun Feb 17 10:58:19 CST 2002


Ove Kaaven wrote:

>On Sat, 16 Feb 2002, Nog wrote:
>
>>Ove Kaaven wrote:
>>
>>>On Sat, 16 Feb 2002, Nog wrote:
>>>
>>[SNIP]
>>
>>>>And if so then why does it assume that the insterrupt it is emulating
>>>>is not builtin?
>>>>
>>>The table of 16-bit interrupt entry points is initialized from wprocs.dll
>>>(dlls/kernel/wprocs.spec), so it doesn't need to assume anything.
>>>
>>This was my point.  When emulating these interrupts it pushes the values 
>>of Eflags, Cs and Eip onto the stack but none of the interrupt handlers 
>>call the iret instruction or pop anything off the stack.  What have I 
>>missed?
>>
>
>They can't do that, of course, as they're 32-bit code, and the caller (and
>the stack) is 16-bit. So it's all taken care of by the 16/32 relay thunks
>generated by winebuild from the .spec file.
>
>>>>What all of this probable garbage came from is: What will it take to 
>>>>emulate int xx from 32-bit code?
>>>>
>>>A sane mechanism to handle those interrupt vectors, probably.
>>>
>>I assume that the Would this be somthing like the code in 
>>msdos/interrupts.c?
>>
>
>Perhaps.
>
>>But then why do we need to have 2 tables for 
>>interrupts (one in msdos/interrupts.c, the other in 
>>dlls/winedos/dosvm.c)?  The only explanation I can come up with is that 
>>mabe, just mabe, the interrupts in wproc.spec get called from 16-bit 
>>windows.
>>
>
>>From 16-bit protected mode, which typically means Win16, yes.
>The winedos tables are for 16-bit real mode (v86 mode).
>
>>Back to implementing int xx from 32-bit code, are all of the interrupts 
>>availible in real mode availible in protected mode?
>>
>
>No. Almost no interrupts are available. Calling DOS interrupts from
>protected mode requires explicit thunking, and apps typically requests
>such services from DPMI. Some thunks are provided by Windows (for
>compatibility) in 16-bit mode, but AFAIK none are provided in 32-bit.
>
>If an app does use DPMI in Wine, then the request will be properly routed
>to winedos and its interrupt tables, so you don't have to do anything for
>this to work (except make int31 (DPMI call) work in 32-bit, of course)
>
Ok, I have hacked togher something, but there is still something that 
I'm not sure about: What to add to Eip? This seems to be 2, looking at 
how other istructions are emulated.  If this is so then there is 
something else wrong because all dpmi programs that I have come up to 
emulate a couple 32-bit instructions and then simply chocke when they 
execute another one with privileged instruction.  Anyway here's the 
first draft of this code...

-------------- next part --------------
Index: include/miscemu.h
===================================================================
RCS file: /home/wine/wine/include/miscemu.h,v
retrieving revision 1.45
diff -u -r1.45 miscemu.h
--- include/miscemu.h	2002/01/31 23:22:07	1.45
+++ include/miscemu.h	2002/02/17 14:55:30
@@ -157,8 +157,10 @@
 
 /* msdos/interrupts.c */
 typedef void (WINAPI *INTPROC)(CONTEXT86*);
-extern FARPROC16 INT_GetPMHandler( BYTE intnum );
-extern void INT_SetPMHandler( BYTE intnum, FARPROC16 handler );
+extern FARPROC16 INT_Get16PMHandler( BYTE intnum );
+extern void INT_Set16PMHandler( BYTE intnum, FARPROC16 handler );
+extern INTPROC INT_Get32PMHandler( BYTE intnum );
+extern void INT_Set32PMHandler( BYTE intnum, INTPROC handler );
 
 /* msdos/ioports.c */
 extern DWORD IO_inport( int port, int count );
Index: loader/task.c
===================================================================
RCS file: /home/wine/wine/loader/task.c,v
retrieving revision 1.115
diff -u -r1.115 task.c
--- loader/task.c	2001/08/28 18:39:04	1.115
+++ loader/task.c	2002/02/17 14:55:42
@@ -297,9 +297,9 @@
     pTask->pdb.dispatcher[0] = 0x9a;  /* ljmp */
     PUT_UA_DWORD(&pTask->pdb.dispatcher[1], 
                  (DWORD)GetProcAddress16( GetModuleHandle16("KERNEL"), "DOS3Call" ));
-    pTask->pdb.savedint22 = INT_GetPMHandler( 0x22 );
-    pTask->pdb.savedint23 = INT_GetPMHandler( 0x23 );
-    pTask->pdb.savedint24 = INT_GetPMHandler( 0x24 );
+    pTask->pdb.savedint22 = INT_Get16PMHandler( 0x22 );
+    pTask->pdb.savedint23 = INT_Get16PMHandler( 0x23 );
+    pTask->pdb.savedint24 = INT_Get16PMHandler( 0x24 );
     pTask->pdb.fileHandlesPtr =
         MAKESEGPTR( GlobalHandleToSel16(pTask->hPDB), (int)&((PDB16 *)0)->fileHandles );
     pTask->pdb.hFileHandles = 0;
cvs server: Diffing loader/ne
cvs server: Diffing memory
Index: memory/instr.c
===================================================================
RCS file: /home/wine/wine/memory/instr.c,v
retrieving revision 1.13
diff -u -r1.13 instr.c
--- memory/instr.c	2001/10/21 15:18:15	1.13
+++ memory/instr.c	2002/02/17 14:55:51
@@ -672,12 +672,15 @@
         case 0xcd: /* int <XX> */
             if (long_op)
             {
-                ERR("int xx from 32-bit code is not supported.\n");
-                break;  /* Unable to emulate it */
+                FARPROC addr = INT_Get32PMHandler( instr[1] );
+                (*addr)(context);
+                context->Eip += prefixlen + 2;
             }
             else
             {
-                FARPROC16 addr = INT_GetPMHandler( instr[1] );
+                FARPROC16 addr = INT_Get16PMHandler( instr[1] );
                 WORD *stack = get_stack( context );
                 if (!addr)
                 {
Index: msdos/dpmi.c
===================================================================
RCS file: /home/wine/wine/msdos/dpmi.c,v
retrieving revision 1.60
diff -u -r1.60 dpmi.c
--- msdos/dpmi.c	2001/12/17 22:12:26	1.60
+++ msdos/dpmi.c	2002/02/17 14:55:55
@@ -365,7 +365,7 @@
         break;
     case 0x0204:  /* Get protected mode interrupt vector */
     	TRACE("get protected mode interrupt handler (0x%02x), stub!\n",BL_reg(context));
-	dw = (DWORD)INT_GetPMHandler( BL_reg(context) );
+	dw = (DWORD)INT_Get16PMHandler( BL_reg(context) );
 	CX_reg(context) = HIWORD(dw);
 	DX_reg(context) = LOWORD(dw);
 	break;
@@ -373,7 +373,7 @@
     case 0x0205:  /* Set protected mode interrupt vector */
     	TRACE("set protected mode interrupt handler (0x%02x,%p), stub!\n",
             BL_reg(context),MapSL(MAKESEGPTR(CX_reg(context),DX_reg(context))));
-	INT_SetPMHandler( BL_reg(context),
+	INT_Set16PMHandler( BL_reg(context),
                           (FARPROC16)MAKESEGPTR( CX_reg(context), DX_reg(context) ));
 	break;
 
Index: msdos/int21.c
===================================================================
RCS file: /home/wine/wine/msdos/int21.c,v
retrieving revision 1.67
diff -u -r1.67 int21.c
--- msdos/int21.c	2001/12/26 23:08:33	1.67
+++ msdos/int21.c	2002/02/17 14:56:08
@@ -1252,7 +1252,7 @@
         break;
 		
     case 0x25: /* SET INTERRUPT VECTOR */
-        INT_SetPMHandler( AL_reg(context), (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context)));
+        INT_Set16PMHandler( AL_reg(context), (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context)));
         break;
 
     case 0x29: /* PARSE FILENAME INTO FCB */
@@ -1373,7 +1373,7 @@
     case 0x35: /* GET INTERRUPT VECTOR */
         TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context));
         {
-            FARPROC16 addr = INT_GetPMHandler( AL_reg(context) );
+            FARPROC16 addr = INT_Get16PMHandler( AL_reg(context) );
             context->SegEs = SELECTOROF(addr);
             BX_reg(context) = OFFSETOF(addr);
         }
Index: msdos/int2f.c
===================================================================
RCS file: /home/wine/wine/msdos/int2f.c,v
retrieving revision 1.39
diff -u -r1.39 int2f.c
--- msdos/int2f.c	2002/01/13 01:46:12	1.39
+++ msdos/int2f.c	2002/02/17 14:56:12
@@ -343,7 +343,7 @@
 
     case 0x87: /* DPMI installation check */
 #if 1   /* DPMI still breaks pkunzip */
-        if (ISV86(context)) break; /* so bail out for now if in v86 mode */
+/*        if (ISV86(context)) break; /* so bail out for now if in v86 mode */
 #endif
         {
 	    SYSTEM_INFO si;
Index: msdos/interrupts.c
===================================================================
RCS file: /home/wine/wine/msdos/interrupts.c,v
retrieving revision 1.21
diff -u -r1.21 interrupts.c
--- msdos/interrupts.c	2001/12/04 19:54:49	1.21
+++ msdos/interrupts.c	2002/02/17 14:56:12
@@ -14,20 +14,33 @@
 
 DEFAULT_DEBUG_CHANNEL(int);
 
-static FARPROC16 INT_Vectors[256];
+/* 16-bit protected mode vector table */
+static FARPROC16 INT_Vectors16[256];
+/* 32-bit protected mode vector table */
+static INTPROC INT_Vectors32[256] = 
+{
+    /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0,
+    /* 08 */ 0, 0, 0, 0, 0, 0, 0, 0,
+    /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0,
+    /* 18 */ 0, 0, 0, 0, 0, 0, 0, 0,
+    /* 20 */ 0, 0, 0, 0, 0, 0, 0, 0,
+    /* 28 */ 0, 0, 0, 0, 0, 0, 0, 0,
+    /* 30 */ 0, INT_Int31Handler
+};
+
 
 /* Ordinal number for interrupt 0 handler in WPROCS.DLL */
 #define FIRST_INTERRUPT 100
 
 
 /**********************************************************************
- *	    INT_GetPMHandler
+ *	    INT_Get16PMHandler
  *
- * Return the protected mode interrupt vector for a given interrupt.
+ * Return the 16-bit protected mode interrupt vector for a given interrupt.
  */
-FARPROC16 INT_GetPMHandler( BYTE intnum )
+FARPROC16 INT_Get16PMHandler( BYTE intnum )
 {
-    if (!INT_Vectors[intnum])
+    if (!INT_Vectors16[intnum])
     {
         static HMODULE16 wprocs;
         if (!wprocs)
@@ -39,26 +52,26 @@
                 return 0;
             }
         }
-        if (!(INT_Vectors[intnum] = GetProcAddress16( wprocs, (LPCSTR)(FIRST_INTERRUPT + intnum))))
+        if (!(INT_Vectors16[intnum] = GetProcAddress16( wprocs, (LPCSTR)(FIRST_INTERRUPT + intnum))))
         {
-            WARN("int%x not implemented, returning dummy handler\n", intnum );
-            INT_Vectors[intnum] = GetProcAddress16( wprocs, (LPCSTR)(FIRST_INTERRUPT + 256) );
+            WARN("int%x in 16-bit mode not implemented, returning dummy handler\n", intnum );
+            INT_Vectors16[intnum] = GetProcAddress16( wprocs, (LPCSTR)(FIRST_INTERRUPT + 256) );
         }
     }
-    return INT_Vectors[intnum];
+    return INT_Vectors16[intnum];
 }
 
 
 /**********************************************************************
- *	    INT_SetPMHandler
+ *	    INT_Set16PMHandler
  *
- * Set the protected mode interrupt handler for a given interrupt.
+ * Set the 16-bit protected mode interrupt handler for a given interrupt.
  */
-void INT_SetPMHandler( BYTE intnum, FARPROC16 handler )
+void INT_Set16PMHandler( BYTE intnum, FARPROC16 handler )
 {
-    TRACE("Set protected mode interrupt vector %02x <- %04x:%04x\n",
+    TRACE("Set 16-bit protected mode interrupt vector %02x <- %04x:%04x\n",
                  intnum, HIWORD(handler), LOWORD(handler) );
-    INT_Vectors[intnum] = handler;
+    INT_Vectors16[intnum] = handler;
 }
 
 
@@ -69,4 +82,33 @@
  */
 void WINAPI INT_DefaultHandler( CONTEXT86 *context )
 {
+}
+
+
+/**********************************************************************
+ *	    INT_Get32PMHandler
+ *
+ * Return the 32-bit protected mode interrupt vector for a given interrupt.
+ */
+INTPROC INT_Get32PMHandler( BYTE intnum )
+{
+    if(!INT_Vectors32[intnum])
+    {
+        WARN("int%x in 32-bit mode not implemented, returning dummy handler\n", intnum );
+        INT_Vectors32[intnum] = INT_DefaultHandler;
+    }
+    return INT_Vectors32[intnum];
+}
+
+
+/**********************************************************************
+ *	    INT_Set32PMHandler
+ *
+ * Set the 32-bit protected mode interrupt handler for a given interrupt.
+ */
+void INT_Set32PMHandler( BYTE intnum, INTPROC handler )
+{
+    INT_Vectors32[intnum] = handler;
 }
Index: windows/user.c
===================================================================
RCS file: /home/wine/wine/windows/user.c,v
retrieving revision 1.84
diff -u -r1.84 user.c
--- windows/user.c	2002/01/01 00:24:35	1.84
+++ windows/user.c	2002/02/17 14:56:22
@@ -82,7 +82,7 @@
 {
     /* Hack: restore the divide-by-zero handler */
     /* FIXME: should set a USER-specific handler that displays a msg box */
-    INT_SetPMHandler( 0, INT_GetPMHandler( 0xff ) );
+    INT_Set16PMHandler( 0, INT_Get16PMHandler( 0xff ) );
 
     /* Create task message queue */
     if ( !InitThreadInput16( 0, 0 ) ) return 0;


More information about the wine-devel mailing list