A resposta curta : você não pode traduzir um executável vinculado compilado. Embora 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 os rótulos), é muito possível fazê-lo (embora, de alguma maneira, você obtenha a fonte do assembly, a menos que o programa seja escrito em assembly, você deve ter o código fonte do programa original como bem, é melhor compilá-lo para a arquitetura diferente).
A resposta longa :
O QEMU e outros emuladores podem traduzir as instruções rapidamente e, portanto, executar um executável em um computador para o qual não foi compilado. Por que não fazer essa tradução antes do tempo, e não em tempo real, a fim de acelerar o processo?
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, diferentes estruturas de código de operação, tamanhos diferentes de palavras e alguns nem sequer têm as instruções necessárias.
Digamos que você precise substituir as instruções XYZ
por mais duas instruções, ABC
e DEF
. Agora, você mudou efetivamente todos os endereços relativos / offset em todo o programa a partir desse ponto, para que você precise analisar e percorrer todo o programa e atualizar os desvios (antes e depois da alteração). Agora, digamos que uma das compensações mude significativamente - agora você precisa alterar os modos de endereçamento, o que pode alterar o tamanho do endereço. Isso forçará novamente a varredura de todo o arquivo e a recálculo de todos os endereços, e assim por diante.
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 por que isso rapidamente se torna uma tarefa não trivial e quase impossível. Substituir uma única instrução pode exigir que você passe pelo programa inteiro centenas de vezes antes de prosseguir.
Pelo meu conhecimento um tanto limitado de montagem, a maioria das instruções como MOV, ADD e outras devem ser portáveis entre arquiteturas.
Sim, mas observe os problemas descritos acima. E o tamanho da palavra da máquina? Comprimento do endereço? Ele tem os mesmos modos de endereçamento? Novamente, você não pode simplesmente "encontrar e substituir" instruções. Cada segmento de um programa possui um endereço definido especificamente. Os saltos para outras etiquetas são substituídos por endereços de memória literal ou offset quando um programa é montado.
Qualquer coisa que não tenha um mapeamento direto pode ser mapeada para outro conjunto de instruções, pois todas as máquinas são Turing Complete. Fazer isso seria muito complicado? Não funcionaria por algum motivo que eu não estou familiarizado? Funcionaria, mas não produziria melhores resultados do que usar um emulador?
Você está 100% correto de que isso é possível e seria muito mais rápido . No entanto, escrever um programa para fazer isso é incrivelmente difícil e altamente improvável, se não for por qualquer coisa, exceto pelos problemas descritos acima.
Se você tivesse o código-fonte real da montagem, seria trivial traduzir o código da máquina para outra arquitetura do conjunto de instruções. O próprio código da máquina, no entanto, é montado ; portanto, sem a fonte do assembly (que contém várias etiquetas usadas para calcular endereços de memória), torna-se incrivelmente difícil. Mais uma vez, alterar uma única instrução pode alterar os desvios 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, senã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 da máquina no programa. Para qualquer programa de tamanho decente, é quase impossível.