public CPUx86() { EIP = new Register32Bit("EIP", 0, RegisterType.InstructionPointer, false); EFLAGS = new FlagsRegister(); EAX = new GeneralPurposeRegister("EAX", 0); EBX = new GeneralPurposeRegister("EBX", 1); ECX = new GeneralPurposeRegister("ECX", 2); EDX = new GeneralPurposeRegister("EDX", 3); ESP = new GeneralPurposeRegister("ESP", 4); EBP = new GeneralPurposeRegister("EBP", 5); ESI = new GeneralPurposeRegister("ESI", 6); EDI = new GeneralPurposeRegister("EDI", 7); CR0 = new CR0(); CR2 = new ControlRegister("CR2", 2); CR3 = new ControlRegister("CR3", 3); CR4 = new ControlRegister("CR3", 4); AX = new Legacy16BitRegister("AX", EAX); BX = new Legacy16BitRegister("BX", EBX); CX = new Legacy16BitRegister("CX", ECX); DX = new Legacy16BitRegister("DX", EDX); SI = new Legacy16BitRegister("SI", ESI); DI = new Legacy16BitRegister("DI", EDI); BP = new Legacy16BitRegister("BP", EBP); AL = new Legacy8BitLowRegister("AL", EAX); BL = new Legacy8BitLowRegister("BL", EBX); CL = new Legacy8BitLowRegister("CL", ECX); DL = new Legacy8BitLowRegister("DL", EDX); AH = new Legacy8BitHighRegister("AH", EAX); BH = new Legacy8BitHighRegister("BH", EBX); CH = new Legacy8BitHighRegister("CH", ECX); DH = new Legacy8BitHighRegister("DH", EDX); XMM0 = new RegisterFloatingPoint("XMM0", 0, RegisterType.FloatingPoint); XMM1 = new RegisterFloatingPoint("XMM1", 1, RegisterType.FloatingPoint); XMM2 = new RegisterFloatingPoint("XMM2", 2, RegisterType.FloatingPoint); XMM3 = new RegisterFloatingPoint("XMM3", 3, RegisterType.FloatingPoint); XMM4 = new RegisterFloatingPoint("XMM4", 4, RegisterType.FloatingPoint); XMM5 = new RegisterFloatingPoint("XMM5", 5, RegisterType.FloatingPoint); XMM6 = new RegisterFloatingPoint("XMM6", 6, RegisterType.FloatingPoint); XMM7 = new RegisterFloatingPoint("XMM7", 7, RegisterType.FloatingPoint); ST0 = new RegisterFloatingPoint("ST0", -1, RegisterType.FloatingPoint); CS = new SegmentRegister("CS", 0); DS = new SegmentRegister("DS", 1); ES = new SegmentRegister("ES", 2); FS = new SegmentRegister("FS", 3); GS = new SegmentRegister("GS", 4); SS = new SegmentRegister("SS", 5); Reset(); }
public static LegacyPrefix GetSegmentOverride(SegmentRegister segment) { switch (segment) { case SegmentRegister.CS: return LegacyPrefix.CSSegmentOverride; case SegmentRegister.DS: return LegacyPrefix.DSSegmentOverride; case SegmentRegister.ES: return LegacyPrefix.ESSegmentOverride; case SegmentRegister.FS: return LegacyPrefix.FSSegmentOverride; case SegmentRegister.GS: return LegacyPrefix.GSSegmentOverride; case SegmentRegister.SS: return LegacyPrefix.SSSegmentOverride; default: throw new ArgumentOutOfRangeException(nameof(segment)); } }
private uint GetVirtualAddress(SegmentRegister segment, uint offset) { Segment seg = segments[(int)segment]; if (PMode) { return(seg.GDTEntry.BaseAddress + offset); } else { return(seg.GDTEntry.BaseAddress + (ushort)offset); } }
private void SetSelector(SegmentRegister segment, uint selector) { if (PMode) { segments[(int)segment].Selector = selector; segments[(int)segment].GDTEntry = GetSelectorEntry(selector); if (segment == SegmentRegister.CS) { codeSize = segments[(int)segment].GDTEntry.Is32Bit ? 32 : 16; } } else { segments[(int)segment].Selector = selector; segments[(int)segment].GDTEntry = realModeEntry; segments[(int)segment].GDTEntry.BaseAddress = selector << 4; } }
private ushort SegReadWord(SegmentRegister segment, uint offset) { return((ushort)SegRead(segment, offset, 16)); }
private void SetSelector(SegmentRegister segment, uint selector) { if (PMode) { segments[(int)segment].Selector = selector; segments[(int)segment].GDTEntry = GetSelectorEntry(selector); if (segment == SegmentRegister.CS) codeSize = segments[(int)segment].GDTEntry.Is32Bit ? 32 : 16; } else { segments[(int)segment].Selector = selector; segments[(int)segment].GDTEntry = realModeEntry; segments[(int)segment].GDTEntry.BaseAddress = selector << 4; } }
private void SegWriteDWord(SegmentRegister segment, uint offset, uint value) { SegWrite(segment, offset, value, 32); }
private void SegWrite(SegmentRegister segment, uint offset, uint value, int size) { uint virtAddr = GetVirtualAddress(segment, offset); Memory.Write(virtAddr, value, size); }
private uint SegReadDWord(SegmentRegister segment, uint offset) { return SegRead(segment, offset, 32); }
private uint SegRead(SegmentRegister segment, uint offset, int size) { uint virtAddr = GetVirtualAddress(segment, offset); return Memory.Read(virtAddr, size); }
public uint GetSelectorBase(SegmentRegister segment) { return segments[(int)segment].GDTEntry.BaseAddress; }
public uint GetSelectorBase(SegmentRegister segment) { return(segments[(int)segment].GDTEntry.BaseAddress); }
private void SegWriteWord(SegmentRegister segment, uint offset, ushort value) { SegWrite(segment, offset, value, 16); }
private void SegWriteByte(SegmentRegister segment, uint offset, byte value) { SegWrite(segment, offset, value, 8); }
private uint SegReadDWord(SegmentRegister segment, uint offset) { return(SegRead(segment, offset, 32)); }
public static EffectiveAddress FromIndirect16Encoding( SegmentRegister? segment, byte rm, short displacement) { GprCode @base; GprCode? index = null; switch (rm) { case 0: @base = GprCode.BX; @index = GprCode.SI; break; case 1: @base = GprCode.BX; @index = GprCode.DI; break; case 2: @base = GprCode.BP; @index = GprCode.SI; break; case 3: @base = GprCode.BP; @index = GprCode.DI; break; case 4: @base = GprCode.SI; break; case 5: @base = GprCode.DI; break; case 6: @base = GprCode.BP; break; case 7: @base = GprCode.BX; break; default: throw new ArgumentOutOfRangeException(nameof(rm)); } return Indirect(AddressSize._16, segment, @base, index, 1, displacement); }
private uint SegRead(SegmentRegister segment, uint offset, int size) { uint virtAddr = GetVirtualAddress(segment, offset); return(Memory.Read(virtAddr, size)); }
private static Flags BaseFlags(AddressSize size, SegmentRegister segment) { var flags = BaseFlags(size); switch (segment) { case SegmentRegister.CS: flags |= Flags.Segment_C; break; case SegmentRegister.DS: flags |= Flags.Segment_D; break; case SegmentRegister.ES: flags |= Flags.Segment_E; break; case SegmentRegister.FS: flags |= Flags.Segment_F; break; case SegmentRegister.GS: flags |= Flags.Segment_G; break; case SegmentRegister.SS: flags |= Flags.Segment_S; break; default: throw new UnreachableException(); } return flags; }
private uint GetVirtualAddress(SegmentRegister segment, uint offset) { Segment seg = segments[(int)segment]; if (PMode) return seg.GDTEntry.BaseAddress + offset; else return seg.GDTEntry.BaseAddress + (ushort)offset; }
public static EffectiveAddress Absolute(AddressSize size, SegmentRegister segment, int address) { Contract.Requires(size > AddressSize._16 || (short)address == address); return new EffectiveAddress(BaseFlags(size, segment) | Flags.BaseReg_None | Flags.IndexReg_None, address); }
private byte SegReadByte(SegmentRegister segment, uint offset) { return (byte)SegRead(segment, offset, 8); }
public static EffectiveAddress Indirect( AddressSize addressSize, SegmentRegister? segment, AddressBaseRegister? @base, GprCode? index = null, byte scale = 1, int displacement = 0) { Contract.Requires(scale == 1 || scale == 2 || scale == 4 || scale == 8 || (scale == 0 && !index.HasValue)); Contract.Requires(@base != AddressBaseRegister.Rip || (addressSize != AddressSize._16 && index.HasValue)); if (addressSize == AddressSize._16) { Contract.Requires(!(@base >= AddressBaseRegister.R8)); Contract.Requires(!(index >= GprCode.R8)); Contract.Requires((short)displacement == displacement); if (@base.HasValue) { if (index.HasValue) { Contract.Requires(@base == AddressBaseRegister.B || @base == AddressBaseRegister.BP); Contract.Requires(index.Value == GprCode.SI || index.Value == GprCode.DI); } else { Contract.Requires(@base == AddressBaseRegister.SI || @base == AddressBaseRegister.DI || @base == AddressBaseRegister.BP || @base == AddressBaseRegister.B); } } else { Contract.Requires(!index.HasValue); } } else { Contract.Requires(index != GprCode.Esp); } // Segment defaults to D, or S if we are using a stack-pointing register if (!segment.HasValue) { segment = (@base == AddressBaseRegister.SP || @base == AddressBaseRegister.BP) ? SegmentRegister.SS : SegmentRegister.DS; } var flags = BaseFlags(addressSize, segment.Value); if (@base.HasValue) flags |= (Flags)(((int)@base + 1) << (int)Flags.BaseReg_Shift); if (index.HasValue) { // Swap eax and esp (esp meaning "none") if (index.Value == GprCode.Eax) flags |= Flags.IndexReg_Eax; else flags |= (Flags)((int)index.Value << (int)Flags.IndexReg_Shift); } if (scale == 2) flags |= Flags.Scale_2x; else if (scale == 4) flags |= Flags.Scale_4x; else if (scale == 8) flags |= Flags.Scale_8x; return new EffectiveAddress(flags, displacement); }
private ushort SegReadWord(SegmentRegister segment, uint offset) { return (ushort)SegRead(segment, offset, 16); }
public static EffectiveAddress Indirect( AddressSize addressSize, SegmentRegister? segment, GprCode? @base, GprCode? index = null, byte scale = 1, int displacement = 0) => Indirect(addressSize, segment, (AddressBaseRegister?)@base, index, scale, displacement);
public static EffectiveAddress Indirect( AddressSize addressSize, SegmentRegister? segment, GprCode @base, int displacement = 0) => Indirect(addressSize, segment, (AddressBaseRegister)@base, displacement);
public static EffectiveAddress RipRelative( AddressSize addressSize, SegmentRegister? segment, int displacement) { Contract.Requires(addressSize != AddressSize._16); return Indirect(addressSize, segment, AddressBaseRegister.Rip, displacement); }
public static EffectiveAddress Indirect( AddressSize addressSize, SegmentRegister? segment, AddressBaseRegister @base, int displacement = 0) => Indirect(addressSize, segment, @base, index: null, scale: 1, displacement: displacement);
private byte SegReadByte(SegmentRegister segment, uint offset) { return((byte)SegRead(segment, offset, 8)); }