La réponse courte : vous ne pouvez pas traduire un exécutable compilé et lié. Bien que techniquement possible, il est hautement improbable d'accomplir (voir ci-dessous). Cependant , si vous avez le fichier source de l' assembly (contenant les instructions et les étiquettes), il est très possible de le faire (bien que si vous obtenez en quelque sorte la source de l'assembly, à moins que le programme ne soit écrit en assembly, vous devriez avoir le code source du programme d'origine comme eh bien, vous feriez mieux de le compiler pour les différentes architectures pour commencer).
La réponse longue :
QEMU et d'autres émulateurs peuvent traduire les instructions à la volée, et donc exécuter un exécutable sur un ordinateur pour lequel il n'a pas été compilé. Pourquoi ne pas faire cette traduction à l'avance, plutôt qu'à la volée afin d'accélérer le processus?
Je sais que cela peut sembler facile en principe, mais en pratique, c'est presque impossible pour plusieurs raisons principales. Pour commencer, différents jeux d'instructions utilisent des modes d'adressage largement différents, différentes structures d'opcode, différentes tailles de mot et certains n'ont même pas les instructions dont vous avez besoin.
Supposons que vous deviez remplacer l'instruction XYZ
par deux autres instructions, ABC
et DEF
. À partir de ce moment, vous avez effectivement déplacé toutes les adresses relatives / décalées dans l'ensemble du programme, vous devez donc analyser et parcourir le programme entier et mettre à jour les décalages (avant et après la modification). Maintenant, disons que l'un des décalages change de manière significative - vous devez maintenant changer les modes d'adressage, ce qui pourrait changer la taille de l'adresse. Cela vous obligera à nouveau à analyser à nouveau l'intégralité du fichier et à recalculer toutes les adresses, et ainsi de suite et ainsi de suite.
Lorsque vous écrivez des programmes d'assemblage, vous pouvez utiliser des étiquettes, mais pas l'UC - lorsque le fichier est assemblé, toutes les étiquettes sont calculées pour être des emplacements relatifs, absolus ou décalés. Vous pouvez voir pourquoi cela devient rapidement une tâche non triviale et presque impossible. Le remplacement d'une seule instruction peut vous obliger à parcourir l'ensemble du programme des centaines de fois avant de continuer.
De ma connaissance quelque peu limitée de l'assemblage, la plupart des instructions comme MOV, ADD et autres devraient être portables à travers les architectures.
Oui, mais regardez les problèmes que j'ai décrits ci-dessus. Qu'en est-il de la taille des mots de la machine? Longueur de l'adresse? At-il même les mêmes modes d'adressage? Encore une fois, vous ne pouvez pas simplement "rechercher et remplacer" les instructions. Chaque segment d'un programme a une adresse spécifiquement définie. Les sauts vers d'autres étiquettes sont remplacés par des adresses mémoire littérales ou décalées lorsqu'un programme est assemblé.
Tout ce qui n'a pas de mappage direct peut être mappé à un autre ensemble d'instructions, car toutes les machines sont Turing Complete. Est-ce que cela serait trop compliqué? Cela ne fonctionnerait-il pas du tout pour une raison que je ne connais pas? Cela fonctionnerait-il, mais ne donnerait-il pas de meilleurs résultats que l'utilisation d'un émulateur?
Vous avez 100% raison que c'est à la fois possible et serait beaucoup plus rapide . Cependant, écrire un programme pour y parvenir est incroyablement difficile et hautement improbable, sinon pour autre chose que les problèmes que j'ai décrits ci-dessus.
Si vous disposiez du code source de l'assembly, il serait trivial de traduire le code machine en une autre architecture de jeu d'instructions. Le code machine lui-même, cependant, est assemblé , donc sans la source d'assemblage (qui contient diverses étiquettes utilisées pour calculer les adresses mémoire), cela devient incroyablement difficile. Encore une fois, la modification d'une seule instruction peut modifier les décalages de mémoire dans l'ensemble du programme et nécessiter des centaines de passes pour recalculer les adresses.
Faire cela pour un programme avec quelques milliers d'instructions nécessiterait des dizaines sinon des centaines de milliers de passes. Pour des programmes relativement petits, cela peut être possible, mais n'oubliez pas que le nombre de passes augmentera de façon exponentielle avec le nombre d'instructions machine dans le programme. Pour tout programme d'une taille suffisamment décente, c'est presque impossible.