У вас ошибка в таблице: 16 и 32-битный размер операнда имеют один и тот же код операции, и дифференцированы с помощью префикса размера операнда байт использовать тот, который в настоящее время не размер операнда по умолчанию. (Таким образом, 16-битные инструкции занимают дополнительный байт в 32-битном и 64-битном режимах.) Это справедливо для всех кодов операций, а не только mov
.
Вы могли бы проверить это самостоятельно с помощью ассемблера и дизассемблера, который включает в себя шестнадцатеричные байты кодировки команд на выходе.
Для большинства инструкций есть отдельные коды операций для 8 и 16/32/64, но я думаю, что недостаточно места для опций, чтобы добавить еще одну версию всего, когда произошло расширение от 16 до 32 бит.
mov r8, imm8
использует код операции B0+rb
(так, В0-В7).
mov r16/32/64, imm16/32/64
использует код операции B8+rw/rd
(так, B8-BF) с префиксом размера операнда, префиксом REX с установленным битом .W) или без префикса.
Поскольку мы на эту тему, стоит отметить, что mov r/m64, imm32
(по знаку шаг-немедленный) должен использовать дополнительные байты для кодирования регистр назначения или эффективный адреса, но еще короче mov r64, imm64
. В AT T синтаксис вы должны использовать мнемонику movabs
, если хотите, иначе ассемблер обрезает вашу константу до 32 бит.
Фактические двоичные кодировки для номеров регистров, как представляется, указывается в трех местах в руководствах Intel, реф, Том 2. (связанные с x86 вики).
Наиболее релевантный этому вопросу (регистр, закодированный как последние 3 бита кода операции), есть Таблица 3-1. Регистрирующие коды, связанные с + rb, + rw, + rd, + ro, внутри Раздел 3.1: ИНТЕРПРЕТАЦИЯ СТРУКТУРЫ ИНСТРУКЦИИ.
Кодировки такие же, как в Приложении B.1.3, что также указывает, что поле 3-разрядного регистра может быть последним 3 бит кода операции. (Я думаю, что все коды операций, которые используют +rb
/+rd
, являются кратными 8, поэтому добавление 0-7 = установка последних 3 бит). B.1.4.1 имеет таблицы, в которых регистрируются каждое возможное 3-битное значение, для 16-битного и 32-битного размеров операндов (в не-64-битном режиме).
Он идет:
encoding | 8bit reg | 32bit reg
000 | AL | EAX
001 | CL | ECX
010 | DL | EDX
011 | BL | EBX
100 | AH | ESP
101 | CH | EBP
110 | DH | ESI
111 | BH | EDI
Таблицы для других размеров операндов, а для 64-разрядного режима, находятся поблизости.(Инструкции с префиксом REX обычно не могут адресовать AH/BH/CH/DH, только младшие байты из 16 GP-регистров. Я предполагаю, что это связано с тем, что кодировка для ch
сталкивается с bpl
при использовании с префиксом REX.)
Там также таблица регистра кодировок (для использования в модах/ет полей) в главе 2, с таблицами.
Существует также упоминание о кодировании реестра dest в код операции в разделе для 64-битного режима после таблиц.
Глава 2.2.1.1: Кодирование (в разделе IA-32e):
Intel 64 и IA-32 форматы команд указать до трех регистров с использованием 3-битовых полей в кодировке, в зависимости на формате:
- ModR/М: рег и г/м полей ModR/M байт
- ModR/M с SIB: рег поле/M байт ModR, базы и индекса поля байта SIB (шкала, индекс, база)
- Инструкции без ModR/М: р поле опкода
Но если определенное значение используется для указания другой информации по размерам, чем текущий, что если вы хотите использовать ту же ценность, как операнд? – user504882
И как определяется текущий размер данных (16-/32-бит)? Является ли это жестко запрограммированным в процессоре или может быть изменено с помощью конкретной мнемоники? – user504882
@ user504882: Если вы хотите 16-разрядный размер операнда в 16-битном режиме, вы опускаете байт префикса размера операнда ('66h'). Текущий размер операнда по умолчанию - это режим, в котором может находиться процессор. реальный режим 16 бит, защищенный режим - 32 бит. Или что-то типа того. Я не думаю, что есть способ изменить размер операнда по умолчанию без привилегированных инструкций, чтобы изменить режим работы ЦП. –