Машинные команды разных размеров регистров

Мне зачем-то понадобились x86_64 опкоды и я решил попытался узнать их ассемблерными компиляторами. Написал простенький код:

mov ax, 0
mov eax, 0
mov rax, 0

У меня было два компилятора:

  1. 8086 Simulator(Android)
  2. 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 шт):

Автор решения: Jack Katch
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

→ Ссылка
Автор решения: user22405329

Опкод для mov rax, <константа64бита> - 48 B8:

  • 48 - префикс REX.W, который означает "64-битная операция". Доступен только в 64-битном режиме!
  • B8 - опкод операции "загрузить константу в AX/EAX/RAX"
  • после этого следует сама константа - 8 байт

Если константа умещается в 32-бита (со знаком), то ассемблер может также выдать 48 C7 C0:

  • 48 - префикс REX.W
  • C7 - опкод "загрузить константу в память/регистр"
  • 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)
→ Ссылка