Sebastian Lackner : ntoskrnl: Emulate 'mov Eb, Gb' instruction on x86 processor architecture.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Mar 26 11:13:57 CDT 2015


Module: wine
Branch: master
Commit: b61d93a6b7dc45003fa036226710ec6f3c817138
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b61d93a6b7dc45003fa036226710ec6f3c817138

Author: Sebastian Lackner <sebastian at fds-team.de>
Date:   Mon Nov 10 07:14:48 2014 +0100

ntoskrnl: Emulate 'mov Eb, Gb' instruction on x86 processor architecture.

---

 dlls/ntoskrnl.exe/instr.c | 33 ++++++++++++++++++++++++++++-----
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c
index e170044..45021c6 100644
--- a/dlls/ntoskrnl.exe/instr.c
+++ b/dlls/ntoskrnl.exe/instr.c
@@ -59,7 +59,7 @@ static inline struct idtr get_idtr(void)
 }
 
 /* store an operand into a register */
-static void store_reg( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op )
+static void store_reg_word( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op )
 {
     switch((regmodrm >> 3) & 7)
     {
@@ -98,6 +98,22 @@ static void store_reg( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int lo
     }
 }
 
+/* store an operand into a byte register */
+static void store_reg_byte( CONTEXT *context, BYTE regmodrm, const BYTE *addr )
+{
+    switch((regmodrm >> 3) & 7)
+    {
+    case 0: context->Eax = (context->Eax & 0xffffff00) | *addr; break;
+    case 1: context->Ecx = (context->Ecx & 0xffffff00) | *addr; break;
+    case 2: context->Edx = (context->Edx & 0xffffff00) | *addr; break;
+    case 3: context->Ebx = (context->Ebx & 0xffffff00) | *addr; break;
+    case 4: context->Eax = (context->Eax & 0xffff00ff) | (*addr << 8); break;
+    case 5: context->Ecx = (context->Ecx & 0xffff00ff) | (*addr << 8); break;
+    case 6: context->Edx = (context->Edx & 0xffff00ff) | (*addr << 8); break;
+    case 7: context->Ebx = (context->Ebx & 0xffff00ff) | (*addr << 8); break;
+    }
+}
+
 /***********************************************************************
  *           INSTR_GetOperandAddr
  *
@@ -404,19 +420,26 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
         }
         break;  /* Unable to emulate it */
 
+    case 0x8a: /* mov Eb, Gb */
     case 0x8b: /* mov Ev, Gv */
     {
-        BYTE *addr = INSTR_GetOperandAddr(context, instr + 1, long_addr,
+        BYTE *data = INSTR_GetOperandAddr(context, instr + 1, long_addr,
                                           segprefix, &len);
+        unsigned int data_size = (*instr == 0x8b) ? (long_op ? 4 : 2) : 1;
         struct idtr idtr = get_idtr();
-        unsigned int offset = addr - idtr.base;
+        unsigned int offset = data - idtr.base;
 
-        if (offset <= idtr.limit + 1 - (long_op ? 4 : 2))
+        if (offset <= idtr.limit + 1 - data_size)
         {
             idt[1].LimitLow = 0x100; /* FIXME */
             idt[2].LimitLow = 0x11E; /* FIXME */
             idt[3].LimitLow = 0x500; /* FIXME */
-            store_reg( context, instr[1], (BYTE *)idt + offset, long_op );
+
+            switch (*instr)
+            {
+            case 0x8a: store_reg_byte( context, instr[1], (BYTE *)idt + offset ); break;
+            case 0x8b: store_reg_word( context, instr[1], (BYTE *)idt + offset, long_op ); break;
+            }
             context->Eip += prefixlen + len + 1;
             return ExceptionContinueExecution;
         }




More information about the wine-cvs mailing list