Адрес ячейки
В компьютерах на базе процессоров 8086/8088 адресная шина имеет 20 линий. Поэтому с их помощью можно задавать адрес в адресном пространстве размером 1 М = 1 Мегабайт = 220 байт = 1024 К = 1048576 байт. Внутренняя память центрального процессора состоит из 16-разрядных ячеек, называемых регистрами. В то же время физические адреса ячеек памяти 20-разрядные, заведомо в 16 разрядах не умещаются. Возникает вопрос: как хранить в регистрах процессора адреса ячеек памяти?
Сначала подсчитаем, какой объем памяти можно адресовать с помощью 16-разрядного регистра 216 = 26 210 = 26 К = 64 К. Дадим определение: сегмент — блок адресного пространства размером 64 Кбайта, начальный адрес сегмента кратен 16 = 10h (т.е. младшие 4 бита адреса – нулевые). Если сегмент пересекает верхнюю границу памяти, то он усекается. Адрес сегмента хранится в 16-разрядной ячейке без младших четырех битов. После умножения на 10h (это сводится к приписыванию справа одного 16-ричного нуля, или четырех двоичных нулей) получается физический адрес сегмента. Чтобы получить физический адрес ячейки памяти, нужно взять адрес какого-либо сегмента, в котором находится эта ячейка. "Расстояние" от адреса сегмента до ячейки называется смещением (offset). Смещение внутри сегмента также хранится в 16-разрядной ячейке. Оно складывается с физическим адресом сегмента и получается физический адрес ячейки. Эти вычисления автоматически проделывает центральный процессор. Итак, (физический адрес) = (адрес сегмента)*10h + (смещение), т.е. address = segment*10h + offset. Адрес записывается так: segment:offset (или короче: seg:off).
Как правило, программа на языке Ассемблера укладывается в один сегмент и работает с данными в пределах одного сегмента, поэтому в дальнейшем мы будем говорить "адрес", понимая под этим "смещение".
Регистры центрального процессора (ЦП)
ЦП имеет свою небольшую быструю память. Ячейки этой памяти носят название регистров. Все они программно доступны. При написании программ следует по возможности хранить промежуточные результаты именно в регистрах, а не в ячейках оперативной памяти. Тогда быстродействие программы увеличится.
В ЦП 14 регистров. Они делятся на группы.
1) Регистры общего назначения — РОН (General Purpose Registers). Они в свою очередь делятся на две подгруппы.
1.1) HL-регистры. Это четыре 16-разрядных регистра с именами AX, BX, CX, DX (рис.1.4). Можно также обращаться по отдельности к старшим и младшим байтам этих регистров. Например, старший байт AX — это регистр AH (High — старший), младший байт — AL (Low — младший). (Именно поэтому эта подгруппа регистров носит название HL — high-low)
AX — accumulator — аккумулятор,
BX — base register — регистр базы,
CX — counter register — счётчик,
DX — data register — регистр данных.
1.2) PI-регистры (рис.1.5). Это четыре 16-разрядных регистра с именами SI, DI, SP, BP. Они предназначены для хранения адресов (точнее, смещений), что и оправдывает название подгруппы (PI — Pointer-Index — указательно-индексные). К их старшим и младшим байтам отдельно обращаться нельзя.
Названия регистров расшифровываются так:
SP — Stack Pointer — указатель стека,
BP — Basa Pointer — указатель базы стека,
(регистры SP и BP предназначены для работы со стеком).
SI — Source Index — индекс источника,
DI — Destination Index — индекс приемника.
В команде можно непосредственно указывать адрес операнда. Но если хранить адрес в регистре, а в команде указывать имя регистра, то длина кода команды сокращается. Кроме того, над содержимым регистров можно выполнять арифметические операции. Допустим, мы записали в SI адрес массива двойных слов. Тогда, чтобы перейти к обработке очередного элемента массива, достаточно увеличить SI на 4.
2) Указатель команд — Instruction Pointer (рис.1.6). Он содержит смещение (offset) инструкции, подлежащей выполнению.
3) Сегментные регистры (рис.1.7). Сегментный регистр содержит адрес сегмента без младших четырех бит (они всегда равны нулю, поэтому их можно без ущерба отбросить).
CS — Code Segment — программный (кодовый) сегмент,
DS — Data Segment — сегмент данных,
SS — Stack Segment — сегмент стека,
ES — Extra Segment — дополнительный сегмент данных.
CS указывает, как правило, на сегмент памяти, содержащий машинные инструкции, DS и ES — на сегменты, содержащие данные, SS — на сегмент, где расположен стек. Оговорка "как правило" существенна. Например, в сегменте, адрес которого в CS, могут содержаться и данные.
Адрес очередной команды, которую предстоит выполнить, хранится в регистрах CS и IP В CS хранится сегментная часть адреса, а в IP - смещение.
Регистр флагов (Flags) (рис.1.8).
Флаги делятся на три группы: флаги состояния CF, PF, AF, ZF, SF, OF отображают некоторые характеристики результата выполнения команды - они устанавливаются или сбрасываются центральным процессором; системные флаги TF, IF и флаг управления DF задают режимы работы ЦП и явно устанавливаются специальными командами.
Опишем назначение флагов состояния.
CF — carry flag — флаг переноса. При сложении сюда попадает бит переноса из знакового разряда. CF изменяется и по результатам некоторых других команд.
PF — parity flag — флаг чётности. Установлен, если младший байт результата содержит чётное число единиц. Используется для тестирования памяти.
AF — auxiliary flag — флаг вспомогательного переноса. Равен значению бита переноса из младшей тетрады в старшую в младшем байте (т.е. перенос из 3-го в 4-й бит). Используется при работе с двоично-десятичными числами.
ZF — zero flag — флаг нуля. Установлен, если результат нулевой; сброшен, если результат ненулевой.
SF — sign flag — флаг знака. Равен знаковому биту результата. Стало быть, установлен, если результат отрицательный; сброшен, если неотрицательный.
OF — overflow flag — флаг знакового переполнения. Установлен, если результат арифметической операции лежит вне допустимого диапазона.