div.main {margin-left: 20pt; margin-right: 20pt}
МИКРОПРОЦЕССОР INTEL 8086
Структуру команд и методы адресации мы
далее будем рассматривать на примере широко распространенного микропроцессора
Intel 8086. Рассмотрим аппаратную модель этого микропроцессора.
Выполнение программы в ЭВМ представляет собой циклическую
последовательность приведенных ниже действий, образующих цикл команды: 1)
выборка команды из памяти и формирование адреса следующейпо порядку
команды; 2) считывание операнда из памяти, если это требуется по смыслу
команды; 3) собственно выполнение команды;
4) запись результата в память, если это указано в команде, и переход к
новому циклу команды. Обычно в микропроцессоре эти действия выполняются
последова- тельно во времени. В процессоре 8086 основные этапы сохранены,
но они распределены внутри процессора по двум сравнительно независимым
устройствам. Операционное устройство выполняет команды, а устройство шинного
интерфейса выбирает команды, считывает операнды и записывает результаты. Оба
устройства могут работать параллельно и в большинстве случаев обеспечивают
значительное совмещение выборки и выполнения команд. В результате этого время
выборки команды как-бы "исчезает" из цикла команды, так как операционное
устройство выполняет команды, уже выбранные шинным интерфейсом. Операционное
устройство содержит группу общих регистров, арифметико-логическое устройство
(АЛУ), основу которого составляет комбинированный 16-разрядный сумматор с
последовательно-параллельным переносом, регистр флажков и несколько регистров
для временного хранения операндов и результата операции. Оно выполняет команды,
обменивается данными и адресами с шинным интерфейсом, оперирует общими
регистрами и флажками. В его составе имеется блок микропрограммного управления,
который дешифрует команды и формирует необходимые управляющие сигналы.
Операционное устройство изолированно от внешней шины, за исключением нескольких
внешних сигналов. Шинный интерфейс выполняет для операционного устройства все
операции обмена. Данные передаются между процессором и памятью или портами ввода-вывода по
запросам операционного устройства. Когда операционное устройство занято
выполнением команды, шинный интерфейс самостоятельно инициирует опережающую
выборку из памяти очередных команд. Команды хранятся во внутренней регистровой
памяти, называемой очередью (буфером) команд. Очередь команд выполняет по
существу функции регистра команды процессора. Длина очереди составляет 6
байт. Очередь команд работает по принципу FIFO ("первым пришел, первым вышел"),
который сохраняет на выходе порядок поступления команд. Шинный интерфейс
инициирует выборку из памяти следующего командного слова, когда в очереди
оказываются два свободных (пустых) байта. В большинстве случаев очередь команд
содержит минимум один байт потока команд, и операционное устройство не ожидает
выборки команды. Конечно, очередь обеспечивает положительный эффект при
естественном порядке выполнения команд. Когда операционное устройство выполняет
команду передачи управления, шинный интерфейс сбрасывает очередь, выбирает
команду по новому адресу, передает ее в операционное устройство, а затем
начинает заполнение очереди из следующихячеек. Эти действия выполняются при
условных и безусловных переходах, вызовах подпрограмм, возвратах из подпрограмм
и при обработке прерываний. Шинный интерфейс приостанавливает выборку
команд, когда операционное устройство запрашивает операцию считывания или записи
в память или порт ввода-вывода. В состав шинного интерфейса входят несколько
регистров и сумматор, которые формируют 20-разрядный физический адрес памяти из
двух 16-разрядных логических адресов: сегмента (базы) и смещения. При
готовности операционного устройства выполнять команду оно считывает из очереди
байт, а затем выполняет предписанную командой операцию. При многобайтных
командах из очереди считываются и другие байты команды. Когда операционное
устройство готово считать командный байт, а очередь команд пуста, оно ожидает
выборки командного слова из памяти программ, которую производит шинный
интерфейс. Если команда требует обращения к памяти или порту вво- да-вывода,
операционное устройство запрашивает шинный интерфейс на выполнение необходимого
цикла шины. Когда шинный интерфейс не занят выборкой команды, он удовлетворяет
запрос немедленно; в противном случае операционное устройство ожидает завершения
текущего цикла шины.
ПРОГРАММНАЯ МОДЕЛЬ ПРОЦЕССОРА 8086
Программная модель процессора - это
функциональная модель, используемая программистом при разработке программ в
кодах ЭВМ или на языке ассемблера. В такой модели игнорируются многие
аппаратные особенности в работе процессора. В процессоре 8086 имеется несколько
быстрых элементов памяти, которые называются регистрами. Каждый из регистров
имеет уникальную природу и предоставляет определенные возможности, которые
другими регистрами или ячейками памяти не поддерживаются.
Регистры
разбиваются на четыре категории: регистры общего назначения, регистр флагов,
указатель команд и сегментные регистры. Все регистры 16-разрядные.
Формат регистров общего назначения:
|
15 |
7
0 |
ax |
ah |
al |
bx |
bh |
bl |
cx |
ch |
cl |
dx |
dh |
dl |
si |
|
di |
|
sp |
|
bp |
|
Формат регистра флагов:
|
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
flags |
** |
** |
** |
** |
OF |
DF |
IF |
TF |
SF |
ZF |
** |
ZF |
** |
PF |
** |
CF |
Указатель команд:
|
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
ip |
|
Формат сегментных регистров:
|
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
cs |
|
ds |
|
es |
|
ss |
|
РЕГИСТР ФЛАГОВ
Этот 16-разрядный регистр содержит всю необходимую
информа- цию о состоянии процессора 8086 и результатах выполнения
послед- ней команды.
Битовые флаги: OF - флаг переполнения; DF -
флаг направления; IF - флаг прерывания; TF - флаг трассировки; SF -
флаг знака; ZF - флаг нуля; AF - флаг дополнительного переноса; PF -
флаг четности; CF - флаг переноса; ** - бит не используется, состояние не
определено.
Флаг переполнения OF сигнализирует о потере старшего
бита результата сложения или вычитания. Имеется специальная
команда прерывания при переполнении, которая генерирует программное
пре- рывание. Флаг направления DF определяет порядок сканирования
цепочек байт или слов в соответствующих командах: от меньших адресов
к большим (DF = 0) или наоборот (DF = 1).
- платят и немало.
Флаг прерывания IF определяет реакцию
процессора на запросы внешних прерываний по входу INT. Если IF = 0, запросы
прерываний игнорируются (говорят также, что прерывания запрещены или
замаскированы), а если IF = 1, процессор распознает запросы на прерывания и
реагирует на них соответствующим образом. Состояние флага IF не влияет на
восприятие внешних немаскируемых прерываний по входу NMI, а также внутренних
(программных) прерываний. Установка в состояние 1 флага трассировки TF переводит
процессор в одношаговый (покомандный) режим работы, который применяется при
отладке программ. В этом режиме процессор автоматически генерирует внутреннее
прерывание после выполнения каждой команды с переходом к соответствующей
подпрограмме обработки, которая может, например, демонстрировать содержимое
регистров процессора на зкране дисплея. Флаг знака SF повторяет значение
старшего бита результата, который при использовании дополнительного кода
соответствует знаку числа. Флаг нуля ZF сигнализирует о получении нулевого
результата операции. Флаг вспомогательного переноса AF фиксирует перенос
(заем) из младшей тетрады в старшую 8- или 16-битного результата. Он необходим
только для команд десятичной арифметики. Флаг четности (паритета) PF фиксирует
наличие четного числа единиц в младших 8 разрядах результата операции. Этот флаг
пред- назначен для контроля правильности передачи данных. Флаг CF фиксирует
значение переноса (заема), возникающего при сложении или вычитании байт или
слов, а также значение выдвигаемого бита при сдвиге операнда.
Регистр
флагов не считывается и не модифицируется непосредственно. Вместо этого в
системе команд микропроцессора предусмотрены специальные команды, с помощью
которых программист может задать необходимое ему состояние любого из флагов
(кроме TF). Содержимое регистра флагов используется микропроцессором
при выполнении команд условного перехода, циклических сдвигов, операций с
цепочками байт или
слов.
РЕГИСТРЫ ОБЩЕГО НАЗНАЧЕНИЯ
Восемь регистров общего назначения процессора
8086 (каждый разрядностью 16 бит) используются в операциях большинства
инструкций в качестве источника или приемника при перемещении данных и
вычислениях, указателей на ячейки памяти и счетчиков. Каждый регистр общего
назначения может использоваться для хранения 16-битового значения, в
арифметических и логических операциях, может выполняться обмен между регистром и
памятью (запись из регистра в память и наоборот).
Кроме этих общих
свойств, каждый регистр общего назначения имеет свои особенности. Поэтому
рассмотрим далее каждый из них отдельно.
Регистр AX называют также
накопителем (аккумулятором). Этот регистр всегда используется в операциях
умножения или деления и является также одним из тех регистров, который можно
использовать для наиболее эффективных операций (арифметических, логических или
операций перемещения данных). Младшие 8 битов регистра AX называются также
регистром AL, а старшие 8 битов - регистром AH. Это может оказаться удобным при
работе с данными размером в байт. Таким образом, регистр AX можно использовать,
как два отдельных регистра.
Регистр BX может использоваться для ссылки на
ячейку памяти (указатель), т.е. 16-битовое значение, записанное в BX, может
использоваться в качестве части адреса ячейки памяти, к которой производится
обращение. По умолчанию, когда BX используется в качестве указателя на ячейку
памяти, он ссылается на нее относи- тельно сегментного регистра DS. Как и
регистры AX, CX и DX, регистр BX может интерпретироваться, как два восьмибитовых
регистра - BH и BL.
Специализация регистра CX - использование в качестве
счетчика при выполнении циклов. Уменьшение значения счетчика и цикл - это часто
используемый элемент программы, поэтому в процессоре 8086 используется
специальная команда для того, чтобы циклы выполнялись быстрее и были более
компактными. Эта команда называется LOOP. Инструкция LOOP вычитает 1 из CX и
выполняет переход, если содержимое регистра CX не равно 0. Регистр CX можно
интерпретировать, как два 8-разрядных регистра - CH и CL.
Регистр DX -
это единственный регистр, которые может использоваться в качестве указателя
адреса ввода-вывода в командах IN и OUT. Фактически, кроме использования
регистра DX нет другого способа адресоваться к портам ввода-вывода с 256 по
65535. Другие уникальные качества регистра DX относятся к
операциям деления и умножения. Когда вы делите 32-битовое делимое на
16-битовый делитель, старшие 16 битов делимого должны быть помещены в регистр DX
(младшие 16 битов делимого должны быть помещены в регистр AX). После выполнения
деления остаток также сохраняется в регистре DX (частное от деления будет
записано в AX). Аналогич- но, когда вы перемножаете два 16-битовых
сомножителя, старшие 16 битов произведения сохраняются в DX (младшие 16 битов
записываются в регистр AX). Регистр DX можно интерпретировать, как два
8-разрядных регистра - DH и DL.
Как и регистр BX, регистр SI может использоваться, как указатель на ячейку
памяти. Особенно полезно использовать регистр SI для ссылки на память в
строковых командах процессора 8086, которые не только изменяют содержимое по
адресу памяти, на который указывает SI, но к SI также добавляется или вычитается
1. Это может оказаться очень эффективным при организации доступа к
последовательным ячейкам памяти (например, к строке текста). Кроме того, можно
сделать так, что строковые команды будут автоматически определенное число раз
повторять свои действия, так что отдельная команда может выполнить сотни, а
иногда и тысячи действий.
Регистр DI очень похож на регистр SI в том
плане, что его можно использовать в качестве указателя ячейки памяти. При
использовании его в строковых командах регистр DI несколько отличается от
регистра SI. В то время как SI всегда используется в строковых командах, как
указатель на исходную ячейку памяти (источник), DI всегда служит указателем на
целевую ячейку памяти (приемник). Кроме того, в строковых командах регистр SI
обычно адресуется к памяти относительно сегментного регистра DS, в то время как
DI всегда адресуется к памяти относительно сегментного регистра ES. Когда SI
и DI используются в качестве указателей на ячейки памяти в других командах (не
строковых), то они всегда адресуются к памяти относительно регистра DS. Как и
регистры BX, SI и DI, регистр BP также может использо- ваться в качестве
указателя на ячейку памяти, но здесь есть некоторые отличия. Регистры BX, SI и
DI обычно ссылаются на память относительно сегментного регистра DS (или, в
случае использования в строковых командах регистра DI, относительно сегментного
регистра ES), а регистр BP адресуется к памяти относительно регистра SS
(сегментный регистр стека). Регистр BP создан для обеспечения работы с
параметрами процедур, локальными переменными и других случаев, когда
требуется адресация к памяти с использованием стека.
Регистр SP
называется также указателем стека. Это "наименее общий" из регистров общего
назначения, поскольку он практически всегда используется для специальной цели -
обеспечения стека. Стек - это область памяти, в которой можно сохранять значения
и из которой они могут затем извлекаться по дисциплине "послед-
ний-пришел-первый-ушел" (LIFO ). То есть последнее сохраненное в стеке значение будет первым
значением, которое вы получите при чтении из стека. Регистр SP в каждый
момент времени указывает на вершину стека. Вершина стека - это то место, в
котором в стеке сохраняется следующее помещенное туда значение. Действие,
состоящее в занесении значений в стек, называют также "заталкиванием" (pushing)
в стек (для этого используется команда PUSH). Аналогично, дейст- вие,
состоящее в извлечении (выборке) значений из стека, называют также
"выталкиванием" (popping) из стека (для этого используется команда POP). Хотя
процессор 8086 и позволяет записывать значения в SP или складывать и вычитать
хранящиеся в регистре SP значения (как это можно делать с обычными регистрами
общего назначения), вам не следует к этому прибегать, если вы в точности не
знаете, что делаете. Если вы изменяете SP, то изменяется расположение вершины
стека, что быстро может привести к неприятностям, так как занесе- ние данных
в стек и извлечение их из него не является единствен ным способом использования
стека. Стек используется всякий раз, когда вы вызываете или возвращаетесь из
подпрограммы (процедуры или функции). Кроме того, стек используют некоторые
системные программы (такие, как драйвер клавиатуры или системный таймер), когда
они прерывают процессор 8086, чтобы выполнить свои функции. Все это означает,
что стек может в любой момент потребоваться. Если вы измените SP, то
правильное значение стека может оказаться недоступным, когда он потребуется
системным программам. Можно свободно выполнять операции занесения в стек и
извлечения из него, вызовы и возвраты управления, но не изменяйте значения
регистра SP непосредственно. Любой из других семи регистров общего назначения
можно спокойно изменять в любой момент.
УКАЗАТЕЛЬ КОМАНД
Указатель команд (регистр IP) всегда содержит
смещение в памяти, по которому хранится следующая выполняемая команда. Когда
выполняется одна команда, указатель команд перемещается таким образом, чтобы
указывать на адрес памяти, по которому хранится следующая команда. Обычно
следующей выполняемой командой является команда, хранимая по следующему адресу
памяти, но некоторые команды, такие, как вызовы или переходы, могут привести
к тому, что в указатель команд будет загружено новое значение. Таким образом,
будет выполнен переход на другой участок программы. Значение счетчика команд
нельзя прочитать или записать непосредственно. Загрузить в указатель команд
новое значение может только специальная команда перехода. Указатель команд сам
по себе не определяет адрес, по которому находится следующая выполняемая
команда. Картину здесь опять усложняет сегментная организация памяти
процессора 8086. Для извлечения команды предусмотрен регистр CS, где хранится
базовый адрес, при этом указатель команд задает смещение относительно этого
базового адреса.
СЕГМЕНТНЫЕ РЕГИСТРЫ
Теперь мы подошли к
наиболее необычному аспекту процессора 8086 - сегментации памяти. Основной
предпосылкой сегментации является следующее: процессор 8086 может адресоваться к
1 мегабайту памяти. Для адресации ко всем ячейкам адресного пространства в 1
мегабайт необходимы 20-разрядные сегментные регистры. Однако процессор 8086
использует только 16-разрядные указатели на ячейки памяти. Как же тогда
согласовать 16-разрядные указатели процессора 8086 и 20-разрядные
адреса? Ответ состоит в том, что процессор 8086 использует двухступенчатую
схему адресации. Да, используются 16-разрядные указатели, но эта форма
представляет собой только часть полной схемы адресации. Каждый 16-разрядный
указатель памяти или смещение комбинируется с содержимым 16-разрядного
сегментного регистра для формирования 20-разрядного адреса памяти. Сегменты и
смещения комбинируются следующим образом: значение сегмента сдвигается влево на
4 (то есть умножается на 16), а затем складывается со смещением. Фактически, для
доступа к памяти процессор всегда использует пару "сегмент:смещение". Все
команды и режимы адресации процессора 8086 по умолчанию работают относительно
того или иного сегментного регистра, хотя в некоторых командах можно явно
указать, что нужно использовать желаемый сегментный регистр. Вам редко
потребуется загружать значение непосредственно в сегментный регистр. Вместо
этого вы будете загружать в сегментные регистры имена сегментов, которые в ходе
ассемблирования, компо- новки и выполнения превращаются в числа. Это
необходимо, поскольку нет способа сказать заранее, где в памяти будет находиться
данный сегмент: это зависит от версии DOS, числа и размера резидентных в памяти
программ, а также потребности в памяти остальной части программы. Использование
имен сегментов позволяет ассембле- ру и операционной системе DOS выполнять
подобные вычисления. Использование сегментов процессора 8086 приводит к
некоторым интересным моментам. Один из них состоит в том, что только блок памяти
размером в 64К в любой момент может адресоваться через сегментный регистр, так
как 64К - это максимальный объем памяти, к которой можно адресоваться с помощью
16-битового смещения. Это может оказаться неприятным при работе с большим
(более 64К) объемом памяти, так как и значение сегментного регистра, и смещение,
придется часто изменять. Адресация к большим блокам памяти в процессоре 8086
может представлять еще большую трудность, поскольку, в отличие от регистров
общего назначения, сегментные регистры не могут использоваться в качестве
источников или приемников в арифметических и логических команд. Фактически,
единственная операция, которую можно выполнять с сегментными регистрами,
состоит в копировании значений между сегментными регистрами и другими общими
регистрами или памятью. Вторая особенность использования сегментов состоит в
том, что каждая ячейка памяти адресуется через многие возможные сочетания
"сегмент:смещение". Например, адрес памяти 100h адресуется с помощью следующих
значений "сегмент:смещение": 0:100h, 1:F0h, 2:E0h и т.д., так как при вычислении
всех этих пар "сегмент:сме- щение" получается значение адреса
100h.
Аналогично регистрам общего назначения каждый сегментный регистр
играет свою, конкретную роль. Регистр CS указывает на код программы, DS
указывает на данные, SS - на стек. Сегментный регистр ES - это дополнительный
сегмент, который может использоваться так, как это необходимо. Рассмотрим
сегментные регистры более подробно. Регистр CS указывает на начало блока памяти
объемом 64К, или сегмент кода, в котором находится следующая выполняемая
команда. Следующая команда, которую нужно выполнить, находится по смещению,
определяемому в сегменте кода регистром IP, то есть на нее указывает адрес (в
форме "сегмент:смещение") CS:IP. Процессор 8086 никогда не может извлечь команду
из сегмента, отличного от того, который определяется регистром
CS.
Регистр CS можно изменять с помощью многих команд, включая отдельные
команды перехода, вызовы и возвраты управления. Ни при каких обстоятельствах
регистр CS нельзя загрузить непосредственно. Никакие другие режимы адресации или
указатели памяти, отличные от IP, не могут нормально работать относительно
регистра CS.
Регистр DS указывает на начало сегмента данных, которые
представляет собой блок памяти объемом 64К, в котором находится большинство
размещенных в памяти операндов. Обычно для ссылки на адреса памяти используются
смещения, предполагающие использование регистров BX, SI или DI. В основном
сегмент данных представляет собой то, о чем говорит его название: как правило
это сегмент, в котором находится текущий набор данных.
Регистр ES
указывает на начало блока памяти объемом 64К, который называется дополнительным
сегментом. Как и подразумевает его название, дополнительный сегмент не служит
для какой-то конкретной цели, но доступен тогда, когда в нем возникает
необходимость. Иногда сегмент ES используется для выделения дополни- тельного
блока памяти объемом 64К для данных. Однако доступ к памяти в дополнительном
сегменте менее эффективен, чем доступ к памяти в сегменте данных. Особенно
полезен дополнительный сегмент, когда используются строковые команды. Все
строковые команды, которые выполняют запись в память, используют в качестве
адреса, по которому нужно выполнить запись, пару регистров ES:DI. Это означает,
что регистр
ES особенно полезен при использовании его в качестве целевого
сегмента при копировании блоков, сравнении строк, просмотре памяти и очистке
блоков памяти.
|