A resposta curta : você não pode traduzir um executável vinculado compilado. Embora seja tecnicamente possível, é altamente improvável de realizar (veja abaixo). No entanto , se você tiver o arquivo de origem do assembly (contendo as instruções e rótulos), é muito possível fazer (embora se você de alguma forma obtiver a fonte de montagem, a menos que o programa é escrito em assembly, você deve ter o código-fonte do programa original também, então seria melhor compilar para a arquitetura diferente para começar).
A resposta longa :
QEMU and other emulators can translate the instructions on the fly, and therefore run an executable on a computer it wasn't compiled for. Why not do this translation ahead of time, instead of on the fly in order to speed up the process?
Eu sei que pode parecer fácil em princípio, mas na prática, é quase impossível por algumas razões principais. Para começar, diferentes conjuntos de instruções usam modos de endereçamento amplamente diferentes, estruturas opcode diferentes, tamanhos de palavras diferentes, e alguns nem têm as instruções que você precisa.
Digamos que você precise substituir a instrução XYZ
por mais duas instruções, ABC
e DEF
. Agora você deslocou efetivamente todos os endereços relativos / deslocados de todo o programa a partir de então, então você precisaria analisar e percorrer todo o programa e atualizar os deslocamentos (antes e depois da mudança). Agora, digamos que um dos deslocamentos muda significativamente - agora você precisa alterar os modos de endereçamento, o que pode alterar o tamanho do endereço. Isso irá forçá-lo novamente a varrer novamente todo o arquivo e recalcular todos os endereços, e assim por diante e em quarto lugar.
Quando você escreve programas de montagem, pode usar rótulos, mas a CPU não - quando o arquivo é montado, todos os rótulos são calculados para serem relativos, absolutos ou deslocados. Você pode ver porque isso rapidamente se torna uma tarefa não trivial e quase impossível. Substituir uma instrução single pode exigir que você passe por todo o programa centenas de vezes antes de prosseguir.
From my somewhat limited knowledge of assembly, most of the instructions like MOV, ADD and others should be portable across architectures.
Sim, mas observe os problemas que descrevi acima. E quanto ao tamanho da palavra da máquina? Comprimento do endereço? Tem mesmo os mesmos modos de endereçamento? Novamente, você não pode simplesmente "encontrar e substituir" instruções. Cada segmento de um programa tem um endereço especificamente definido. Saltos para outras etiquetas são substituídos por endereços literais ou de memória offset quando um programa é montado.
Anything that's doesn't have a direct mapping could be mapped to some other set of instructions, since all machines are Turing Complete. Would doing this be too complicated? Would it not work at all for some reason I'm unfamiliar with? Would it work, but yield no better results than using an emulator?
Você está 100% correto de que é possível e seria muito mais rápido . No entanto, escrever um programa para realizar isso é incrivelmente difícil e altamente improvável, se não for para qualquer coisa, exceto os problemas que descrevi acima.
Se você tivesse o código-fonte real do assembly, seria trivial traduzir o código da máquina para outra arquitetura de conjunto de instruções. O próprio código da máquina, no entanto, é montado , portanto, sem a fonte de montagem (que contém vários rótulos usados para calcular os endereços de memória), torna-se incrivelmente difícil. Novamente, a alteração de uma única instrução pode alterar os deslocamentos de memória em todo o programa e exigir centenas de passes para recalcular os endereços.
Fazer isso para um programa com alguns milhares de instruções exigiria dezenas, se não centenas, de milhares de passes. Para programas relativamente pequenos, isso pode ser possível, mas lembre-se de que o número de passes aumentará exponencialmente com o número de instruções de máquina no programa. Para qualquer programa de tamanho decente, é quase impossível.