public void DecimalAdjustAfterAddition() { Operand tempOp = new Operand(); if (((AL & 0xf) > 9) || AF) { bool carry = false; var temp = (ushort)(AL + 6); if (temp > byte.MaxValue) carry = true; CF = (CF | carry); AF = true; AL += 6; } else AF = false; if (((AL & 0xf0) > 0x90) || CF) { AL += 0x60; CF = true; } else CF = false; tempOp.Size = 8; tempOp.Value = AL; SetCPUFlags(tempOp); }
private void SetCPUFlags(Operand operand) { SF = operand.MSB; ZF = operand.Value == 0; PF = (((((byte)operand.Value * 0x0101010101010101UL) & 0x8040201008040201UL) % 0x1FF) & 1) == 0; }
public CPU() { PMode = false; segments = new Segment[6]; registers = new Register[9]; controlRegisters = new uint[5]; idtRegister = new TableRegister(); gdtRegister = new TableRegister(); disasm = new Disassembler(DisassemblerRead); disasm.CodeSize = codeSize; ProcessOperations(); realModeEntry = new GDTEntry { BaseAddress = 0, Is32Bit = false, IsAccessed = true, IsCode = false, Limit = 0xffff, IsWritable = true }; Halted = false; interruptOperand = new Operand(); interruptOperand.Size = 8; interruptOperand.Type = OperandType.Immediate; Reset(); }
public void CallFarMemory(Operand dest) { dest.Value = SegRead(dest.Memory.Segment, dest.Memory.Address + 2, 16); dest.Address = SegRead(dest.Memory.Segment, dest.Memory.Address, (int)dest.Size); CallFar(dest); }
public void Test(Operand dest, Operand source) { dest.Value = dest.Value & source.Value; SetCPUFlags(dest); CF = false; OF = false; }
public void StringIOWrite(Operand dest, Operand source) { uint count = GetCount(); int size = (int)(source.Size / 8); while (count > 0) { uint addr; if (addressSize == 32) addr = ESI; else addr = SI; uint value = SegRead(source.Memory.Segment, addr, (int)source.Size); IOWrite((ushort)dest.Value, value, (int)source.Size); if (DF) { if (addressSize == 32) ESI = (uint)(ESI - size); else SI = (ushort)(SI - size); } else { if (addressSize == 32) ESI = (uint)(ESI + size); else SI = (ushort)(SI + size); } count--; } SetCount(count); }
public void StringIORead(Operand dest, Operand source) { uint count = GetCount(); int size = (int)(dest.Size / 8); while (count > 0) { uint addr; if (addressSize == 32) addr = EDI; else addr = DI; uint value = IORead((ushort)source.Value, (int)dest.Size); SegWrite(SegmentRegister.ES, addr, value, (int)dest.Size); if (DF) { if (addressSize == 32) EDI = (uint)(EDI - size); else DI = (ushort)(DI - size); } else { if (addressSize == 32) EDI = (uint)(EDI + size); else DI = (ushort)(DI + size); } count--; } SetCount(count); }
public void RotateCarryRight(Operand dest, Operand source) { byte tempCount; byte tempCF; switch (dest.Size) { case 8: tempCount = (byte)((source.Value & 0x1f) % 9); break; case 16: tempCount = (byte)((source.Value & 0x1f) % 17); break; default: tempCount = (byte)((source.Value & 0x1f)); break; } if(source.Value == 1) OF = dest.MSB ^ CF; while (tempCount != 0) { tempCF = (byte)(dest.Value & 0x1); dest.Value = (uint)((dest.Value / 2) + ((CF ? 1 : 0) << (int)(dest.Size - 1))); CF = tempCF != 0; tempCount--; } SetCPUFlags(dest); WriteOperand(dest); }
public void DoIOWrite(Operand dest, Operand source) { WriteCallback ioWrite = IOWrite; if (ioWrite != null) ioWrite((ushort)dest.Value, source.Value, (int)source.Size); }
public void Or(Operand dest, Operand source) { dest.Value = dest.Value | source.Value; SetCPUFlags(dest); CF = false; OF = false; WriteOperand(dest); }
public void SegmentLoadDS(Operand dest, Operand source) { ushort segment; uint offset; GetSegmentAndOffset(source, out segment, out offset); DS = segment; dest.Value = offset; WriteOperand(dest); }
public void Exchange(Operand dest, Operand source) { Operand temp; temp = dest; dest.Value = source.Value; source.Value = temp.Value; WriteOperand(source); WriteOperand(dest); }
public void DoIORead(Operand dest, Operand source) { ReadCallback ioRead = IORead; if (ioRead != null) dest.Value = ioRead((ushort)source.Value, (int)dest.Size); else dest.Value = 0; WriteOperand(dest); }
public void LoadIDT(Operand dest) { if (opSize == 16) { idtRegister.Limit = SegReadWord(dest.Memory.Segment, dest.Memory.Address); idtRegister.Base = SegReadDWord(dest.Memory.Segment, dest.Memory.Address + 2) & 0x00ffffff; } else { idtRegister.Limit = SegReadWord(dest.Memory.Segment, dest.Memory.Address); idtRegister.Base = SegReadDWord(dest.Memory.Segment, dest.Memory.Address + 2); } }
public void Call(Operand dest) { if (opSize == 32) { StackPush(EIP); EIP = (uint)(EIP + dest.SignedValue); } else { StackPush((ushort)EIP); EIP = (ushort)(EIP + dest.SignedValue); } }
public void Decrement(Operand dest) { Operand result = dest; result.Value--; SetCPUFlags(result); if ((1 > 0 && dest.SignedValue < dest.SignedMin + 1)) OF = true; else OF = false; WriteOperand(result); }
public void CallAbsolute(Operand dest) { if (opSize == 16) { StackPush(IP); EIP = (ushort)dest.Value; } else { StackPush(EIP); EIP = dest.Value; } }
public void StoreIDT(Operand dest) { if (opSize == 16) { SegWriteWord(dest.Memory.Segment, dest.Memory.Address, idtRegister.Limit); SegWriteDWord(dest.Memory.Segment, dest.Memory.Address + 2, idtRegister.Base & 0x00ffffff); } else { SegWriteWord(dest.Memory.Segment, dest.Memory.Address, idtRegister.Limit); SegWriteDWord(dest.Memory.Segment, dest.Memory.Address + 2, idtRegister.Base); } }
public void Compare(Operand dest, Operand source) { Operand result = dest; result.Value = dest.Value - source.Value; SetCPUFlags(result); if ((source.SignedValue > 0 && dest.SignedValue < dest.SignedMin + source.SignedValue) || (source.SignedValue < 0 && dest.SignedValue > dest.SignedMax + source.SignedValue)) OF = true; else OF = false; CF = dest.Value < source.Value; }
public void Add(Operand dest, Operand source) { Operand result = dest; result.Value = dest.Value + source.Value; SetCPUFlags(result); CF = result.Value < dest.Value; if (((source.SignedValue > 0) && (dest.SignedValue > (dest.SignedMax - source.SignedValue))) || ((source.SignedValue < 0) && (dest.SignedValue < (dest.SignedMin - source.SignedValue)))) OF = true; else OF = false; WriteOperand(result); }
public void ASCIIAdjustBeforeDivide(Operand source) { byte tempAL = AL; byte tempAH = AH; Operand tmp = new Operand(); tmp.Size = 8; AL = (byte)((tempAL + (tempAH * source.Value)) & 0xff); AH = 0; tmp.Value = AL; SetCPUFlags(tmp); }
public void ASCIIAdjustAfterMultiply(Operand source) { Operand temp = new Operand(); if (source.Value == 0) throw new Exception("Divide Error"); byte tempAL = AL; AH = (byte)(tempAL / source.Value); AL = (byte)(tempAL % source.Value); temp.Size = 16; temp.Value = AH; SetCPUFlags(temp); }
public void Enter(Operand size, Operand nesting) { byte nestingLevel = (byte)(nesting.Value % 32); uint frameTemp; if (opSize == 32) { StackPush(EBP); frameTemp = ESP; } else { StackPush(BP); frameTemp = SP; } if (nestingLevel > 0) { for (int i = 1; i < nestingLevel - 1; i++) { if (opSize == 32) { EBP -= 4; StackPush(EBP); } else { BP -= 2; StackPush(BP); } } StackPush(frameTemp); } if (opSize == 32) { EBP = frameTemp; ESP = EBP - size.Value; } else { BP = (ushort)frameTemp; SP = (ushort)(BP - size.Value); } }
public void FarJump(Operand dest) { uint segment, offset; if (PMode == false && ((CR0 & 0x1) == 0x1)) PMode = true; else if (PMode && ((CR0 & 0x1) == 0)) PMode = false; segment = dest.Value; offset = (uint)dest.Address; CS = segment; if (opSize == 32) EIP = offset; else EIP = (ushort)offset; }
public void CpuID(Operand source) { switch (source.Value) { case 0: EAX = 2; EBX = 0x756e6547; /* "Genu" */ EDX = 0x49656e69; /* "ineI" */ ECX = 0x6c65746e; /* "ntel" */ break; case 1: EAX = 0x0610; /* Pentium Pro (ish) */ EDX = 0x3ce4787; /* support some stuff, other stuff not so much (i will comment or move this to enums at some point)*/ break; default: System.Diagnostics.Debugger.Break(); break; } }
public void AddWithCarry(Operand dest, Operand source) { Operand result = dest; ulong tmp; tmp = dest.Value + source.Value; if (CF) tmp++; result.Value = (uint)tmp; SetCPUFlags(result); if (((source.SignedValue > 0) && (dest.SignedValue > (dest.SignedMax - source.SignedValue))) || ((source.SignedValue < 0) && (dest.SignedValue < (dest.SignedMin - source.SignedValue)))) OF = true; else OF = false; CF = result.Value < tmp; WriteOperand(result); }
public void BitScanReverse(Operand dest, Operand source) { uint temp; if (source.Value == 0) { ZF = true; } else { ZF = false; temp = dest.Size - 1; while ((source.Value & ((1 << (int)temp))) == 0) { temp--; } dest.Value = temp; } WriteOperand(dest); }
public void BitScanForward(Operand dest, Operand source) { uint temp; if (source.Value == 0) { ZF = true; } else { ZF = false; temp = 0; while ((source.Value & ((1 << (int)temp))) == 0) { temp++; } dest.Value = temp; } WriteOperand(dest); }
public void CallFar(Operand dest) { uint segment, offset; segment = dest.Value; offset = (uint)dest.Address; if (opSize == 16) { StackPush(CS); StackPush(IP); CS = segment; EIP = (ushort)offset; } else { StackPush(CS); StackPush(EIP); CS = segment; EIP = offset; } }
public void Pop(Operand dest) { dest.Value = StackPop(); WriteOperand(dest); }