Машинные команды разных размеров регистров
Мне зачем-то понадобились x86_64 опкоды и я решил попытался узнать их ассемблерными компиляторами. Написал простенький код:
mov ax, 0
mov eax, 0
mov rax, 0
У меня было два компилятора:
- 8086 Simulator(Android)
- FASM(Windows)
Также дополнительно искал в таблице https://looch-disasm.narod.ru/refe14.htm
Они выдали разный результат(разные ошибки). Если кратко то:
-------|mov ax|mov eax|mov rax|
x86 Sim| B8 | Error | 66 B8 |
FASM | B8 | 66 B8 | Error |
Скорее всего первый вариант неправильный(потому что 8086 Simulator скорее debuger, чем компилятор).
Так какой же опкод у "mov rax"(и есть ли такая же простая таблица, только для x86_64)?
Ответы (2 шт):
format binary as "bin"
org 0
use64
mov ax, 0
mov eax, 0
mov rax, 0
Результат 0x66 0xB8 0x00 0x00 0xB8 0x00 0x00 0x00 0x00 0x48 0xC7 0xC0 0x00 0x00 0x00 0x00
Опкод для mov rax, <константа64бита>
- 48 B8
:
48
- префикс REX.W, который означает "64-битная операция". Доступен только в 64-битном режиме!B8
- опкод операции "загрузить константу в AX/EAX/RAX"- после этого следует сама константа - 8 байт
Если константа умещается в 32-бита (со знаком), то ассемблер может также выдать 48 C7 C0
:
48
- префикс REX.WC7
- опкод "загрузить константу в память/регистр"C0
- байт операндов: "регистр AX/EAX/RAX"- после этого следует константа - 4 байта
Почему: 48 C7 C0
занимает 7 байт, а 48 B8
- 10 байт. Ассемблер выбирает более короткую инструкцию.
Процессоры x86 имеют 3 бинарно-несовместимых режима: 16-бит, 32-бита и 64-бита. Машинный код в разных режимах - разный. Ваши ассемблеры сгенерировали код для 16-битного режима - в этом режиме регистр RAX недоступен. 64-битные функции доступны только в 64-битном режиме.
Чтобы заставить FASM генерировать 64-битный код, используйте директиву use64
в начале файла.
Я не знаком с 8086 Simulator, но по названию кажется, что он поддерживает только режим 16-бит (как и оригинальный процессор 8086).
Для справки - правильные опкоды для 64-битного режима:
mov ax, <константа16>
-66 B8
mov eax, <константа32>
-B8
mov rax, <константа64>
-48 B8
(или48 C7 C0
)