Микропроцессоры 80186 и 80188 серии iX86 фирмы Intel

Скачать доклад: Микропроцессоры 80186 и 80188 серии iX86 фирмы Intel

Выбор в программе на Ассемблере типа процессора

По умолчанию Турбо Ассемблер ассемблирует код только для процессора 8086. Чтобы Турбо Ассемблер мог поддерживать другие процессоры серии iAPx86, или сопроцессоры, вы должны указывать соответствующие директивы. Следующие директивы сообщают Турбо Ассемблеру, какой тип процессора нужно поддерживать при ассемблировании кода:

  .186       .286C       .287      .386C       .387       .8087
.286 .286P .386 .386P .8086

Эти директивы можно указывать в любом месте исходного файла, после чего они сразу вступают в действие. В одном исходном файле можно разместить несколько директив выбора типа процессора, при этом текущим процессором считается процессор, выбранный по последней указанной директиве.

В любой момент можно указать директиву .8086, по которой Турбо Ассемблер будет снова поддерживать только процессор 8086.

(В остальной части данной главы все ссылки на процессор 8086 относятся в равной степени и к процессору 8088.)

ПРОЦЕССОРЫ 80186 И 80188

Процессор 80186 (который является процессором серии iAPx86) в основном аналогичен процессору 8086. Процессор 80186 поддерживает все инструкции процессора 8086, а также несколько новых инструкций и расширенные формы некоторых инструкций процессора 8086.

Процессор 80188 обладает программной совместимостью с процессором 80186. Единственное отличие между ними заключается в том, что процессор 80186 имеет 16-разрядную шину данных, а процессор 80188 - 8-разрядную.

Поддержка Турбо Ассемблера для ассемблирования кода процессора 80186 разрешается по директиве .186.

Далее мы рассмотрим новые и расширенные инструкции процессора 80186. Перед началом рассмотрения отметим, что процессор 8086 не распознает ни одну из тех инструкций, которые мы будем обсуждать. В итоге все программы, которые содержат хотя бы одну инструкцию (новую или расширенную) процессора 80186, на процессоре 8086 работать не будут.

Новые инструкции

Набор инструкций процессора 80186 содержит следующие новые инструкции:

   BOUND      INS       OUTS      PUSHA
ENTER LEAVE POPA

Инструкции PUSHA и POPA

Инструкции PUSHA и POPA предоставляют эффективное средство, с помощью которого можно заносить и извлекать из стека все восемь общих регистров. Инструкций PUSHA заносит в стек восемь общих регистров в следующем порядке: AX, CX, DX, BX, SP, BP, SI, DI. POPA извлекает регистры DI, SI, BP, BS, DX, CX и AX (то есть выполняет действие, обратное действию инструкции PUSHA). Регистр SP инструкцией POPA не извлекается, вместо этого SP увеличивается на 16 - длину блока регистров, занесенных в стек по инструкции PUSHA, а значение SP, занесенное в стек по инструкции PUSHA, очищается инструкцией POPA и отбрасывается. На сегментные регистры, флаги и указатель инструкций PUSHA и POPA не влияют.

Учтите, что инструкция PUSHA выполняется быстрее, чем восемь отдельных инструкций PUSH, но медленнее, чем три или четыре инструкции PUSH. Если вы хотите сохранить только несколько регистров, то лучше сделать это с помощью инструкции PUSH. Такое же замечание можно сделать относительно инструкций POPA и POP.

Инструкции ENTER и LEAVE

Инструкции ENTER и LEAVE используются для того, чтобы установить и отменить границы стека, в которых передаваемые параметры и локальные динамические переменные доступны относительно BP. Эти инструкции особенно полезны при организации интерфейса Ассемблера с языками, ориентированными на работу со стеком (например, Си).

Инструкция ENTER сохраняет регистр BP вызывающей программы, устанавливает его таким образом, чтобы он указывал на начало передаваемых параметров (если они имеются) в новых границах стека, устанавливает, как это необходимо, SP для выделения пространства для локальных переменных, и даже копирует блок указателей на границы стека языка высокого уровня в новые границы стека (если это необходимо).

Инструкция LEAVE имеет действие, обратное инструкции ENTER, и восстанавливает BP и SP в то состояние, которое они имели перед выполнением соответствующей инструкции ENTER.

SampleFunction  PROC
enter 10,1
.et
SampleFunction ENDP

Первый операнд инструкции ENTER представляет собой 16-битовое промежуточное значение, задающее число байтов, зарезервированных для локальных переменных в новой границе стека. Второй операнд инструкции ENTER - это 8-битовое промежуточное значение, задающее уровень вложенности функции, для которой должна создаваться новая граница стека. Этот операнд задает, сколько раз нужно скопировать указатели границы стека из границ стека вызывающего кода в новые границы стека.

Инструкция BOUND

