Организация памяти ВМ86
В МП ВМ86 существует два уровня представления памяти. На нижнем физическом уровне память организована в виде монолитного 1M-байтового блока 1М´8, каждый байт которого может быть адресован отдельно. Такое пространство и его адрес называют линейными. В МП ВМ86 линейный адрес эквивалентен физическому, т. е. тому, который присутствует на адресной шине.
Слова в линейной памяти занимают два любых соседних байта. В байте с младшим адресом хранится младшая часть слова. Его адрес служит адресом всего слова и может быть как четным, так и нечетным. Двойные слова размещаются как два соседних слова. Младшее слово располагается по младшему адресу, его адрес служит адресом двойного слова.
Для адресации блока в 1 Мбайт необходим 20-разрядный линейный адрес addr20. Однако программист оперирует не этими физическими адресами, а так называемыми логическими адресами. Каждый логический адрес—это пара sel: offset, состоящая из 16-разрядного селектора сегмента sel и 16-разрядного смещения внутри сегмента offset.
Множество логических адресов образует сегментированное адресное пространство логической памяти, состоящей из ряда изолированных друг от друга частей—сегментов. Селектор может рассматриваться как указатель сегмента. Всего возможно 216 логических сегментов. Каждый сегмент хранит функционально законченную часть объектного кода или отдельный набор данных к нему. Отдельный сегмент должен быть отведен для стека той или иной программы. В общем случае сегментированная память отображает модульную организацию программ, что может быть использовано для поддержки модульного программирования. Размер логического сегмента не фиксирован и зависит от его конкретного функционального назначения.
Второй компонент логического адреса—смещение—определяет расстояние от начала сегмента до объекта, расположенного внутри него. Разрядность данной компоненты определяет максимально возможный размер сегмента 64К байт. В целом объем логического пространства адресов составляет 4 Гбайт (Г = 230).
Возникает задача отображения логических сегментов в линейную физическую память. Селектор сегмента однозначно связан с базовым линейным адресом сегмента, определяющим его расположение в линейном пространстве:
base20 = 16 • sel
Линейный адрес объекта формируется из логического как сумма базы сегмента и смещения объекта в нем:
addr20 = base20 + offset = 16 • sel + offset
Один и тот же линейный адрес представляется множеством логических адресов.
В командах, как правило, используется неявный способ задания селектора, в качестве которого всегда выступает содержимое одного из четырех сегментных регистров. Вторая компонента логического адреса offset может быть определена различными традиционными способами.
Сегментные регистры CS—ES выделяют в памяти объемом 1 Мбайт четыре сегмента до 64К байт каждый. Сегменты выравнены по границе 16 байт (граница параграфа) и могут частично или полностью перекрываться друг с другом, как показано на рис. 6.3. Эти сегменты в отличие от остальных будем называть открытыми для доступа, вкладывая в это понятие тот смысл, что их селекторы хранятся в сегментных регистрах и, следовательно, доступ к ним открыт.
Рис. 6.3. Схема преобразования адресов
Неявный способ задания сегментного регистра обусловливает функциональную специализацию сегментов. В зависимости от используемого сегментного регистра различают кодовый сегмент, стековый сегмент, а также основной и дополнительный сегменты данных.
Регистр CS служит для указания кодового сегмента, который хранит объектный код. Содержимое CS используется для определения базы сегмента всякий раз, когда выполняется выборка объектного кода. При этом смещением в сегменте выступает значение программного счетчика IP.
При обращении к стеку (offset = SP) селектор извлекается из регистра SS. Поэтому указываемый им сегмент называется стековым и служит для организации системного стека.
Данные обычно располагаются в основном сегменте данных, база которого хранится в DS. Смещение offset в сегменте определяется одним из традиционных способов формирования исполнительного адреса.
В правилах адресации данных существует три исключения. Так, если при обращении к данным используется один из способов базовой адресации по ВР, то в качестве указателя сегмента служит SS. Этот вариант адресации эффективен при передаче параметров через текущий кадр системного стека. Указателем кадра является адресный регистр ВР.
При обработке строк регистр DS служит указателем сегмента исходной строки, смещение в сегменте извлекается из индексного регистра SI. При этом результирующая строка размещается в дополнительном сегменте данных, указателем которого служит ES. Смещение строки-результата определяется по содержимому DI. Одновременное применение двух сегментов позволяет реализовать эффективную передачу данных между сегментами.
Эти используемые по умолчанию правила выбора сегментных регистров приведены в табл. 6.1. В ряде случаев существует возможность замены сегментного регистра, которая реализуется явным указанием сегментного регистра с помощью специального байта-префикса, предшествующего команде. Однако эти возможности ограничены. С помощью префикса можно изменить только сегмент данных, за исключением обращения к строке-результату. Выборка команды, обращение к стеку и размещение результирующей строки всегда выполняется с помощью CS, SS и ES соответственно.
Таблица 6.1
Вид обращения к памяти | Селектор по умолчанию | Возможные варианты | Смещение offset |
Выборка команды Обращение к стеку Обращение к переменной кроме нижеуказанных Обращение к переменной по базе ВР Обращение к исходной строке Обращение к результирующей строке | CS SS DS SS DS ES | ¾ ¾ CS, ES, SS CS, ES, DS CS, ES, SS ¾ | ¾ ¾ Исполнительный адрес Исполнительный адрес SI DI |
Сегментирование памяти позволяет оформлять позиционно независимые и динамически перемещаемые программные модули, которые сами не должны изменять содержимое сегментных регистров, т. е. все смещения и переходы в программе должны выполняться относительно неизвестных, но фиксированных значений сегментных регистров.
Формат команд ВМ86
Команды МП занимают в памяти от 1 до 6 байт и имеют один из представленных на рис. 6.4 форматов. Перед командой может присутствовать один или несколько байтов-префиксов, фиксирующих определенный режим исполнения команды, например префикс замены сегментного регистра. Большое число форматов объясняется стремлением разработчиков реализовать эффективное кодирование команд.
Рис. 6.4. Формат команд ВМ86
Код операции (биты X), как правило, содержится в первом байте, иногда для этой цели используется также часть или весь второй байт. В форматах команд, оперирующих как словами, так и байтами, отведен специальный бит w, служащий признаком длины операнда: при w = 1 операнд имеет длину слова, при w = 0 операндом является байт. Если при этом применяется непосредственный операнд, то поле data(w) будет иметь соответственно два или один байт в зависимости от значения w. В одном из двух форматов команд с непосредственным операндом предусмотрен специальный бит s—признак расширения байта в слово с учетом знака, дающий возможность кодирования 16-разрядных непосредственных данных в одном байте. Если слово упаковывается в байт, то w = 1 и s = 1.
Поля reg и seg используются в командах с регистровым способом адресации для указания на регистры МП. Поле reg длиной 3 бита кодирует один из восьми регистров адреса/данных. При байтовом операнде в качестве этих регистров выступают байтовые регистры AL—BH. При 16-разрядном операнде это поле кодирует регистры AX—SP. Кодирование выполняется согласно табл. 6.2. Двухразрядное поле seg применяется для ссылки на один из четырех сегментных регистров. Правила кодирования указаны в табл. 6.3.
Таблица 6.2
Код reg | Регистр | Код reg | Регистр | ||
w = 0 | w = 1 | w = 0 | w = 1 | ||
AL | AX | АН | SP | ||
CL | CX | СН | BP | ||
DL | DX | DH | SI | ||
BL | BX | ВН | DI |
Таблица 6.3
Код | Регистр |
ES | |
CS | |
SS | |
DS |
Для команд с прямой адресацией в логическом пространстве адресов предусмотрено два формата. В одном из них зарезервировано 32-разрядное поле для указания полного логического адреса seg:offset. При этом за кодом команды следует смещение offset, а потом селектор sel, как этого требуют правила хранения двойных слов в памяти.
В другом формате, использующем внутрисегментную прямую адресацию, предусмотрено 16-разрядное поле для кодирования только смещения offset полного логического адреса. Альтернативой внутрисегментного прямого способа адресации является относительный. Короткий относительный адрес указывается в 8-разрядном поле disp8, которое интерпретируется как представленное в дополнительном коде целое со знаком и дает возможность осуществить внутрисегментную адресацию в пределах +127 ¸ –127 от текущего положения IP.
В большинстве команд применяемый способ доступа к данным определяется байтом mod XXX r/m или mod reg г/m. Он всегда следует непосредственно за кодом команды и называется постбайтом. Первый тип постбайта используется в однооперандных командах, когда поля mod и r/m определяют одну из 32 возможных схем вычисления адреса операнда согласно табл. 6.4, а свободные биты XXX служат для расширения поля кода операции. Второй тип постбайта определяет местоположение двух операндов. В качестве одного из операндов всегда выступает содержимое регистра адреса/данных, кодируемого полем reg в соответствии с табл. 6.2, другой определяется полями mod и r/m.
Таблица 6.4
Код | Схема вычисления адреса | Код | Схема вычисления адреса | ||
mod | г/m | mod | r/m | ||
(BX) + (SI) | (SI) + disp8 | ||||
(BX) + (DI) (BP) + (SI) | (DI) + disp8 (BP) + disp8 | ||||
(BP) + (DI) | (BX) + disp8 | ||||
(SI) | |||||
(DI) offset (BX) | (BX) + (SI) + disp16 (BX) + (DI) + disp16 (BP) + (SI) + disp16 | ||||
(BX) + (SI) + disp8 (BX) + (DI) + disp8 | (BP) + (DI) + disp16 (SI) + disp16 (DI) + disp16 | ||||
(BP) + (SI) + disp8 (BP) + (DI) + disp8 | (BP) + disp16 (BX) + disp16 | ||||
X | reg (см. табл. 6.2) |
Из табл. 6.4 можно получить обобщенную схему вычисления адреса
offset = base + index + disp
которая содержит три компонента. В качестве базы используется содержимое базового регистра BX или BP, в качестве индекса index—содержимое одного из индексных регистров SI или DI. Смещение кодируется непосредственно в команде и интерпретируется как целое со знаком. Сложение выполняется по модулю 216, т. е. с циклическим переходом через границу в 64К байт. В зависимости от значения смещение disp может быть как 8- так и 16-разрядным. В обоих случаях смещение следует непосредственно за постбайтом в одноименном поле disp(mod).
Один или два компонента из трех могут отсутствовать. В зависимости от этого различают семь базовых способов адресации памяти данных, которые представлены в табл. 6.5. Эти способы вместе с регистровым и непосредственным образуют полный набор методов адресации данных. Составы используемых в табл. 6.5 условных обозначений адресных регистров приведены в табл. 6.6.
Таблица 6.5
Наименование | Обозначение | Операнд |
Регистровая Прямая | reg addr16 | (reg) M(addr16) |
Косвенная регистровая | [rireg] | M((rireg)) |
По базе с 8-разрядным смещением | [bireg]. disp8 [bireg + disp8] | M((bireg) + disp8) |
По базе с 16-разрядным смещением или индексная | [bireg]. disp16 [bireg + disp16] addr16 [bireg] [addr16 + bireg] | M((bireg) + disp16) M(addr16 + (bireg)) |
По базе с индексированием без смещения | [breg] [ireg] [breg + ireg] | M((breg) + (ireg)) |
По базе с индексированием и 8-разрядным смещением | [breg] [ireg]. disp8 [breg + ireg]. disp8 [breg] [ireg + disp8] [breg + ireg + disp8] | M((breg) + (ireg) + disp8) |
По базе с индексированием и 8-разрядным смещением или с двойным индексированием | [breg] [ireg]. disp16 [breg + ireg]. disp16 [breg] [ireg + disp16] [breg + ireg + disp16] addr16 [breg] [ireg] addr16 [breg + ireg] [addr16 + breg] [ireg] | M((breg) + (ireg) + disp16) M(addr16 + (breg) + (ireg)) |
Непосредственная | data | data |
Таблица 6.6
Назначение | Мнемоника | Регистры | |||||
AX BX | CX | DX | BP | SI | DI | ||
Регистр косвенного адреса Базовый или индексный регистр Базовый регистр Индексный регистр | rireg bireg breg ireg | – + – + – + – – | – | – | – | + | + |
– | – | + | + | + | |||
– | – | + | – | – | |||
– | – | – | + | + |
Одноразрядный признак d/v выполняет двойную функцию. В некоторых командах он задает направление операции (функция d). При d = 1 поля mod r/m постбайта определяют операнд-источник src. При d = 0 ситуация меняется, поля mod r/m относятся к dst, а поле reg играет роль src. В командах сдвига и вращения этот флажок используется в качестве модификатора кода операции (функция v). Если v = 0, то реализуется обычный сдвиг вправо (влево) на один разряд, в противном случае (v = 1) выполняется параметрический сдвиг на число разрядов, кодируемых содержимым CL.
Поле port8 содержит короткий 8-разрядный адрес порта, расположенного в начальном диапазоне 0—255 адресов пространства ВВ. В других случаях это поле резервируется для кодирования типа вектора прерывания vect.
В командах условного перехода 4-разрядное поле cc применяется для кодирования 16 условий перехода. Младший разряд поля cc указывает на инверсию условия, а три старших определяют тип условия согласно табл. 6.7, который зависит от типа используемых данных. В соответствии с этим множество условий разделено на три группы: логических условий С—РО, анализа чисел со знаком L—NLE и сравнений чисел без знака B—NBE.
Таблица 6.7
Мнемоника сс | Код cc | Условие перехода | Наименование |
С | CF = 1 | Перенос | |
NC | CF = 0 | Нет переноса | |
S | SF = 1 | Отрицательный | |
NS | SF = 0 | Положительный | |
E/Z | ZF = 1 | Равно/нулевой | |
NE/NZ | ZF = 0 | Не равно/не нулевой | |
О | OF = 1 | Переполнение | |
NO | OF = 0 | Нет переполнения | |
Р/РЕ | A | PF = 1 | Четный |
NP/PO | В | PF = 0 | Нечетный |
L/NGE GE/NL LE/NG G/NLE | С D E F | SFÅОF = 1 SFÅOF = 0 (SFÅOF) V ZF = 1 (SFÅOF) V ZF = 0 | Меньше/не больше и не равно Больше или равно/не меньше Меньше или равно/не больше Больше/не меньше и не равно |
B/NAE AE/NB BE/NA A/NBE | CF = 1 CF = 0 CFVZF = 1 CFVZF = 0 | Меньше/не больше и не равно Больше или равно/не меньше Меньше или равно/не больше Больше/не меньше и не равно | |
П р и м е ч а н и е. C—Carry, N—Not, S—Sign, E—Equal, Z—Ziro, О—Overflow, P—Parity, РЕ—Parity Even, PO—Parity Odd, L—Less, G—Great, В—Below, A—Above. |
При символическом кодировании команд ВМ86 на языке ассемблера ASM86 придерживаются несколько необычных принципов. Один из них состоит в применении групповой мнемоники и отказе от различного рода модификаторов именной части команды, указывающих на типы операндов и способы доступа к ним. Это означает, что одно и то же имя, например MOV, используется как для 8-, так и 16-разрядных операндов. При этом допускаются всевозможные способы адресации, включая непосредственный. В системе команд ВМ80 для данных случаев применялись различные имена. Принцип групповой мнемоники приводит к тому, что символической команде с одним и тем же именем соответствует несколько машинных команд с разными форматами и кодами операций.
В условиях неизменной именной части вся информация о типах операндов и способах доступа к ним должна содержаться в адресных полях команды. Если способ доступа кодируется формой записи адресного выражения, что соответствует общепринятому, то тип используемых операндов связан с типом адресного выражения, введение которого служит еще одной особенностью языка ассемблера ASM86, сближающей его с языком высокого уровня.
Основу любых адресных выражений образуют такие простейшие элементы, как константы, переменные и метки. Обычно на уровне языка ассемблера они ничем не отличаются друг от друга. Язык ASM86 различает их, присваивая в момент определения различные атрибуты, включая тип (TYPE). Так, константам (возможно именованным), не имеющим ничего, кроме значения, присваивается тип CONSTANT (константа). Переменные имеют не только имя и значение, но и смещение (OFFSET), сегмент (SEGMENT) и тип, который может быть трех видов: BYTE (байт), WORD (слово) и DWORD (двойное слово). Меткам кроме имени тоже присваиваются такие атрибуты, как смещение, сегмент и тип. Различают два типа меток: NEAR (внутрисегментные) и FAR (межсегментные). Если OFFSET определяет смещение переменной или метки внутри сегмента, то атрибут SEGMENT связан с именем и соответственно с селектором логического сегмента, в котором была определена данная переменная или метка. Наконец, TYPE указывает на разрядность переменной в байтах (1, 2 и 4) или число байтов, необходимых для представления метки. Внутрисегментная метка требует только 16-разрядного поля для кодирования нового значения смещения, загружаемого в IP, межсегментная метка—двойного слова для указания полного логического адреса seg:offset загружаемого в CS:IP соответственно.
Каждое адресное выражение также имеет тип, связанный с типом входящих в его состав элементов: констант, переменных, меток. Этот тип проверяется на допустимость его применения в конкретной операции и затем используется для генерации адекватной машинной команды. Так, если метки образуют основу операндов в командах передачи управления, то переменные—основу адресных выражений во всех других командах. Например, по команде MOV AX, NAME будет сформирована машинная команда с непосредственным операндом, если NAME—поименованная константа, или с прямой адресацией, если NAME—переменная типа WORD. В остальных случаях будет выдано сообщение об ошибке.
В некоторых случаях невозможно определить тип адресного выражения. Например, DEC [BX] может быть интерпретировано, не только как декрементировать байт, адресуемый BX, но и как декрементировать слово. Такие адресные выражения называются анонимными ссылками. Иногда может возникнуть необходимость в применении некоторого объекта по назначению, отличному от того, которое предписано его типом, например осуществить переход по значению переменной или использовать имя метки в качестве переменной для организации доступа к программному коду, как к обычному элементу данных. Во всех этих ситуациях появляется необходимость в явном определении типа адресного выражения. Для этого требуются специальные операторы указания типа [38]
Оператор BYTE PTR WORD PTR DWORD PTR | Тип BYTE WORD DWORD | Оператор NEAR PTR FAR PTR | Тип NEAR FAR |
Доступ к отдельным атрибутам с целью работы с ними обеспечивает другой набор операторов, возвращающих значение соответствующего атрибута и имеющих тип CONSTANT. Среди них:
OFFSET SEG TYPE | Возвращает смещение объекта Возвращает селектор объекта Возвращаеттип объекта |
Проверки на типы, свойственные языкам высокого уровня, оберегают программы от ошибок, связанных с неправильным использованием имен. Однако они вносят ограничения, не характерные для низкоуровневых языков ассемблера. Возможность применения операторов указания типа и операторов доступа к атрибутам снимают эти ограничения, позволяет программисту использовать символьное программирование.
Дата добавления: 2019-02-07; просмотров: 515;