Коротка відповідь : Ви не можете перекласти складений, пов'язаний виконуваний файл. Хоча технічно це можливо, це неможливо здійснити (див. Нижче). Однак якщо у вас є вихідний файл збірки (що містить інструкції та мітки), це дуже можливо зробити (хоча якщо ви якось отримаєте джерело збірки, якщо програма не написана в збірці, у вас повинен бути вихідний вихідний код програми як ну, тож вам буде краще скомпілювати його для початку для різної архітектури).
Довга відповідь :
QEMU та інші емулятори можуть перекладати інструкції на ходу, а тому запускати виконуваний файл на комп'ютері, для якого він не був складений. Чому б не зробити цей переклад достроково, а не на ходу, щоб прискорити процес?
Я знаю, що це може здатися простим в принципі, але на практиці це практично неможливо з кількох основних причин. Для початку різні набори інструкцій використовують значно різні режими адресації, різні структури коду, різні розміри слів, а деякі навіть не мають потрібних інструкцій.
Скажімо, вам потрібно було замінити інструкцію ще XYZ
двома інструкціями ABC
та DEF
. Тепер ви фактично змістили всі відносні / зміщені адреси у всій програмі з цього моменту, тому вам потрібно буде проаналізувати та пройти всю програму та оновити компенсації (як до, так і після зміни). Скажімо, один із зрушень суттєво зміниться - тепер вам потрібно змінити режими адресації, які можуть змінити розмір адреси. Це знову змусить вас повторно сканувати весь файл і перерахувати всі адреси тощо, і так далі, і четверте.
Коли ви пишете програми складання, ви можете використовувати мітки, але ЦП не робить - коли файл зібраний, усі мітки обчислюються як відносні, абсолютні або зміщені місця. Ви можете зрозуміти, чому це швидко стає нетривіальним завданням, а поруч неможливим. Заміна однієї інструкції може зажадати вас пройти всю програму сотні разів, перш ніж рухатись далі.
З моїх дещо обмежених знань про складання, більшість інструкцій, таких як MOV, ADD та інші, повинні бути переносними в архітектурах.
Так, але подивіться на проблеми, які я окреслив вище. А як щодо розміру слова машини? Довжина адреси? Чи навіть у нього є однакові режими адресації? Знову ж таки, ви не можете просто «знайти та замінити» інструкції. Кожен сегмент програми має конкретно визначену адресу. При зібранні програми переходи до інших міток замінюються буквальними або зміщеними адресами пам'яті.
Все, що не має прямого відображення, може бути відображене в якомусь іншому наборі інструкцій, оскільки всі машини Turing Complete. Це було б занадто складно? Хіба це взагалі не вийшло з якихось незнайомих мені причин? Це буде працювати, але не дасть кращих результатів, ніж використання емулятора?
Ви на 100% вірні, що це і можливо , і було б набагато швидше . Однак написати програму для її виконання надзвичайно складно і вкрай малоймовірно, якщо не для чого, крім тих питань, які я окреслив вище.
Якщо у вас був фактичний вихідний код збірки, було б тривіально перекласти машинний код в іншу архітектуру набору інструкцій. Однак сам машинний код зібраний , тому без джерела складання (який містить різні мітки, які використовуються для обчислення адрес пам'яті), стає неймовірно складно. Знову ж таки, зміна однієї інструкції може змінити зсуви пам’яті у всій програмі та вимагати сотні пропусків для повторного обчислення адрес.
Для виконання програми з кількома тисячами інструкцій потрібно десятки, якщо не сотні тисяч пропусків. Для відносно невеликих програм це може бути можливим, але пам’ятайте, що кількість пропусків буде експоненціально збільшуватися із кількістю машинних інструкцій у програмі. Для будь-якої програми досить гідного розміру це майже неможливо.