Директиве BOUND проверяет, что 16-битовое значение находится в диапазоне со знаком, заданном двумя смежными словами памяти, при этом верхняя граница записана по адресу, расположенному непосредственно над нижней границей. Обе границы интерпретируются, как значения со знаком, поэтому можно задать максимальный диапазон от -32768 до +32767 включительно. Значения, совпадающие с нижней или верхней границей, рассматриваются, как принадлежащие заданному диапазону.

Инструкция BOUND используется обычно для того, чтобы предотвратить выход за границы массива. Если BX не находится в заданном диапазоне, то генерируется прерывание INT 5.

Первый операнд инструкции BOUND представляет собой 16-разрядный регистр общего назначения, содержащий проверяемое значение. Второй операнд инструкции BOUND - это двойное слово, содержащее диапазон. Это двойное слово содержит 16-битовую нижнюю границу в младшем слове и 16-битовую верхнюю границу со знаком в качестве старшего слова.

Инструкции INS и OUTS

Инструкции INS и OUTS обеспечивают эффективную передачу данных между портами ввода-вывода и памятью.

Инструкция INS перемещает один или более байтов (или слов) из порта ввода-вывода, на который указывает регистр DX, в массив в памяти, на который указывают ES:DI, увеличивая DI на 1 (или на 2) после того, как каждый байт (или слово) будет передан (или уменьшая SI, если установлен флаг направления).

Инструкция OUTS перемещает один или более байтов (или слов) из массива в памяти, на который указывают DS:SI, в порт ввода-вывода, на который указывает регистр DX, увеличивая SI на 1 (или 2) после пересылки каждого байта (или слова) либо уменьшая регистр SI, если установлен флаг направления.

Расширенные версии инструкций процессора 8086

В наборе инструкций процессора 80186 имеются следующие расширенные версии инструкций процессора 8086:

        IMUL            ROL             SAR
PUSH ROR SHL
RCL SAL SHR
RCR

Занесение в стек промежуточных значений

В то время как процессор 8086 может заносить в стек только регистровые операнды или операнды в памяти, процессор 80186 может заносить в него также и промежуточные значения:

push 19

Сдвиги и циклические сдвиги c непосредственными значениями

В то время как процессор 8086 может может только выполнять сдвиг или циклический сдвиг на 1 бит или на число битов, заданное в CL, процессор 80186 может выполнять сдвиг или циклический сдвиг на значение-константу:

        ror     ax,3
shl dl,7

Умножение на непосредственное значение

Процессор 8086 может умножать только 8- или 16-разрядный регистр или операнд в памяти на AL или AX, размещая результат в AX или DX:AX. В процессоре 80186 предусмотрены две новые формы умножения, которые используются, когда 16-разрядное умножение будет размещаться в 16 битах.

Одна из новых форм умножения перемножает 16-разрядный регистр и 16-разрядное непосредственное значение, а результат сохраняет обратно в 16-разрядном регистре. Например, следующая инструкция умножает DX на 4, а произведение записывает в DX:

        imul    dx,4

Первый операнд, который может представлять собой любой 16-разрядный регистр общего назначения, является одновременно источником для одного из сомножителей и приемником для произведения. Второй операнд, который должен представлять собой непосредственное 16-битовое значение, - это другой сомножитель.

Еще одна новая форма умножения перемножает 16-разрядный регистр или операнд в памяти на 16-битовое непосредственное значение, и сохраняет результат в заданном 16-битовом регистре. Например, следующая инструкция умножает DX на 600h и помещает произведение в CX:

        imul    cx,dx,600h

Аналогично, следующая инструкция умножает 16-разрядное значение в [BX+SI+1] на 3 и помещает произведение в AX.

        imul    ax,[bx+si+1],3

В данной форме инструкции IMUL первый операнд представляет собой приемник. Этот операнд может быть любым 16-разрядным общим регистром. Второй операнд, который может задаваться любым 16-разрядным общим регистром или ячейкой памяти, является источником одного из сомножителей. Третий операнд, который должен задаваться 16-битовым непосредственным значением, - это другой сомножитель.

Первая из новых форм умножения - это в действительности подмножество второй новой формы. Например, следующая инструкция:

        imul    si,10

это просто сокращенная форма инструкции:

        imul    si,si,10

Для обеих новых форм инструкции IMUL соответствующий шестнадцатиричный код будет одинаковым. Тем не менее, удобно иметь возможность использовать более простую форму инструкции IMUL с двумя операндами, когда один и тот же регистр используется и как источник, и как приемник.

При любой из новых форм умножения любая часть результата, которая не помещается в 16 битов, теряется. Если теряются значащие биты (предполагая, что результат должен представлять собой значение со знаком), то устанавливаются флаги переноса и переполнения. В новых формах операции умножения умножение значений со знаком и беззнаковых значений не различаются, поскольку результат имеет длину только 16 битов, и младшие 16 битов произведения (полученного в результате перемножения как значений со знаком, так и беззнаковых значений) всегда совпадают. Следовательно, для обозначения новых форм умножения можно использовать только инструкцию IMUL.