C'est une question très intéressante. Il existe des millions d'instructions, mais seulement quelques-unes très couramment utilisées.
La première chose que je regarderais est l'origine et l'utilisation prévue. Si vous pensez qu'il a été conçu aux États-Unis, vous viserez principalement les processeurs avec des fiches techniques disponibles en anglais, par exemple. S'il a été conçu en Asie, il existe un certain nombre de processeurs qu'ils utilisent pour les appareils fabriqués en série que les ingénieurs américains voient rarement. Même l'Europe a quelques processeurs plus courants que d'autres.
J'examinerais ensuite la taille et la fonctionnalité du code (en supposant que vous savez ce que fait le code dans une certaine mesure). S'il s'agit de quelques mégaoctets de code, vous pouvez à peu près réduire la plupart des processeurs 8 bits intégrés et commencer à regarder des appareils plus grands avec une mémoire externe. S'il s'agit de quelques kilo-octets ou moins, vous voudrez plutôt vous concentrer sur des appareils plus petits et moins chers. Si la fonctionnalité est simple, il peut même s'agir d'un code pour un processeur quatre bits.
À ce stade, il vaut la peine d'examiner la structure de la mémoire. Il y aura probablement une section de programme et une section de données au minimum. S'il s'agit d'un fichier binaire (par rapport à un enregistrement hexadécimal d'Intel ou de Motorola), vous avez peu d'informations sur l'emplacement en mémoire de certains blocs de données. Un éditeur hexadécimal peut afficher certains modèles. Si elle vient dans un format d'enregistrement hexadécimal ou s, vous pourriez avoir plus d'informations sur la structure de la mémoire du processeur auquel elle est destinée. Certains processeurs sont réinitialisés à l'emplacement de mémoire de programme 0, certains à l'emplacement de mémoire le plus élevé. Le programme peut inclure des valeurs initiales EEPROM dans un emplacement mémoire séparé. S'il est destiné à un processeur sécurisé (tel qu'utilisé dans le secteur bancaire), il peut même avoir des clés de sécurité pour un emplacement de mémoire impair.
Selon la langue dans laquelle il a été programmé, vous pourriez avoir des indices supplémentaires. S'il a été programmé en C ou dans un langage procédural similaire, les fonctions commenceront presque toujours par une séquence d'instructions pour enregistrer certains registres dans la pile (beaucoup de push) puis juste avant de retourner beaucoup de pops pour retourner les valeurs d'origine de la pile . Si vous pouvez faire une reconnaissance de modèle, vous trouverez un grand nombre de ces séquences tout au long et vous pourrez peut-être déterminer quelles instructions sont les instructions push / pop les plus susceptibles, retourner, etc., ce qui pourrait affiner un peu vos choix.
S'il s'agit d'un appareil intégré avec des interruptions, il peut avoir une table de vecteurs d'interruption, qui ressemblera à un tas de sauts vers différents emplacements de mémoire dans un grand bloc, probablement à un emplacement pratique (adresse de 0x ??? 0 par exemple) . Les tables de sauts sont également utilisées ailleurs pour d'autres choses, mais si vous pouvez localiser une séquence d'instructions qui semblent identiques à l'exception de l'adresse à laquelle vous souhaitez sauter, vous pourrez peut-être déduire à quoi ressemble une instruction de saut, et encore une fois restreindre vos choix vers le bas.
À ce stade, je commencerais par les architectures de processeur les plus courantes et verrais si quelque chose est en corrélation. x86, arm, mips, 8051, avr, pic, powerpc, Z80, 68k, 6502, etc, etc, etc. Il existe des listes de processeurs et de jeux d'instructions courants - au moins dans le monde anglophone - qui pourraient s'avérer utiles.
Je ne connais aucun outil automatisé qui pourrait aider à cela, mais MAME émule un grand nombre d'architectures de processeur, et une méthode possible est d'exécuter le code via un certain nombre de processeurs et de regarder les registres pour voir si quelque chose clique selon ce que vous connaissez le design.