Esta es una pregunta muy interesante. Hay millones de instrucciones establecidas allí, pero solo un puñado de instrucciones muy usadas.
Lo primero que vería es el origen y el uso previsto. Si sospechas que fue diseñado en los EE. UU., Estarías apuntando principalmente a procesadores con hojas de datos disponibles en inglés, por ejemplo. Si fue diseñado en Asia, entonces hay una serie de procesadores que utilizan para dispositivos fabricados en masa que los ingenieros de EE. UU. Rara vez ven. Incluso Europa tiene unos pocos procesadores que son más comunes que otros.
Luego echaría un vistazo al tamaño y la funcionalidad del código (asumiendo que sabes lo que el código hace hasta cierto punto). Si son unos pocos megabytes de código, puede descontar la mayoría de los procesadores de 8 bits integrados y comenzar a buscar dispositivos más grandes con memoria externa. Si son unos pocos kilobytes o menos, entonces querrás centrarte en dispositivos más pequeños y baratos. Si la funcionalidad es simple, incluso podría ser un código para un procesador de cuatro bits.
En este punto, vale la pena mirar la estructura de la memoria. Es probable que haya una sección del programa y una sección de datos como mínimo. Si se trata de un archivo binario (en comparación con Intel hex o el registro de motorola), entonces tiene poca idea de dónde se colocan ciertos fragmentos de datos en la memoria. Un editor hexadecimal podría mostrar algunos patrones. Si viene en formato de registro hexadecimal, es posible que tenga más información sobre la estructura de memoria del procesador para el que está diseñada. Algunos procesadores se reinician en la ubicación de memoria del programa 0, algunos en la ubicación de memoria más alta. El programa puede incluir valores iniciales de EEPROM en una ubicación de memoria separada. Si está destinado a un procesador seguro (como se usa en banca), incluso podría tener claves de seguridad para una ubicación de memoria impar.
Dependiendo del idioma en el que se programó, es posible que tengas algunas pistas adicionales. Si se programó en C o en un lenguaje de procedimiento similar, entonces las funciones casi siempre comenzarán con una secuencia de instrucciones para guardar ciertos registros en la pila (muchos empujes) y luego justo antes de devolver muchos pops para devolver los valores originales de la pila. . Si puede hacer un reconocimiento de patrones, encontrará muchas de estas secuencias en todo el proceso, y podrá determinar qué instrucciones son las más probables, las de retorno, etc., que podrían reducir un poco sus opciones.
Si es un dispositivo incorporado con interrupciones, puede tener una tabla de vectores de interrupción, que se verá como un montón de saltos a diferentes ubicaciones de memoria en un bloque grande, probablemente en una ubicación conveniente (dirección de 0x ??? 0 por ejemplo). Las tablas de salto se usan en otros lugares para otras cosas también, pero si puede ubicar una secuencia de instrucciones que parezcan idénticas, excepto en cuál sería la dirección a la que saltar, es posible que pueda inferir cómo se ve una instrucción de salto y, de nuevo, restringir tus elecciones hacia abajo.
En ese momento, comenzaría con las arquitecturas de procesadores más comunes y vería si algo se correlaciona. x86, arm, mips, 8051, avr, pic, powerpc, Z80, 68k, 6502, etc, etc, etc. Hay listas de procesadores y conjuntos de instrucciones comunes, al menos en el mundo de habla inglesa, que pueden ser útiles.
No tengo conocimiento de ninguna herramienta automatizada que ayude con esto, pero MAME emula una gran cantidad de arquitecturas de procesadores, y un método posible es ejecutar el código a través de varios procesadores y ver los registros para ver si hace clic. De acuerdo con lo que sabes sobre el diseño.