v86m.c

来自「一个类似windows」· C语言 代码 · 共 812 行 · 第 1/2 页

C
812
字号
	    }
	  Exit = TRUE;
	  break;

      /* outsb */
	case 0x6E:
	  if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
	    {
	      ULONG Count;
	      PUCHAR Port;
	      PUCHAR Buffer;
	      ULONG Offset;

	      Count = 1;
	      if (RepPrefix)
		{
		  Count = Tf->Ecx;
		  if (!BigAddressPrefix)
		    {
		      Count = Count & 0xFFFF;
		    }
		}

	      Port = (PUCHAR)(Tf->Edx & 0xFFFF);
	      Offset = Tf->Edi;
	      if (!BigAddressPrefix)
		{
		  Offset = Offset & 0xFFFF;
		}
	      Buffer = (PUCHAR)((Tf->SegEs * 16) + Offset);
	      for (; Count > 0; Count--)
		{
		  WRITE_PORT_UCHAR(Port, *Buffer);
		  if (Tf->EFlags & DIRECTION_FLAG)
		    {
		      Buffer++;
		    }
		  else
		    {
		      Buffer--;
		    }
		}
	      Tf->Eip++;
	      return(0);
	    }
	  Exit = TRUE;
	  break;

	  /* insw/insd */
	case 0x6F:
	  if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
	    {
	      ULONG Count;
	      PUCHAR Port;
	      PUSHORT BufferS = NULL;
	      PULONG BufferL = NULL;
	      ULONG Offset;

	      Count = 1;
	      if (RepPrefix)
		{
		  Count = Tf->Ecx;
		  if (!BigAddressPrefix)
		    {
		      Count = Count & 0xFFFF;
		    }
		}

	      Port = (PUCHAR)(Tf->Edx & 0xFFFF);
	      Offset = Tf->Edi;
	      if (!BigAddressPrefix)
		{
		  Offset = Offset & 0xFFFF;
		}
	      if (BigDataPrefix)
		{
		  BufferL = (PULONG)((Tf->SegEs * 16) + Offset);
		}
	      else
		{
		  BufferS = (PUSHORT)((Tf->SegEs * 16) + Offset);
		}
	      for (; Count > 0; Count--)
		{
		  if (BigDataPrefix)
		    {
		      WRITE_PORT_ULONG((PULONG)Port, *BufferL);
		    }
		  else
		    {
		      WRITE_PORT_USHORT((PUSHORT)Port, *BufferS);
		    }
		  if (Tf->EFlags & DIRECTION_FLAG)
		    {
		      if (BigDataPrefix)
			{
			  BufferL++;
			}
		      else
			{
			  BufferS++;
			}
		    }
		  else
		    {
		      if (BigDataPrefix)
			{
			  BufferL--;
			}
		      else
			{
			  BufferS--;
			}
		    }
		}
	      Tf->Eip++;
	      return(0);
	    }
	  Exit = TRUE;
	  break;

      /* insb */
	case 0x6C:
	  if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
	    {
	      ULONG Count;
	      PUCHAR Port;
	      PUCHAR Buffer;
	      ULONG Offset;

	      Count = 1;
	      if (RepPrefix)
		{
		  Count = Tf->Ecx;
		  if (!BigAddressPrefix)
		    {
		      Count = Count & 0xFFFF;
		    }
		}

	      Port = (PUCHAR)(Tf->Edx & 0xFFFF);
	      Offset = Tf->Edi;
	      if (!BigAddressPrefix)
		{
		  Offset = Offset & 0xFFFF;
		}
	      Buffer = (PUCHAR)((Tf->SegEs * 16) + Offset);
	      for (; Count > 0; Count--)
		{
		  *Buffer = READ_PORT_UCHAR(Port);
		  if (Tf->EFlags & DIRECTION_FLAG)
		    {
		      Buffer++;
		    }
		  else
		    {
		      Buffer--;
		    }
		}
	      Tf->Eip++;
	      return(0);
	    }
	  Exit = TRUE;
	  break;

	  /* insw/insd */
	case 0x6D:
	  if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
	    {
	      ULONG Count;
	      PUCHAR Port;
	      PUSHORT BufferS = NULL;
	      PULONG BufferL = NULL;
	      ULONG Offset;

	      Count = 1;
	      if (RepPrefix)
		{
		  Count = Tf->Ecx;
		  if (!BigAddressPrefix)
		    {
		      Count = Count & 0xFFFF;
		    }
		}

	      Port = (PUCHAR)(Tf->Edx & 0xFFFF);
	      Offset = Tf->Edi;
	      if (!BigAddressPrefix)
		{
		  Offset = Offset & 0xFFFF;
		}
	      if (BigDataPrefix)
		{
		  BufferL = (PULONG)((Tf->SegEs * 16) + Offset);
		}
	      else
		{
		  BufferS = (PUSHORT)((Tf->SegEs * 16) + Offset);
		}
	      for (; Count > 0; Count--)
		{
		  if (BigDataPrefix)
		    {
		      *BufferL = READ_PORT_ULONG((PULONG)Port);
		    }
		  else
		    {
		      *BufferS = READ_PORT_USHORT((PUSHORT)Port);
		    }
		  if (Tf->EFlags & DIRECTION_FLAG)
		    {
		      if (BigDataPrefix)
			{
			  BufferL++;
			}
		      else
			{
			  BufferS++;
			}
		    }
		  else
		    {
		      if (BigDataPrefix)
			{
			  BufferL--;
			}
		      else
			{
			  BufferS--;
			}
		    }
		}
	      Tf->Eip++;
	      return(0);
	    }
	  Exit = TRUE;
	  break;

	  /* Int nn */
	case 0xCD:
	  {
	    unsigned int inum;
	    unsigned int entry;

	    inum = ip[1];
	    entry = ((unsigned int *)0)[inum];

	    Tf->HardwareEsp = Tf->HardwareEsp - 6;
	    sp = sp - 3;

	    sp[0] = (USHORT)((Tf->Eip & 0xFFFF) + 2);
	    sp[1] = (USHORT)(Tf->SegCs & 0xFFFF);
	    sp[2] = (USHORT)(Tf->EFlags & 0xFFFF);
	    if (VTf->regs->Vif == 1)
	      {
		sp[2] = (USHORT)(sp[2] | INTERRUPT_FLAG);
	      }
	    DPRINT("sp[0] %x sp[1] %x sp[2] %x\n", sp[0], sp[1], sp[2]);
	    Tf->Eip = entry & 0xFFFF;
	    Tf->SegCs = entry >> 16;
	    Tf->EFlags = Tf->EFlags & (~TRAP_FLAG);

	    return(0);
	  }
	}

      /* FIXME: Also emulate ins and outs */
      /* FIXME: Handle opcode prefixes */
      /* FIXME: Don't allow the BIOS to write to sensitive I/O ports */
    }

  DPRINT1("V86GPF unhandled (was %x)\n", ip[i]);
  *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
  return(1);
}

