Это вопрос о префиксах переопределения размера операнда в архитектуре x86-64 (AMD64).
Вот набор инструкций ассемблера (nasm) и их кодировки; под новым я имею в виду регистры r8, …, r15:
67: address-size override prefix | | 4x: operand-size override prefix | | ; Assembler ; | Dst operand | Src operand | — — mov eax,ecx ; | 32-bit | 32-bit | 89 C8 | mov r8d,ecx ; | 32-bit new | 32-bit | 41 89 C8 | mov eax,r9d ; | 32-bit | 32-bit new | 44 89 C8 | mov r8d,r9d ; | 32-bit new | 32-bit new | 45 89 C8 | mov rax,rcx ; | 64-bit | 64-bit | 48 89 C8 | mov r8,rcx ; | 64-bit new | 64-bit | 49 89 C8 | mov rax,r9 ; | 64-bit | 64-bit new | 4C 89 C8 | mov r8,r9 ; | 64-bit new | 64-bit new | 4D 89 C8 | lea eax,[ecx] ; | 32-bit | 32-bit | 67 8D 01 | lea r8d,[ecx] ; | 32-bit new | 32-bit | 67 44 8D 01 | lea eax,[r9d] ; | 32-bit | 32-bit new | 67 41 8D 01 | lea r8d,[r9d] ; | 32-bit new | 32-bit new | 67 45 8D 01 | lea rax,[rcx] ; | 64-bit | 64-bit | 48 8D 01 | lea r8,[rcx] ; | 64-bit new | 64-bit | 4C 8D 01 | lea rax,[r9] ; | 64-bit | 64-bit new | 49 8D 01 | lea r8,[r9] ; | 64-bit new | 64-bit new | 4D 8D 01 | push rax ; | | 64-bit | 50 | push r8 ; | | 64-bit new | 41 50 |
Изучая эти и те же инструкции с другими регистрами, я пришел к следующему. Между «старым» и «новым» регистрами существует пара. Не исчерпывающе:
AX <—> R8 CX <—> R9 DX <—> R10 BX <—> R11 BP <—> R13
Игнорируя префикс размера, байты инструкции относятся не к конкретным регистрам, а к парам регистров. В качестве примера: байты 89 C8 указывают команду mov из источника, который является либо ecx, rcx, r9d, либо r9, в пункт назначения, который является либо eax, rax, r8d, либо r8. Учитывая, что операнды должны быть 32- или 64-битными, существует восемь допустимых комбинаций. Префикс переопределения размера операнда (или его отсутствие) указывает, какая из этих комбинаций является предполагаемой. Например, если префикс присутствует и равен 44, то исходный операнд должен быть 32-битным новым регистром (в этом примере затем сворачиваться до r9d), а местом назначения должен быть 32-битный старый регистр (здесь тогда сигнализация eax).
Возможно, я не совсем правильно понял, но я думаю, что уловил суть. Тогда может показаться, что префиксы переопределения размера операнда переопределяют тот факт, что без них инструкция использовала бы 32-битные «старые» операнды.
Но наверняка есть кое-что, что ускользнет от меня, иначе: какой смысл тогда говорить о «версии x86-64 с размером операнда по умолчанию 64-бит» (например, здесь)?
Или есть способ, работающий на 64-битной машине, установить размер операнда по умолчанию на 32 или 64, и если это так, и если моя программа настроит машину соответствующим образом, я бы увидел разные кодировки?
Также: когда будет использоваться префикс переопределения размера операнда 66H?
Взгляните на руководства Intel по разработке программного обеспечения. Объясняется кодировка и значение префиксов. Я могу написать настоящий ответ позже. — person user1752563 schedule 07.07.2021
Префиксы от 40h до 4Fh называются префиксами REX. Они могут указывать 64-битный размер операнда. Они также могут указывать на использование одного из 8 верхних регистров для источника или назначения. Я считаю, что возможна любая комбинация этих вариантов. — person user1752563 schedule 07.07.2021
Префикс 66 изменяет размер операнда на 16 бит. — person user1752563 schedule 07.07.2021
См., Например, wiki.osdev.org/X86-64_Instruction_Encoding#Encoding бит REX смыслы. — person user1752563 schedule 07.07.2021
Да, в машинном коде по умолчанию используется 32-битная версия для большинства инструкций, 64-битная для стека и инструкций перехода / вызова. В источнике сборки нет значения по умолчанию, это должно подразумеваться регистром или указываться явно. (За исключением некоторых ассемблеров, имеющих значение по умолчанию для push / pop.) Обратите внимание, что 16-битный AX соответствует 16-битному R8W, а RAX и R8 — это пара, различающаяся префиксом REX. — person user1752563 schedule 07.07.2021
@ecm В частности, префикс REX кодирует четыре бита состояния (один бит для размера операнда, три бита для старших регистров). Простое присутствие префикса REX дополнительно кодирует то, что вы хотите sil, dil, spl и bpl вместо ah, ch, dh и bh. — person user1752563 schedule 07.07.2021
@Peter Cordes Под «AX ‹—› R8» я имел в виду, что регистры, которые объединены в пары для целей кодирования, — это eax, rax с одной стороны и r8d, r8 с другой. Но Питер, на вопрос, который я связал, почему вы говорите о «версии x86-64 с размером операнда по умолчанию 64-бит»? — person user1752563 schedule 07.07.2021
Версия x86-64 с размером операнда по умолчанию 64-бит является чисто гипотетической. Питер говорит о том, как бы все работало, если бы был процессор, который вел бы такое поведение. Но в реальной жизни это не так. — person user1752563 schedule 08.07.2021
Источник: