Die kurze Antwort : Sie können eine kompilierte, verknüpfte ausführbare Datei nicht übersetzen. Obwohl dies technisch möglich ist, ist dies höchst unwahrscheinlich (siehe unten). Allerdings , wenn Sie die haben Assembler - Quelldatei (mit den Anweisungen und Etiketten), ist es sehr gut möglich , zu tun (obwohl , wenn Sie irgendwie die Montage Quelle erhalten, es sei denn , das Programm in Assembler geschrieben ist, sollten Sie das ursprüngliche Programm Quellcode als Nun, es ist besser, wenn Sie es für die verschiedenen Architekturen kompilieren.
Die lange Antwort :
QEMU und andere Emulatoren können die Anweisungen im laufenden Betrieb übersetzen und daher eine ausführbare Datei auf einem Computer ausführen, für den sie nicht kompiliert wurden. Warum nicht diese Übersetzung im Voraus und nicht im laufenden Betrieb durchführen, um den Prozess zu beschleunigen?
Ich weiß, dass es im Prinzip einfach erscheinen mag, aber in der Praxis ist es aus einigen Hauptgründen fast unmöglich. Zu Beginn verwenden verschiedene Befehlssätze stark unterschiedliche Adressierungsmodi, unterschiedliche Opcode-Strukturen, unterschiedliche Wortgrößen, und einige verfügen nicht einmal über die Anweisungen, die Sie benötigen.
Angenommen, Sie mussten die Anweisung XYZ
durch zwei weitere Anweisungen ersetzen , ABC
und DEF
. Jetzt haben Sie effektiv alle relativen / Offset-Adressen im gesamten Programm von diesem Punkt an verschoben, sodass Sie das gesamte Programm analysieren und durchgehen und die Offsets (sowohl vor als auch nach der Änderung) aktualisieren müssen. Angenommen, einer der Offsets ändert sich erheblich. Jetzt müssen Sie die Adressierungsmodi ändern, wodurch sich die Größe der Adresse ändern kann. Dadurch werden Sie erneut gezwungen, die gesamte Datei erneut zu scannen und alle Adressen neu zu berechnen, und so weiter und so fort.
Wenn Sie Assembly-Programme schreiben, verwenden Sie möglicherweise Beschriftungen, die CPU jedoch nicht. Wenn die Datei zusammengestellt wird, werden alle Beschriftungen als relative, absolute oder versetzte Positionen berechnet. Sie können sehen, warum dies schnell zu einer nicht trivialen Aufgabe wird und nahezu unmöglich ist. Wenn Sie eine einzelne Anweisung ersetzen möchten, müssen Sie möglicherweise das gesamte Programm hunderte Male durchlaufen, bevor Sie fortfahren können.
Aufgrund meiner etwas eingeschränkten Kenntnisse in der Montage sollten die meisten Anweisungen wie MOV, ADD und andere architekturübergreifend portierbar sein.
Ja, aber schauen Sie sich die oben beschriebenen Probleme an. Was ist mit der Wortgröße der Maschine? Adresslänge? Hat es überhaupt die gleichen Adressierungsmodi? Auch hier können Sie Anweisungen nicht einfach "finden und ersetzen". Jedes Segment eines Programms hat eine spezifisch definierte Adresse. Sprünge zu anderen Bezeichnungen werden beim Zusammenstellen eines Programms durch Literal- oder Offset-Speicheradressen ersetzt.
Alles, was keine direkte Zuordnung hat, kann einem anderen Befehlssatz zugeordnet werden, da alle Maschinen Turing Complete sind. Wäre das zu kompliziert? Würde es aus irgendeinem Grund, den ich nicht kenne, überhaupt nicht funktionieren? Würde es funktionieren, aber keine besseren Ergebnisse erzielen als mit einem Emulator?
Sie haben zu 100% Recht, dass beides möglich ist und viel schneller wäre . Das Schreiben eines Programms, um dies zu erreichen, ist jedoch unglaublich schwierig und höchst unwahrscheinlich, wenn nicht für irgendetwas anderes als die oben beschriebenen Probleme.
Wenn Sie den eigentlichen Assembly-Quellcode hätten, wäre es trivial, den Maschinencode in eine andere Befehlssatzarchitektur zu übersetzen. Der Maschinencode selbst wird jedoch zusammengestellt , sodass es ohne die Assembly-Quelle (die verschiedene Beschriftungen enthält, die zum Berechnen von Speicheradressen verwendet werden) unglaublich schwierig wird. Das Ändern eines einzelnen Befehls kann wiederum die Speicherversätze im gesamten Programm ändern und Hunderte von Durchläufen erfordern, um die Adressen neu zu berechnen.
Dies für ein Programm mit einigen tausend Anweisungen zu tun, würde Zehntausende, wenn nicht Hunderttausende von Durchgängen erfordern. Bei relativ kleinen Programmen ist dies möglicherweise möglich. Beachten Sie jedoch, dass die Anzahl der Durchgänge mit der Anzahl der Maschinenanweisungen im Programm exponentiell zunimmt. Für jedes Programm mit einer angemessenen Größe ist dies nahezu unmöglich.