ULONG
NTAPI
KeV86Exception(ULONG ExceptionNr, PKTRAP_FRAME Tf, ULONG address)
{
  PUCHAR Ip;
  PKV86M_TRAP_FRAME VTf;

  ASSERT (ExceptionNr != 14);

  VTf = (PKV86M_TRAP_FRAME)Tf;

  /* FIXME: This should use ->VdmObjects */
  if(KeGetCurrentProcess()->Unused)
  {
    VTf->regs->PStatus = (PNTSTATUS) ExceptionNr;
    return 1;
  }

  /*
   * Check if we have reached the recovery instruction
   */
  Ip = (PUCHAR)((Tf->SegCs & 0xFFFF) * 16 + (Tf->Eip & 0xFFFF));
  
  DPRINT("ExceptionNr %d Ip[0] %x Ip[1] %x Ip[2] %x Ip[3] %x Tf->SegCs %x "
	 "Tf->Eip %x\n", ExceptionNr, Ip[0], Ip[1], Ip[2], Ip[3], Tf->SegCs,
	 Tf->Eip);
  DPRINT("VTf %x VTf->regs %x\n", VTf, VTf->regs);

  if (ExceptionNr == 6 &&
      memcmp(Ip, VTf->regs->RecoveryInstruction, 4) == 0 &&
      (Tf->SegCs * 16 + Tf->Eip) == VTf->regs->RecoveryAddress)
    {
      *VTf->regs->PStatus = STATUS_SUCCESS;
      return(1);
    }

  /*
   * Handle the exceptions
   */
  switch (ExceptionNr)
    {
      /* Divide error */
    case 0:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Single step */
    case 1:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* NMI */
    case 2:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Breakpoint */
    case 3:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Overflow */
    case 4:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Array bounds check */
    case 5:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Invalid opcode */
    case 6:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Device not available */
    case 7:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Double fault */
    case 8:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Intel reserved */
    case 9:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Invalid TSS */
    case 10:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Segment not present */
    case 11:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Stack fault */
    case 12:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* General protection fault */
    case 13:
      return(KeV86GPF(VTf, Tf));

      /* Intel reserved */
    case 15:
    case 16:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

      /* Alignment check */
    case 17:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);

    default:
      *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
      return(1);
    }
}



⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?