La risposta breve : non è possibile tradurre un eseguibile compilato e collegato. Sebbene tecnicamente possibile, è altamente improbabile da realizzare (vedi sotto). Tuttavia , se si dispone del file sorgente dell'assembly (contenente le istruzioni e le etichette), è molto possibile farlo (anche se in qualche modo si ottiene l'origine dell'assembly, a meno che il programma non sia scritto in assembly, è necessario disporre del codice sorgente originale del programma come bene, quindi faresti meglio a compilarlo per la diversa architettura per cominciare).
La lunga risposta :
QEMU e altri emulatori possono tradurre le istruzioni al volo e quindi eseguire un eseguibile su un computer per il quale non è stato compilato. Perché non fare questa traduzione in anticipo, anziché al volo per accelerare il processo?
So che in linea di principio potrebbe sembrare facile, ma in pratica è quasi impossibile per alcuni motivi principali. Per iniziare, diversi set di istruzioni utilizzano modalità di indirizzamento in gran parte diverse, strutture di codici operativi diverse, dimensioni delle parole diverse e alcune non hanno nemmeno le istruzioni necessarie.
Diciamo che dovevi sostituire le istruzioni XYZ
con altre due istruzioni ABC
e DEF
. Ora hai effettivamente spostato tutti gli indirizzi relativi / offset nell'intero programma da quel punto in poi, quindi dovrai analizzare e passare attraverso l'intero programma e aggiornare gli offset (sia prima che dopo la modifica). Ora, supponiamo che uno degli offset cambi in modo significativo - ora è necessario modificare le modalità di indirizzamento, che potrebbero cambiare la dimensione dell'indirizzo. Questo ti costringerà di nuovo a scansionare nuovamente l'intero file e ricalcolare tutti gli indirizzi, e così via e così quarto.
Quando si scrivono programmi di assemblaggio, è possibile utilizzare le etichette, ma la CPU no: quando il file viene assemblato, tutte le etichette vengono calcolate come posizioni relative, assolute o offset. Puoi capire perché questo diventa rapidamente un compito non banale e quasi impossibile. La sostituzione di una singola istruzione potrebbe richiedere di passare l'intero programma centinaia di volte prima di procedere.
Dalla mia conoscenza piuttosto limitata dell'assemblaggio, la maggior parte delle istruzioni come MOV, ADD e altre dovrebbero essere trasportabili attraverso architetture.
Sì, ma guarda ai problemi che ho descritto sopra. E le dimensioni della parola della macchina? Indirizzo lunghezza? Ha anche le stesse modalità di indirizzamento? Ancora una volta, non puoi semplicemente "trovare e sostituire" le istruzioni. Ogni segmento di un programma ha un indirizzo specificamente definito. I salti su altre etichette vengono sostituiti con indirizzi di memoria letterali o offset quando viene assemblato un programma.
Tutto ciò che non ha una mappatura diretta può essere mappato su un altro set di istruzioni, poiché tutte le macchine sono Turing complete. Fare questo sarebbe troppo complicato? Non funzionerebbe affatto per qualche motivo con cui non ho familiarità? Funzionerebbe, ma non produrrebbe risultati migliori rispetto all'utilizzo di un emulatore?
Hai ragione al 100% sul fatto che sia possibile e sarebbe molto più veloce . Tuttavia, scrivere un programma per raggiungere questo obiettivo è incredibilmente difficile e altamente improbabile, se non per altro, tranne i problemi che ho descritto sopra.
Se si disponesse dell'attuale codice sorgente dell'assembly, sarebbe banale tradurre il codice macchina in un'altra architettura di set di istruzioni. Il codice macchina stesso, tuttavia, è assemblato , quindi senza la sorgente assembly (che contiene varie etichette utilizzate per calcolare gli indirizzi di memoria), diventa incredibilmente difficile. Ancora una volta, la modifica di una singola istruzione potrebbe modificare gli offset di memoria nell'intero programma e richiedere centinaia di passaggi per ricalcolare gli indirizzi.
Fare questo per un programma con poche migliaia di istruzioni richiederebbe decine se non centinaia di migliaia di passaggi. Per programmi relativamente piccoli, questo può essere possibile, ma ricorda che il numero di passaggi aumenterà esponenzialmente con il numero di istruzioni della macchina nel programma. Per qualsiasi programma di dimensioni abbastanza decenti, è quasi impossibile.