Krótka odpowiedź : nie można przetłumaczyć skompilowanego, połączonego pliku wykonywalnego. Chociaż jest to technicznie możliwe, jest wysoce nieprawdopodobne do osiągnięcia (patrz poniżej). Jeśli jednak masz plik źródłowy zestawu (zawierający instrukcje i etykiety), jest to bardzo możliwe (chociaż jeśli w jakiś sposób uzyskasz źródło zestawu, chyba że program jest napisany w zestawie, powinieneś mieć oryginalny kod źródłowy programu jako cóż, lepiej więc skompiluj to dla innej architektury na początek).
Długa odpowiedź :
QEMU i inne emulatory mogą tłumaczyć instrukcje w locie, a zatem uruchomić plik wykonywalny na komputerze, dla którego nie został skompilowany. Dlaczego nie zrobić tego tłumaczenia z wyprzedzeniem, zamiast w locie, aby przyspieszyć proces?
Wiem, że może to wydawać się łatwe, ale w praktyce jest to prawie niemożliwe z kilku głównych powodów. Na początek różne zestawy instrukcji używają zasadniczo różnych trybów adresowania, różnych struktur kodu operacyjnego, różnych rozmiarów słów, a niektóre nawet nie mają potrzebnych instrukcji.
Powiedzmy, że musisz zastąpić instrukcję XYZ
dwiema kolejnymi instrukcjami ABC
oraz DEF
. Teraz skutecznie przesunąłeś wszystkie adresy względne / przesunięcia w całym programie od tego momentu, więc musisz przeanalizować i przejść przez cały program i zaktualizować przesunięcia (zarówno przed zmianą, jak i po niej). Powiedzmy, że jedna z przesunięć znacznie się zmienia - teraz musisz zmienić tryby adresowania, które mogą zmienić rozmiar adresu. To znowu zmusi cię do ponownego przeskanowania całego pliku i ponownego obliczenia wszystkich adresów, i tak dalej, i tak po czwarte.
Podczas pisania programów asemblerowych możesz używać etykiet, ale procesor tego nie robi - po skompletowaniu pliku wszystkie etykiety są obliczane jako lokalizacje względne, bezwzględne lub przesunięte. Możesz zobaczyć, dlaczego to szybko staje się nietrywialnym zadaniem, a prawie niemożliwe. Zastąpienie pojedynczej instrukcji może wymagać przejścia całego programu setki razy przed przejściem dalej.
Z mojej nieco ograniczonej wiedzy na temat montażu większość instrukcji takich jak MOV, ADD i inne powinny być przenośne w różnych architekturach.
Tak, ale spójrz na problemy, które przedstawiłem powyżej. Co z rozmiarem słowa maszyny? Długość adresu? Czy ma nawet te same tryby adresowania? Ponownie nie możesz po prostu „znaleźć i zamienić” instrukcje. Każdy segment programu ma konkretnie określony adres. Przeskoki do innych etykiet są zastępowane literalnymi lub przesuniętymi adresami pamięci podczas składania programu.
Wszystko, co nie ma bezpośredniego mapowania, można zmapować na inny zestaw instrukcji, ponieważ wszystkie maszyny są Turing Complete. Czy zrobienie tego byłoby zbyt skomplikowane? Czy to nie zadziałałoby z jakiegoś powodu, którego nie znam? Czy to zadziała, ale nie przyniesie lepszych rezultatów niż użycie emulatora?
Masz 100% rację, że jest to możliwe i byłoby o wiele szybsze . Jednak napisanie programu do osiągnięcia tego celu jest niewiarygodnie trudne i wysoce nieprawdopodobne, jeśli nie z wyjątkiem problemów, które przedstawiłem powyżej.
Jeśli posiadasz aktualny kod źródłowy zestawu, przetłumaczenie kodu maszynowego na inną architekturę zestawu instrukcji byłoby banalne. Sam kod maszynowy jest jednak składany , więc bez źródła asemblera (które zawiera różne etykiety używane do obliczania adresów pamięci) staje się niezwykle trudne. Ponownie zmiana pojedynczej instrukcji może zmienić przesunięcia pamięci w całym programie i wymagać setek przejść w celu ponownego obliczenia adresów.
Wykonanie tego dla programu z kilkoma tysiącami instrukcji wymagałoby dziesiątek, jeśli nie setek tysięcy przejść. W przypadku stosunkowo małych programów może to być możliwe, ale pamiętaj, że liczba przejść wzrośnie wykładniczo wraz z liczbą instrukcji maszynowych w programie. Dla każdego programu o wystarczającej wielkości jest to prawie niemożliwe.