Существует несколько кодов операций для добавления немедленного в 64-битный регистр
REX.W + 05 id ADD RAX, imm32 Add imm32 sign-extended to 64-bits to RAX.
REX.W + 81 /0 id ADD r/m64, imm32 Add imm32 sign-extended to 64-bits to r/m64.
REX.W + 83 /0 ib ADD r/m64, imm8 Add sign-extended imm8 to r/m64.
https://www.felixcloutier.com/x86/ADD.html
, поскольку 01
помещается в байт, ваш ассемблер использует код операции 83
чтобы сохранить длину инструкции.Если вы попробуете add rax, 100000000
или что-то подобное, вы получите код операции 05
Теперь для принудительного другого декодирования вместо более эффективного вам потребуется определить некоторый синтаксис в ассемблере.Например, nasm использует ключевое слово strict
mov eax, 1 ; 5 bytes to encode (B8 imm32)
mov rax, strict dword 1 ; 7 bytes: REX mov r/m64, sign-extended-imm32. NASM optimizes mov rax,1 to the 5B version, but dword or strict dword stops it for some reason
mov rax, strict qword 1 ; 10 bytes
Почему NASM в Linux изменяет регистры в сборке x86_64
Теперь, если вы посмотрите наВ таблице близко вы можете увидеть что-то странное
05 iw ADD AX, imm16 Add imm16 to AX.
05 id ADD EAX, imm32 Add imm32 to EAX.
81 /0 iw ADD r/m16, imm16 Add imm16 to r/m16.
81 /0 id ADD r/m32, imm32 Add imm32 to r/m32.
01 /r ADD r/m16, r16 Add r16 to r/m16.
01 /r ADD r/m32, r32 Add r32 to r/m32.
03 /r ADD r16, r/m16 Add r/m16 to r16.
03 /r ADD r32, r/m32 Add r/m32 to r32.
Почему все 16 и 32-битные версии одной и той же инструкции имеют одинаковые коды операций?
Ответ таков: текущий режим определит тип инструкции.Если вы работаете в 16-битном режиме, то по умолчанию будут использоваться 16-битные регистры, а если вы используете 32- или 64-битный режим, то размер по умолчанию будет 32-битным.Если вы хотите использовать другой размер, вам придется использовать 66h (переопределение размера операнда) префикс .Это означает, что в 16-битном режиме вы получите вывод ниже, чем то, что вы видели выше
83 c0 01 add ax, 1
66 83 c0 01 add eax, 1
Я пытался разобрать 05 01, как показано в руководстве, но он не распознал егов качестве кода операции просто используются номера
Поскольку за 05
должен следовать 4-х байтовый код (id/imm32
, как указано в руководстве) или 2-байтовый протокол (iw/imm16
) в зависимости отразмер операнда по умолчанию.Только инструкции с imm8/ib
могут иметь один байт сразу.Например, онлайн-дизассемблер дает мне следующий вывод
0: 05 01 02 03 04 add eax,0x4030201
5: 66 05 01 02 add ax,0x201
По той же причине, что и выше, был выбран код операции 83h, потому что 0x01 помещается в байт, делая одинаковую длину иассемблер может выбирать все, что ему нравится
0: 66 83 c0 01 add ax,0x1
4: 66 05 01 00 add ax,0x1
Вы можете прочитать это