/// <summary> /// Function to decompile the lines read from a hex file. /// </summary> /// <returns>List with the flash memory abstraction.</returns> public List<picWord> decompile() { int Bytes, BaseAddress, CheckSum, i, bin; DataTypes DataType; List<int> DataBytes = new List<int>(); List<picWord> sourceISA = new List<picWord>(); foreach (String line in HexCode) { Bytes = Convert.ToInt32(line.Substring(1, BYTEBLOCK), 16); BaseAddress = Convert.ToInt32(line.Substring(BYTEBLOCK + 1, 2 * BYTEBLOCK), 16) >> 1; DataType = (DataTypes)Convert.ToInt32(line.Substring(3 * BYTEBLOCK + 1, BYTEBLOCK), 16); if (BaseAddress == 0x2007) { // This is a configuration word... and its extremely poorly documented... bin = Convert.ToInt32(line.Substring(5 * BYTEBLOCK + 1, BYTEBLOCK) + line.Substring(4 * BYTEBLOCK + 1, BYTEBLOCK), 16); sourceISA.Add(new picWord(bin, BaseAddress)); continue; } else if (DataType == DataTypes.ExtendedAddress) { // This is data which was placed in the the PIC's flash memory. To avoid using the limited RAM. for (i = 0; i < (Bytes * BYTEBLOCK) && (DataType == DataTypes.Program); i += 2 * BYTEBLOCK) { // Due to the little endian design of the instruction format, bytes need to be reverse in order to be usable. bin = Convert.ToInt32(line.Substring(i + 5 * BYTEBLOCK + 1, BYTEBLOCK) + line.Substring(i + 4 * BYTEBLOCK + 1, BYTEBLOCK), 16); sourceISA.Add(new picWord(bin, BaseAddress)); } } else { // This is an insrucion block. for (i = 0; i < (Bytes * BYTEBLOCK) && (DataType == DataTypes.Program); i += 2 * BYTEBLOCK) { Queue<asmLabel> Labels = new Queue<asmLabel>(); Instruction I; asmLabel L; String[] args; // Due to the little endian design of the instruction format, bytes need to be reverse in order to be usable. bin = Convert.ToInt32(line.Substring(i + 5 * BYTEBLOCK + 1, BYTEBLOCK) + line.Substring(i + 4 * BYTEBLOCK + 1, BYTEBLOCK), 16); DataBytes.Add(bin); try { // Start the BT by modifying the CPU Registers. L = new asmLabel("", BaseAddress); I = new Instruction(bin, BaseAddress + i / (2 * BYTEBLOCK), ref rf, ref ptrTOS); args = I.getargs(); int addr = I.getAddress(); switch (I.getmnemonic()) { // Managing labels while decompiling. case "CALL": args = I.getargs(); addr = bin & 0x07FF; L.label = args[0]; L.address = addr; if (addr < I.getAddress()) sourceISA.Find(x => x.getAddress() == addr).setLabel(ref L); else Labels.Enqueue(new asmLabel(args[0], addr)); break; case "GOTO": args = I.getargs(); addr = bin & 0x07FF; L.label = args[0]; L.address = addr; if (addr < I.getAddress()) sourceISA.Find(x => x.getAddress() == addr).setLabel(ref L); else Labels.Enqueue(new asmLabel(args[0], addr)); break; default: break; } if ((Labels.Count > 0) && (I.getAddress() == Labels.Peek().address)) { L = Labels.Dequeue(); I.setLabel(ref L); } sourceISA.Add(I); } catch (Exception e) { Console.WriteLine("Something horrible happenned:"); Console.WriteLine(e.Message); Console.WriteLine("Instruction skipped."); //throw e; } } } CheckSum = Convert.ToInt32(line.Substring(line.Length - BYTEBLOCK, BYTEBLOCK), 16); } return sourceISA; }
/// <summary> /// Function to decompile the lines read from a hex file. /// /// </summary> /// <param name="hex">Hex code read as an list of strings.</param> /// <returns>List of strings with the decompiled assembly.</returns> public static List <picWord> decompile(List <String> hex) { int Bytes, BaseAddress, CheckSum, i, bin; DataTypes DataType; List <int> DataBytes = new List <int>(); List <picWord> sourceISR = new List <picWord>(); foreach (String line in hex) { Bytes = Convert.ToInt32(line.Substring(1, BYTEBLOCK), 16); BaseAddress = Convert.ToInt32(line.Substring(BYTEBLOCK + 1, 2 * BYTEBLOCK), 16) >> 1; DataType = (DataTypes)Convert.ToInt32(line.Substring(3 * BYTEBLOCK + 1, BYTEBLOCK), 16); if (BaseAddress == 0x2007) { bin = Convert.ToInt32(line.Substring(5 * BYTEBLOCK + 1, BYTEBLOCK) + line.Substring(4 * BYTEBLOCK + 1, BYTEBLOCK), 16); sourceISR.Add(new picWord(bin, BaseAddress)); continue; // This is a configuration word... and its extremely poorly documented... } else if (DataType == DataTypes.ExtendedAddress) { for (i = 0; i < (Bytes * BYTEBLOCK) && (DataType == DataTypes.Program); i += 2 * BYTEBLOCK) { // Due to the little endian design of the instruction format, bytes need to be reverse in order to be usable. bin = Convert.ToInt32(line.Substring(i + 5 * BYTEBLOCK + 1, BYTEBLOCK) + line.Substring(i + 4 * BYTEBLOCK + 1, BYTEBLOCK), 16); sourceISR.Add(new picWord(bin, BaseAddress)); } } else { for (i = 0; i < (Bytes * BYTEBLOCK) && (DataType == DataTypes.Program); i += 2 * BYTEBLOCK) { Instruction I; asmLabel L; String[] args; // Due to the little endian design of the instruction format, bytes need to be reverse in order to be usable. bin = Convert.ToInt32(line.Substring(i + 5 * BYTEBLOCK + 1, BYTEBLOCK) + line.Substring(i + 4 * BYTEBLOCK + 1, BYTEBLOCK), 16); DataBytes.Add(bin); try { // Start the BT by modifying the CPU Registers. L = new asmLabel("", BaseAddress); I = new Instruction(bin, BaseAddress + i / (2 * BYTEBLOCK), ref RF, ref ptrTOS); args = I.getargs(); int addr = I.getAddress(); switch (I.getmnemonic()) { // Managing labels while decompiling. case "CALL": args = I.getargs(); addr = bin & 0x07FF; L.label = args[0]; L.address = addr; if (addr < I.getAddress()) { sourceISR.Find(x => x.getAddress() == addr).setLabel(ref L); } else { Labels.Enqueue(new asmLabel(args[0], addr)); } break; case "GOTO": args = I.getargs(); addr = bin & 0x07FF; L.label = args[0]; L.address = addr; if (addr < I.getAddress()) { sourceISR.Find(x => x.getAddress() == addr).setLabel(ref L); } else { Labels.Enqueue(new asmLabel(args[0], addr)); } break; default: break; } if ((Labels.Count > 0) && (I.getAddress() == Labels.Peek().address)) { L = Labels.Dequeue(); I.setLabel(ref L); } sourceISR.Add(I); } catch (Exception e) { Console.WriteLine("Something horrible happenned:"); Console.WriteLine(e.Message); Console.WriteLine("Instruction skipped."); //throw e; } } } CheckSum = Convert.ToInt32(line.Substring(line.Length - BYTEBLOCK, BYTEBLOCK), 16); } return(sourceISR); }