No se porqué pensé que te iba bien el Java, por eso se hizo así, ajajjajajajaja. En cuanto al Perls, no lo entiendo, aprendí en su día por obligación Python y me olvidé.
Se puede usar uno estandar como el C/C++, también uso C# y se puede usar el VB .net para los que le vengan bien.
Me sorprende que con Perl haces todo en pocas líneas comparado con otros lenguajes, impresionante.
Receurdo que mi idea no es dedicarme hacer un descompilador así sin más, hago uno con un lenguaje, el mejor que nos adaptemos para poder introducir números binarios de 16 bits y muestra los códigos en ensamblador. Se que PIC16F84A mueve 14 bits, por si acaso quiera en el futuro manejar los PIC18F por eso los dejo en 16 bits para leer.
Estaba trasteando con C# lo de introducir datos en bianrio, 0 y 1 de 16 dígitos.
Con un lenguaje, hay que emular la electrónica. Por ejemplo,usando la consola de C# introduces este código.
000010001000 0110
Precisamente el de este ejemplo:

Y su resultado es 0x0886 en hexadecimal.
Código de este programa binario para pruebas C#:
Código: Seleccionar todo
using System;
using System.Linq;
namespace Binario_cs
{
class Program
{
static void Main(string[] args)
{
// Título de la ventana.
Console.Title = "Binaro a ensamblador de PIC16F84A - C#";
// Muestra texto en pantalla pidiendo que introduzca los datos en binario.
Console.Write("Introduzca 16 números binarios: ");
String binario = Console.ReadLine();
Console.WriteLine();
if (binario.Count(x => x != '0' & x != '1') == 0 & binario.Length == 16)
{
int NumDec = Convert.ToInt32(binario, 2);
string NumHex = String.Format("0x{0:X4}", NumDec);
Console.WriteLine("Binario = " + binario);
Console.WriteLine("Decimal = " + NumDec.ToString());
Console.WriteLine("Hexadecimal = " + NumHex);
}
else
{
Console.WriteLine("Número incorrecto");
}
Console.ReadKey();
}
}
}
Aquí abajo el código en C# que antes era en Java. Introduces el valor 0x0886 y muestra el ensamblador del PIC esta instrucción MOVF PORTB, F. El 0x0886 en hexadecimal es exactamente lo mismo que este binario 000010001000 0110.
Código Descompila en C#:
Código: Seleccionar todo
using System;
namespace Descompilar
{
class Program01
{
static void Main(string[] args)
{
Console.Title = "Descompila con Chago - C#";
descompilar(new TroceadoEnBits(0x0886)); // 0x0886
}
static void print(String cadena)
{
// System.out.println(cadena);
Console.WriteLine(cadena);
Console.ReadKey(); // Pulse cualquier tecla para salir.
}
static String direccion(int operando)
{
String registro = "";
switch (operando)
{
// -----Bank0------------------
case 0x0: registro = "INDF"; break;
case 0x1: registro = "TMR0"; break;
case 0x2: registro = "PCL"; break;
case 0x3: registro = "STATUS"; break;
case 0x4: registro = "FSR"; break;
case 0x5: registro = "PORTA"; break;
case 0x6: registro = "PORTB"; break;
//chago aqui vete completando la tabla de REGISTER FILE MAP
case 0x8: registro = "EEDATA"; break;
case 0x9: registro = "EEADR"; break;
case 0xA: registro = "PCLATH"; break;
case 0xB: registro = "INTCON"; break;
//-----Bank1------------------
case 0x81: registro = "OPTION_REG"; break;
case 0x85: registro = "TRISA"; break;
case 0x86: registro = "TRISB"; break;
case 0x88: registro = "EECON1"; break;
case 0x89: registro = "EECON2"; break;
default:
// registro = Integer.toHexString(operando);
registro = Convert.ToString(operando);
break;
}
return registro;
}
static void descompilar(TroceadoEnBits opcode)
{
int bits1312 = opcode.dameRango(12, 12);// (0x3000 & opcode) >> 12; // extraemos los dos bits superiores
String operando;
switch (bits1312)
{
case 0:
// en este caso, el tercer nibble es la operación, el bit 7 es la suboperación o destino, y el resto, el operando
int nibble3 = opcode.dameRango(8, 11);//(0x0f00 & opcode) >> 8;
int bit7 = opcode.dameRango(7, 7);//(0x0080 & opcode) >> 7;
operando = direccion(opcode.dameRango(0, 6)); //direccion(0x007f & opcode);
String reg = "";
switch (bit7)
{
case 0: reg = ", W "; break;
case 1: reg = ", F "; break;
}
switch (nibble3)
{
case 0x0:
switch (bit7)
{
case 1: print("MOVWF " + operando); break;
case 0:
// aquí pueden ocurrir varios casos, según el primer nibble
int nibble1 = opcode.dameRango(0, 3);// (0x000f & opcode);
switch (nibble1)
{
case 0x0: print("NOP"); break;
case 0x4: print("CLRWDT"); break;
case 0x9: print("RETFIE"); break;
case 0x8: print("RETURN"); break;
case 0x3: print("SLEEP"); break;
}
break;
}
break;
case 0x1:
switch (bit7)
{
case 0: print("CLRW"); break;
case 1: print("CLRF " + operando); break;
}
break;
case 0x2: print("SUBWF " + operando + reg); break;
case 0x3: print("DECF " + operando + reg); break;
case 0x4: print("IORWF " + operando + reg); break;
case 0x5: print("ANDWF " + operando + reg); break;
case 0x6: print("XORWF " + operando + reg); break;
case 0x7: print("ADDWF " + operando + reg); break;
case 0x8: print("MOVF " + operando + reg); break;
case 0x9: print("COMF " + operando + reg); break;
case 0xA: print("INCF " + operando + reg); break;
case 0xB: print("DECFSZ " + operando + reg); break;
case 0xC: print("RRF " + operando + reg); break;
case 0xD: print("RLF " + operando + reg); break;
case 0xE: print("SWAPF " + operando + reg); break;
case 0xF: print("INCFSZ " + operando + reg); break;
}
break;
case 1:
// en este caso, los bits 12 y 11 es la suboperación, los bits 8, 9 y 10 es el número de bit, y el resto, el operandojj
int subop = opcode.dameRango(8, 10);//(0x0c00 & opcode) >> 10;
int bit = opcode.dameRango(7, 9);//(0x0380 & opcode) >> 7;
operando = opcode.dameRangoHex(0, 6);//Integer.toHexString(0x007f & opcode);
switch (subop)
{
case 0x0: print("BCF " + operando + bit); break;
case 0x1: print("BSF " + operando + bit); break;
case 0x2: print("BTFSC " + operando + bit); break;
case 0x3: print("BTFSS " + operando + bit); break;
}
break;
case 2:
// ver el bit 12. El resto es el operando
int bit11 = opcode.dameRango(11, 11);//(0x0800 & opcode) >> 11;
operando = opcode.dameRangoHex(0, 10);//Integer.toHexString(0x07ff & opcode);
switch (bit11)
{
case 0: print("CALL " + operando); break;
case 1: print("GOTO " + operando); break;
}
break;
case 3:
// el tercer nibble es la suboperación, y el resto, el operando
nibble3 = opcode.dameRango(8, 11);//(0x0f00 & opcode) >> 8;
operando = direccion(opcode.dameRango(0, 7));//direccion(0x00ff & opcode);
switch (nibble3)
{
case 0:
case 1:
case 2:
case 3: print("MOVLW " + operando); break;
case 4:
case 5:
case 6:
case 7: print("RETLW " + operando); break;
case 8: print("IORLW " + operando); break;
case 9: print("ANDLW " + operando); break;
case 0xa: print("XORLW " + operando); break;
case 0xb:
case 0xc:
//cc no sé que pasa con 0xd
print("SUBLW " + operando);
break;
case 0xe:
case 0xf:
print("ADDLW " + operando);
break;
}
break;
}
}
}
}
Clase TroceadoEnBits.cs:
Código: Seleccionar todo
using System;
namespace Descompilar
{
class TroceadoEnBits
{
int bits;
public TroceadoEnBits(int bits)
{
// super();
this.bits = bits;
}
public int getBits()
{
return bits;
}
public void setBits(int bits)
{
this.bits = bits;
}
public int dameRango(int ini, int fin)
{
if ((ini < 0 || ini > 13) || (fin < 0 || fin > 13)) throw new ArgumentException("ini y/o fin no pueden ser menores que 0 ni mayores que 13");
int[] desde = new int[14], hasta = new int[14];
// int desde[] = new int[14], hasta[] = new int[14];
desde[0] = 0x3fff; hasta[0] = 0x1;
desde[1] = 0x3ffe; hasta[1] = 0x3;
desde[2] = 0x3ffc; hasta[2] = 0x7;
desde[3] = 0x3ff8; hasta[3] = 0xf;
desde[4] = 0x3ff0; hasta[4] = 0x1f;
desde[5] = 0x3fe0; hasta[5] = 0x3f;
desde[6] = 0x3fc0; hasta[6] = 0x7f;
desde[7] = 0x3f80; hasta[7] = 0xff;
desde[8] = 0x3f00; hasta[8] = 0x1ff;
desde[9] = 0x3e00; hasta[9] = 0x3ff;
desde[10] = 0x3c00; hasta[10] = 0x7ff;
desde[11] = 0x3800; hasta[11] = 0xfff;
desde[12] = 0x3000; hasta[12] = 0x1fff;
desde[13] = 0x2000; hasta[13] = 0x3fff;
return (desde[ini] & hasta[fin] & bits) >> ini;
}
public String dameRangoHex(int ini, int fin)
{
// return Integer.toHexString(dameRango(ini, fin)); // Manera Chago en Java.
// return Convert.ToString(dameRango(ini,fin)); // Manera Acaymo en C#.
return dameRango(ini, fin).ToString("X4"); // Manera de un forero en C#.
}
}
}
Cuando funcione al 100 % en el ordenador de sobremesa, hay que adapatarlo al código de Arduino y colocar sus entradas digitales físicas y Led, también se incluirán los Led de estados, como los estados.
Toda esa electrónica me la ahorraré.
Antes que se me olvide, dejar la lista de instrucciones que puede ayudar.
https://en.wikipedia.org/wiki/PIC_instruction_listings
explorer escribió:Y algunos en código C.
Si haz visto una Web del lenguaje que sea, si es C, mejor que mejor, le hecharé un ojo. Creo que el ejemplo que pusiste en C de la página anterior tiene fallitos. Cuantas más págians de estas haya mejor, la verdad, me cuesta encontrarlas. Ejemplos en C o otro lenguaje sobre compilar.
Saludos.