public static string Disassemble(byte[] program, int length) { StringBuilder builder = new StringBuilder(); var position = 0; while (position < length) { var opcode = (Opcode)program[position]; if (opcode == Opcode.Metadata) { var m1 = program[position + 1]; var m2 = program[position + 2]; var m3 = program[position + 3]; builder.AppendFormat("\nFunction\n{0:D3}:\tMethod [Params: {3}]", position, m1, m2, m3); position += 4; } else { builder.AppendFormat("{0:D3}:\t{1, -16}", position, opcode); position++; foreach (Type t in OpcodeDefinition.For(opcode).Params) { if (t == typeof(byte)) { builder.AppendFormat("{0:X2} ({0})\t", program[position++]); } else if (t == typeof(short)) { builder.AppendFormat("{0:X4} ({0})\t", BitConverter.ToInt16(program, position)); position += sizeof(short); } else if (t == typeof(int)) { builder.AppendFormat("{0:X8} ({0})\t", BitConverter.ToInt32(program, position)); position += sizeof(int); } else if (t == typeof(long)) { builder.AppendFormat("{0:X16} ({0})\t", BitConverter.ToInt64(program, position)); position += sizeof(int); } else { throw new NotImplementedException(); } } } builder.AppendLine(); } return(builder.ToString()); }
public void Emit(Opcode opcode, long param1) { Requires.That(OpcodeDefinition.For(opcode).Params.SequenceEqual(new Type[] { typeof(int) })); Buffer.Position = Length; writer.Write((byte)opcode); writer.Write(param1); writer.Flush(); Length = (int)Buffer.Position; }
public byte[] Link(IEnumerable <FunctionBuilder> emitters) { // goes through all the emitters, lays them out in memory and then links them to their // actual memory addresses. // first emitter is interpreted as main. var totalLength = emitters.Sum(e => e.Length); var memoryStream = new MemoryStream(totalLength); var addresses = new Dictionary <string, int>(); // layout all emitters var offset = OpcodeDefinition.Stride(Opcode.Jump16) + OpcodeDefinition.Stride(Opcode.Halt); var entry = emitters.First(); foreach (var emitter in emitters) { var disassembly = Disassembler.Disassemble(emitter.Buffer.GetBuffer(), emitter.Length); //Console.WriteLine(disassembly); Console.WriteLine($"Linked {emitter.Name} @ {offset}"); addresses.Add(emitter.Name, offset); emitter.Address = offset; offset += emitter.Length; } // set absolute addresses foreach (var emitter in emitters) { foreach (var call in emitter.Calls) { emitter.Link(call.Key, addresses[call.Value]); } } // Write jump to entry function. memoryStream.WriteByte((byte)Opcode.Call16); memoryStream.Write(BitConverter.GetBytes((short)addresses[entry.Name]), 0, sizeof(short)); memoryStream.WriteByte((byte)Opcode.Halt); // iterate through all emitters, and rewrite foreach (var emitter in emitters) { var disassembly = Disassembler.Disassemble(emitter.Buffer.GetBuffer(), emitter.Length); //Console.WriteLine(disassembly); Requires.That(addresses[emitter.Name] == memoryStream.Position); emitter.Buffer.Position = 0; emitter.Buffer.CopyTo(memoryStream, emitter.Length); } memoryStream.Position = 0; BinaryReader reader = new BinaryReader(memoryStream); return(reader.ReadBytes((int)memoryStream.Length)); }