public unsafe void RunMachineCodeTest() { Assert.AreEqual(1, X86Assembly.RunMachineCode(new byte[] { 0xb8, 0x01, 0x00, 0x00, 0x00, 0xc3 })); Assert.AreEqual(145764, X86Assembly.RunMachineCode(new byte[] { 0xB8, 0x40, 0x01, 0x00, 0x00, 0x05, 0x24, 0x38, 0x02, 0x00, 0xc3 })); byte[] buffer = new byte[12]; fixed(byte *newBuffer = &buffer[0]) { try { X86Assembly.RunMachineCode(new byte[] { 0x53, // push %ebx 0x31, 0xc0, // xor %eax,%eax 0x0f, 0xa2, // cpuid 0x8b, 0x44, 0x24, 0x08, // mov 0x8(%esp),%eax 0x89, 0x18, // mov %ebx,0x0(%eax) 0x89, 0x50, 0x04, // mov %edx,0x4(%eax) 0x89, 0x48, 0x08, // mov %ecx,0x8(%eax) 0x5b, // pop %ebx 0xc3 // ret }, typeof(CPUID0Delegate), new IntPtr(newBuffer)); CollectionAssert.AreNotEqual(buffer, new byte[12]); } catch (Exception ex) { Assert.Fail(ex.Message); } } }
public void CompileToMachineCodeTest() { CollectionAssert.AreEqual(new byte[] { 0x53, 0x31, 0xc0, 0x0f, 0xa2, 0x8b, 0x44, 0x24, 0x08, 0x89, 0x18, 0x89, 0x50, 0x04, 0x89, 0x48, 0x08, 0x5b, 0xc3 }, X86Assembly.CompileToMachineCode(new object[] { ASM.push, REG.EBX, ASM.xor, REG.EAX, REG.EAX, new RawAssemblyCode("cpuid"), ASM.mov, REG.EAX, (REG.ESP + 8).Ptr, ASM.mov, (REG.EAX + 0).Ptr, REG.EBX, ASM.mov, (REG.EAX + 4).Ptr, REG.EDX, ASM.mov, (REG.EAX + 8).Ptr, REG.ECX, ASM.pop, REG.EBX, ASM.ret, })); }
public void ConvertInlineAssemblyTest() { Assert.AreEqual("ret", X86Assembly.FromInline(ASM.ret, new object[] { })); Assert.AreEqual("mov eax, 10", X86Assembly.FromInline(ASM.mov, new object[] { REG.EAX, 10 })); Assert.AreEqual("mov byte ptr [eax], 10", X86Assembly.FromInline(ASM.mov, new object[] { REG.EAX.Ptr.Byte, 10 })); Assert.AreEqual("mov word ptr [eax], 10", X86Assembly.FromInline(ASM.mov, new object[] { REG.EAX.Ptr.Word, 10 })); Assert.AreEqual("mov dword ptr [eax], 10", X86Assembly.FromInline(ASM.mov, new object[] { REG.EAX.Ptr, 10 })); Assert.AreEqual("mov dword ptr [eax], 10", X86Assembly.FromInline(ASM.mov, new object[] { REG.EAX.Ptr.DWord, 10 })); Assert.AreEqual("mov qword ptr [eax], 10", X86Assembly.FromInline(ASM.mov, new object[] { REG.EAX.Ptr.QWord, 10 })); Assert.AreEqual("mov dword ptr [eax+4], 10", X86Assembly.FromInline(ASM.mov, new object[] { (REG.EAX + 4).Ptr, 10 })); Assert.AreEqual("mov dword ptr [eax+ebx], 10", X86Assembly.FromInline(ASM.mov, new object[] { (REG.EAX + REG.EBX).Ptr, 10 })); Assert.AreEqual("mov dword ptr [eax+ebx*8+128], eax", X86Assembly.FromInline(ASM.mov, new object[] { (REG.EAX + REG.EBX * 8 + 128).Ptr.DWord, REG.EAX })); Assert.AreEqual("mov dword ptr [ebx*8+128], eax", X86Assembly.FromInline(ASM.mov, new object[] { (REG.EBX * 8 + 128).Ptr.DWord, REG.EAX })); Assert.AreEqual("mov dword ptr [ebx*2], eax", X86Assembly.FromInline(ASM.mov, new object[] { (REG.EBX * 2).Ptr.DWord, REG.EAX })); Assert.AreEqual("mov eax, dword ptr [ebx+4]", X86Assembly.FromInline(ASM.mov, new object[] { REG.EAX, (REG.EBX + 4).Ptr })); }
public static IVirtualMachine Compile(string asmSource) { AsmToken[][] asmTokens = AssemblyLexer.LexAsmCode(asmSource); X86Assembly assembly = X86Assembler.GenerateAssembly(asmTokens); string source = CSharpGenerator.GenerateSource(assembly); return(CSharpCompiler.CompileCSharp(source)); }
public void GetCodeTest() { Assert.AreEqual( $"mov eax, 100\nret\n", X86Assembly.GetCode( ASM.mov, REG.EAX, 100, ASM.ret)); Assert.AreEqual( "mov eax, 100\nadd eax, 200\nret\n", X86Assembly.GetCode( ASM.mov, REG.EAX, 100, ASM.add, REG.EAX, 200, ASM.ret)); Assert.AreEqual( "push 42\npop eax\nret\n", X86Assembly.GetCode( ASM.push, 42, ASM.pop, REG.EAX, ASM.ret)); Assert.AreEqual( "mov eax, 0\nmov ecx, 100\nmyloop:\nadd eax, ecx\nloop myloop\nret\n", X86Assembly.GetCode( ASM.mov, REG.EAX, 0, ASM.mov, REG.ECX, 100, new Label("myloop"), ASM.add, REG.EAX, REG.ECX, ASM.loop, "myloop", ASM.ret)); Assert.AreEqual( @"push ebx mov eax, 0 cpuid mov eax, dword ptr [esp+8] mov dword ptr [eax+0], ebx mov dword ptr [eax+4], edx mov dword ptr [eax+8], ecx pop ebx ret ".Replace("\r\n", "\n"), X86Assembly.GetCode(new object[] { ASM.push, REG.EBX, ASM.mov, REG.EAX, 0, new RawAssemblyCode("cpuid"), ASM.mov, REG.EAX, (REG.ESP + 8).Ptr, ASM.mov, (REG.EAX + 0).Ptr, REG.EBX, ASM.mov, (REG.EAX + 4).Ptr, REG.EDX, ASM.mov, (REG.EAX + 8).Ptr, REG.ECX, ASM.pop, REG.EBX, ASM.ret, })); }
public void ConvertInlineAssemblyRawCodeTest() { string code = "Nobody care this project"; Assert.AreEqual(code, X86Assembly.FromInline(new object[] { new RawAssemblyCode(code) })); }
public static string GenerateSource(X86Assembly assembly) { var generator = new CSharpGenerator(assembly); return(generator.GenerateProgramSource().Source); }
public CSharpGenerator(X86Assembly assembly) { _assembly = assembly; }
public CSharpTranslator(X86Assembly assembly, bool yieldAddress) : this(assembly) { _yieldAddress = yieldAddress; }
public CSharpTranslator(X86Assembly assembly) { _assembly = assembly; }
public static void Generate(ProgramSource ps, X86Assembly assembly, X86Instruction x86Instruction) { var translator = new CSharpTranslator(assembly); var addressTranslator = new CSharpTranslator(assembly, true); switch (x86Instruction.Name) { case "add": if (x86Instruction.OperandCount != 2) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Memory && x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Src.Type == OperandTypes.Label) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " += " + x86Instruction.Src.GetCode(translator)); break; case "and": if (x86Instruction.OperandCount != 2) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Memory && x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Src.Type == OperandTypes.Label) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " &= " + x86Instruction.Src.GetCode(translator)); break; case "call": if (x86Instruction.OperandCount != 1) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Label) { throw new WrongParameterException(x86Instruction); } string function = x86Instruction.Dst.GetCode(translator); if (!X86Assembler.IsFunction(function)) { throw new UnknownFunctionException(x86Instruction); } ps.AddCodeLine("vm." + x86Instruction.Dst.GetCode(translator) + "()"); break; case "cmp": if (x86Instruction.OperandCount != 2) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Src.Type == OperandTypes.Label) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type == OperandTypes.Label) { throw new WrongParameterException(x86Instruction); } GenerateCmp(ps, x86Instruction.Dst.GetCode(translator), x86Instruction.Src.GetCode(translator)); break; case "jmp": case "je": case "jne": case "jg": case "jge": case "jl": case "jle": case "jz": case "jnz": case "loop": JumpInstruction(ps, assembly, x86Instruction); break; case "lea": if (x86Instruction.OperandCount != 2) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Src.Type == OperandTypes.Label) { ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " = " + x86Instruction.Src.GetCode(translator)); break; } if (x86Instruction.Src.Type == OperandTypes.Memory) { ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " = " + x86Instruction.Src.GetCode(addressTranslator)); break; } throw new WrongParameterException(x86Instruction); case "mov": if (x86Instruction.OperandCount != 2) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Memory && x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Src.Type == OperandTypes.Label && !assembly.ConstantExists(((LabelArgument)x86Instruction.Src).Label)) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " = " + x86Instruction.Src.GetCode(translator)); break; case "mul": if (x86Instruction.OperandCount != 2) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Memory && x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Src.Type == OperandTypes.Label) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " *= " + x86Instruction.Src.GetCode(translator)); break; case "or": if (x86Instruction.OperandCount != 2) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Memory && x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Src.Type == OperandTypes.Label) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " |= " + x86Instruction.Src.GetCode(translator)); break; case "push": if (x86Instruction.OperandCount != 1) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine("vm.Push(" + x86Instruction.Dst.GetCode(translator) + ")"); break; case "pop": if (x86Instruction.OperandCount != 1) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " = vm.Pop()"); break; case "ret": if (x86Instruction.OperandCount != 0) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine("return;"); break; case "shl": if (x86Instruction.OperandCount != 2) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Memory && x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Src.Type == OperandTypes.Label) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " <<= " + x86Instruction.Src.GetCode(translator)); break; case "shr": if (x86Instruction.OperandCount != 2) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Memory && x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Src.Type == OperandTypes.Label) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " >>= " + x86Instruction.Src.GetCode(translator)); break; case "sub": if (x86Instruction.OperandCount != 2) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Memory && x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Src.Type == OperandTypes.Label) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " -= " + x86Instruction.Src.GetCode(translator)); break; case "xor": if (x86Instruction.OperandCount != 2) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Memory && x86Instruction.Dst.Type != OperandTypes.Register) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Src.Type == OperandTypes.Label) { throw new WrongParameterException(x86Instruction); } ps.AddCodeLine(x86Instruction.Dst.GetCode(translator) + " ^= " + x86Instruction.Src.GetCode(translator)); break; } }
public static void JumpInstruction(ProgramSource ps, X86Assembly assembly, X86Instruction x86Instruction) { if (x86Instruction.OperandCount != 1) { throw new WrongParameterException(x86Instruction); } if (x86Instruction.Dst.Type != OperandTypes.Label || x86Instruction.Dst as LabelArgument == null) { throw new WrongParameterException(x86Instruction); } var dst = x86Instruction.Dst as LabelArgument; string instructionName = x86Instruction.Name; string realLabel = dst.Label; if (!assembly.LabelExists(realLabel)) { throw new LabelMissingException(x86Instruction.Line, realLabel); } string label = assembly.InternalNameOf(realLabel); switch (instructionName) { case "jmp": ps.AddCodeLine("goto ", label); return; case "je": ps.AddJump("ZF == 1", label); return; case "jne": ps.AddJump("ZF == 0", label); return; case "jg": ps.AddJump("ZF == 0 && SF == OF", label); return; case "jge": ps.AddJump("SF == OF", label); return; case "jl": ps.AddJump("SF != OF", label); return; case "jle": ps.AddJump("ZF == 1 || SF != OF", label); return; case "jz": ps.AddJump("ZF == 1", label); return; case "jnz": ps.AddJump("ZF == 0", label); return; case "loop": ps.AddCodeLine("vm.Ecx.Value--"); ps.AddJump("vm.Ecx.Value != 0", label); return; } Debug.Assert(false, "Unknown jump instruction"); }
public void ExecuteScriptTest() { Assert.AreEqual(100, X86Assembly.ExecuteScript( ASM.mov, REG.EAX, 100, ASM.ret)); Assert.AreEqual(300, X86Assembly.ExecuteScript( ASM.mov, REG.EAX, 100, ASM.add, REG.EAX, 200, ASM.ret)); Assert.AreEqual(42, X86Assembly.ExecuteScript( ASM.push, 42, ASM.pop, REG.EAX, ASM.ret)); int i = 100; Assert.AreEqual(5050, X86Assembly.ExecuteScript( ASM.mov, REG.EAX, 0, ASM.mov, REG.ECX, i, new Label("myloop"), ASM.add, REG.EAX, REG.ECX, ASM.loop, "myloop", ASM.ret)); unsafe { int a = 84; Assert.AreEqual(84, X86Assembly.ExecuteScript( ASM.mov, REG.EAX, (int)&a, ASM.sub, REG.EAX, 4, ASM.mov, REG.EAX, (REG.EAX + 4).Ptr, ASM.ret)); byte[] buffer = new byte[12]; fixed(byte *newBuffer = &buffer[0]) { try { X86Assembly.ExecuteScript(new object[] { ASM.push, REG.EBX, ASM.xor, REG.EAX, REG.EAX, new RawAssemblyCode("cpuid"), ASM.mov, REG.EAX, (REG.ESP + 8).Ptr, ASM.mov, (REG.EAX + 0).Ptr, REG.EBX, ASM.mov, (REG.EAX + 4).Ptr, REG.EDX, ASM.mov, (REG.EAX + 8).Ptr, REG.ECX, ASM.pop, REG.EBX, ASM.ret, }, typeof(CPUID0Delegate), new IntPtr(newBuffer)); CollectionAssert.AreNotEqual(buffer, new byte[12]); } catch { Assert.Fail(); } } } }