Структура команд INTEL 80х86

"— Потому ты и опасен, что ояладел своими страстями." Ф. Херберт. "Мессия Дюны".

Дизассемблирование (тем более в уме) невозможно без понимания того, как процессор интерпретирует команды. Конечно, можно просто запомнить все опко-ды команд и записать их в таблицу, которую потом вызубрить наизусть, но это не самый лучший путь. Уж слишком много придется зубрить. Гораздо легче понять, как строятся команды, чтобы потом с легкостью манипулировать ими.

Для начала разберемся с форматом инструкций архитектуры Intel:


Префикс | Опкод | ModR / М | SIB | Смещение | Непосредств, операнд

       
   

Mod | Reg / Opcode | R/M | | Scale | Index | Base |


Заметим, что все поля, кроме поля опкода, являются факультативными. Т.е. в одних командах они могут присутствовать, а в других нет.

Само поле опкода занимает восемь бит и часто (но не всегда) имеет следую­щий формат:

Опкод Направление Размер
  Регистр
  Условие Инверсия

7 4 3 2 1 0

Поле размера равно нулю, если операнды имеют размер в байт. Единичное значение указывает на слово (двойное слово в 32-режиме или с префиксом 0х66 в 16-разрядном режиме).

Направление обозначает операнд-приемник. Нулевое значение присваивает результат правому операнду, а единица левому. Рассмотрим это на примере инструкции mov bx.dx:

8BDA mov bx,dK

lOOOlO11b

69DA mov dx, bx

lOOOlOO1b

He правда ли, мы можем как по мановению волшебной палочки менять местами операнды, меняя всего один бит? Однако задумаемся, как это поле будет вести себя, когда один из операндов имеет непосредственное значение? Разуме­ется, оно не может быть приемником и независимо от значения этого поля будет только источником. Инженеры Intel учли такую ситуацию и нашли оригинальное применение, часто экономящее до трех байтов. Рассмотрим ситуацию, когда операнду размером в слово или двойное слово присваивается непосредственное значение, меньшее по модулю 0х100. Ясно, что значащим является только младший байт, а нули, стоящие слева, по правилам математики можно и отбросить. Но попробуйте объяснить это процессору! Нужно пожертвовать хотя бы одним битом, чтобы указать ему на такую ситуацию. Вот тут-то и используется байт направления. Рассмотрим следующую команду: