У меня возникла проблема, когда я не могу понять код операции этой инструкции MOV BX, CS, например, первый байт равен 10001100, где первые 6 бит представляют код операции, затем 1 бит направления следует за W. Итак, вот мои сомнения, почему в опкоде это 100011 а не 100010 а в ячейке W почему стоит 0 а не 1 типа с какой целью или есть какое то условие на которое надо обратить внимание.
Я был бы очень признателен, если бы кто-то мог дать мне подробный ответ.
Когда я пытался решить более чем одним методом, я просто не мог получить решение, показанное на рисунке выше, и я просмотрел много видео, но не нашел ответа, который прояснил бы мои сомнения.
Некоторые коды операций не следуют этому шаблону, в том числе коды для mov
в/из сегментных регистров. 8-битной версии этих инструкций не существует, поэтому младший бит не соответствует Width = 8 против 16-битной.
Младшие 2 бита, являющиеся направлением и шириной, не являются универсальными, это просто шаблон, который существует в большинстве обычных кодов операций ALU, которые идут парами для 8-битного и 16/32/64-битного размера операнда 1, например and
, add
, cmp
и т. д., которые имеют оба направления, непосредственные формы как с imm16
, так и с расширенным знаком imm8
для 16-битного размера операнда, и короткие кодировки al, imm8
/ ax, imm16
без ModRM. Также такие, как shr
, у которых нет обоих направлений, но есть оба размера.
Даже mov
для несегментных регистров имеет некоторые специальные формы, с формой mov reg, imm
с номером регистра как младшими 3 битами кода операции, а не направлением или шириной. И нет mov r/m16, sign_extended_imm8
, потому что 8086 не пригодился для этого. (https://www.felixcloutier.com/x86/mov показывает различные коды операций mov.)
Код операции mov r/m, Sreg
, на который вы смотрите, — 8C. Четыре кода операции с разными значениями младших 2 битов включают mov Sreg, r/m
, а также два несвязанных кода операции с установленным младшим битом, и все они существуют только в формах с 16-битным размером операнда, поэтому на самом деле это не означает W для любого из их. Хотя это работает для LEA и pop
.
8C
— это mov r/m, Sreg
код операции, о котором вы спрашиваете.
8D
это lea
8E
— это mov Sreg, r/m
(который существует с установленным битом d и работает с любой регистрацией сегмента, отличной от CS, в поле /r ModRM. Кодирование его с назначением CS возможно, но это вызовет исключение #UD на ЦП после 8086. В 8086 не было исключений из-за недопустимых инструкций, каждый битовый шаблон выполнялся как нечто. Некоторые модели 8086 даже запускали mov в CS как переход.)
8F
есть pop r/m
.
См. http://ref.x86asm.net/coder32.html#x8C список инструкций по коду операции. Есть много других исключений из шаблона, например, cli
и sti
являются FA и FB соответственно.
Сноска 1: при 16/32/64-битном размере операнда все имеют одинаковый код операции. Значение по умолчанию подразумевается текущим режимом. Префикс 66h
устанавливает противоположность 16 или 32-разрядному, а префикс REX.W выбирает 64-разрядный.
Когда разрабатывались 386 и AMD64, не было места для новых кодов операций, поэтому вместо них использовались префиксы.
Большое спасибо за подробное объяснение .... действительно ценю это.