Jump to content

chrissx

Member
  • Posts

    2
  • Joined

  • Last visited

Reputation Activity

  1. Like
    chrissx reacted to FreeDev in The under 100 line challenge!   
    Probably pointless, but could useful depending on the individual who is interested in IL programming and this snippet is about 140 lines of code. I created it on a whim.
     
    The purpose of this snippet is basically to emit Brainf*ck programming language into IL during runtime in C#:
     
    using System; using System.Collections.Generic; using System.Reflection.Emit; using System.Runtime.InteropServices; using System.IO; namespace BFJIT { public unsafe class BFJIT { public static void ZeroOutMemory(byte* ptr, int size) { for (int I = 0; I < size; I++) ptr[I] = 0; } public delegate IntPtr BrainFkCompile(); public BrainFkCompile Compile(string code) { var WhileBeginMarkStack = new Stack<Label>(); var WhileEndMarkStack = new Stack<Label>(); var reader = new StringReader(code); var method = new DynamicMethod($"BrainFk{Guid.NewGuid().ToString().Replace("-", "_")}", typeof(IntPtr), null); var il = method.GetILGenerator(); // Set the locals il.DeclareLocal(typeof(byte*)); il.DeclareLocal(typeof(IntPtr)); // Allocate pointer il.Emit(OpCodes.Ldc_I4, 1048576); // 1 MB Memory il.EmitCall(OpCodes.Call, typeof(Marshal).GetMethod("AllocHGlobal", new Type[] { typeof(int) }), null); il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Ldloca_S, 1); il.EmitCall(OpCodes.Call, typeof(IntPtr).GetMethod("ToPointer"), null); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldc_I4, 1048576); // 1 MB Memory il.EmitCall(OpCodes.Call, typeof(BFJIT).GetMethod("ZeroOutMemory"), null); int currentCharacter = -1; do { currentCharacter = reader.Read(); switch ((char)currentCharacter) { case '>': { il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_0); break; } case '<': { il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Sub); il.Emit(OpCodes.Stloc_0); break; } case '+': { il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldind_U1); int increment = 1; while (reader.Peek() == '+') { ++increment; reader.Read(); } il.Emit(OpCodes.Ldc_I4, increment); il.Emit(OpCodes.Add); il.Emit(OpCodes.Conv_U1); il.Emit(OpCodes.Stind_I1); break; } case '-': { il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldind_U1); int decrement = 1; while (reader.Peek() == '-') { ++decrement; reader.Read(); } il.Emit(OpCodes.Ldc_I4, decrement); il.Emit(OpCodes.Sub); il.Emit(OpCodes.Conv_U1); il.Emit(OpCodes.Stind_I1); break; } case '.': { il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldind_U1); il.EmitCall(OpCodes.Call, typeof(Console).GetMethod("Write", new[] { typeof(byte) }), null); break; } case '[': { Label begin = il.DefineLabel(); Label end = il.DefineLabel(); il.Emit(OpCodes.Br, end); il.MarkLabel(begin); WhileBeginMarkStack.Push(begin); WhileEndMarkStack.Push(end); break; } case ']': { il.MarkLabel(WhileEndMarkStack.Pop()); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldind_U1); il.Emit(OpCodes.Brtrue, WhileBeginMarkStack.Pop()); break; } default: continue; } } while (currentCharacter > -1); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Ret); return (BrainFkCompile)method.CreateDelegate(typeof(BrainFkCompile)); } static unsafe void Main(string[] args) { var jitter = new BFJIT(); var func = jitter.Compile("++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."); Console.WriteLine("Brainfk Compiled"); var ptr = func(); Console.WriteLine(); Console.WriteLine("Program Terminated."); Marshal.FreeHGlobal(ptr); Console.ReadLine(); } } }  
×