CodeNet / Языки программирования / Ассемблер / СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
Сегментные регистры
-----------------------------------------------------------------
Теперь мы подошли к наиболее необычному аспекту процессора
8086 - сегментации памяти. Основной предпосылкой сегментации яв-
ляется следующее: процессор 8086 может адресоваться к 1 мегабайту
памяти. Для адресации ко всем ячейкам адресного пространства в 1
мегабайт необходимы 20-разрядные сегментные регистры. Однако про-
цессор 8086 использует только 16-разрядные указатели на ячейки
памяти. Вспомним, например, что для ссылки на память используется
16-разрядный регистр BX. Как же тогда согласовать 16-разрядные
указатели процессора 8086 и 20-разрядные адреса?
Ответ состоит в том, что процессор 8086 использует двухсту-
пенчатую схему адресации. Да, используются 16-разрядные указате-
ли, но эта форма представляет собой только часть полной схемы ад-
ресации. Каждый 16-разрядный указатель памяти или смещение комби-
нируется с содержимым 16-разрядного сегментного регистра для фор-
мирования 20-разрядного адреса памяти.
Сегменты и смещения комбинируются следующим образом: значе-
ние сегмента сдвигается влево на 4 (то есть умножается на 16), а
затем складывается со смещением, как показано на Рис. 4.7.
--------------------------- ----------------
| 16-разрядный сегментный | | 16-разрядное |
| регистр | | смещение |
--------------------------- ----------------
| |
V |
-------------------- |
( умножение на 16 ) |
( /сдвиг влево на 4/ ) |
-------------------- |
| |
V |
---------------------- |
| Значение сегмента, | |
| умноженное на 16, | |
| равно 20-разрядно- | |
| му значению | |
---------------------- |
| |
| ----- |
---------->( + )<-------------
-----
|
V
---------------------------------------
| 20-разрядное значение адреса памяти |
---------------------------------------
Рис. 4.7 20-разрядные адреса памяти.
Рассмотрим, например, следующий фрагмент программы:
.
.
.
mov ax,1000h
mov ds,ax
mov si,201h
mov dl,[si]
.
.
.
Здесь для сегментного регистра DS устанавливается значение
1000h, SI устанавливается в значение 201h. Мы можем представить
их в виде 4сегмент:смещение" - 1000:201h. (Эффективные вычисления
для пары "сегмент:смещение" могут выполняться только по основа-
нию 16. Это еще одна причина необходимости познакомиться с шест-
надцатиричной арифметикой.) Адрес в DL, из которого загружается
адрес, представляет собой:
((DS * 16) + SI) или ((1000h * 16) + 201h)
1000h
Х 16
------
10000h
Этот пример иллюстрируется на Рис. 4.8.
--------------------------- ----------------
DS | 1000h | SI | 201h |
--------------------------- ----------------
| |
V |
-------------------- |
( умножение на 16 ) |
( /сдвиг влево на 4/ ) |
-------------------- |
| |
V |
---------------------- |
| 10000h | |
---------------------- |
| |
| ----- |
---------->( + )<-------------
-----
|
V
-----------------------
Адрес памяти | 10201h |
-----------------------
Рис. 4.8 Вычисление адреса памяти с помощью инструкции mov.
С другой стороны это можно рассматривать просто как сдвиг
значения сегмента на 4 бита, или одну шестнадцатиричную цифру,
что эквивалентно умножению на 16:
1000
+ 201
-----
10201
Теперь вы можете видеть, что программа получает доступ к
полному адресному пространству в 1 мегабайт с помощью использова-
ния только пары "сегмент:смещение". Фактически, для доступа к па-
мяти вы всегда должны использовать пару "сегмент:смещение". Все
инструкции и режимы адресации процессора 8086 по умолчанию рабо-
тают относительно того или иного сегментного регистра, хотя в не-
которых инструкциях можно явно указать, что нужно использовать
желаемый сегментный регистр.
Вам редко потребуется загружать значение непосредственно в
сегментный регистр. Вместо этого вы будете загружать в сегментные
регистры имена сегментов, которые в ходе ассемблирования, компо-
новки и выполнения превращаются в числа. Это необходимо, посколь-
ку нет способа сказать заранее, где в памяти будет находиться
данный сегмент: это зависит от версии DOS, числа и размера рези-
дентных в памяти программ, а также потребности в памяти остальной
части программы. Использование имен сегментов позволяет Турбо Ас-
семблеру и операционной системе DOS выполнять подобные вычисле-
ния.
Наиболее общим именем сегмента является @Date, которое в уп-
рощенных директивах определения сегментов используется для ссылки
на используемый по умолчанию сегмент данных. Например:
DOSSEG
.MODEL SMALL
.DATA
var1 DW 0
.
.
.
.CODE
mov ax,@data
mov ds,ax
.
.
.
END
Здесь регистр DS загружается таким образом, что он будет
указывать на используемый по умолчанию сегмент данных, в котором
находится Var1.
Здесь мы опять забежали вперед: упрощенные директивы опреде-
ления сегментов и загрузку сегментных регистров мы обсудим в сле-
дующей главе.
Использование сегментов процессора 8086 приводит к некоторым
интересным моментам. Один из них состоит в том, что только блок
памяти размером в 64К в любой момент может адресоваться через
сегментный регистр, так как 64К - это максимальный объем памяти,
к которой можно адресоваться с помощью 16-битового смещения. Это
может оказаться неприятным при работе с большим (более 64К) объ-
емом памяти, так как и значение сегментного регистра, и смещение,
придется часто изменять.
Адресация к большим блокам памяти в процессоре 8086 может
представлять еще большую трудность, поскольку, в отличие от ре-
гистров общего назначения (общих регистров), сегментные регистры
не могут использоваться в качестве источников или приемников в
арифметических и логических инструкциях. Фактически, единственная
операция, которую можно выполнять с сегментными регистрами, сос-
тоит в копировании значений между сегментными регистрами и други-
ми общими регистрами или памятью. Например, чтобы добавить значе-
ние 100 к регистру ES, потребуется следующее:
.
.
.
mov ax,es
add ax,100
mov es,ax
.
.
.
Из всего этого можно сделать заключение, что процессор 8086
лучше подходит для работы с памятью в блоках, не превышающих 64К.
Второй момент использования сегментов состоит в том, что
каждая ячейка памяти адресуется через многие возможные сочетания
"сегмент:смещение". Например, адрес памяти 100h адресуется с по-
мощью следующих значений "сегмент:смещение": 0:100h, 1:F0h, 2:E0h
и т.д., так как при вычислении всех этих пар "сегмент:смещение"
получается значение адреса 100h.
Аналогично регистрам общего назначения каждый сегментный ре-
гистр играет свою, конкретную роль. Регистр CS указывает на код
программы, DS указывает на данные, SS - на стек, сегмент (сегмен-
тный регистр) ES - это "трафаретный" (дополнительный) сегмент,
который может использоваться так, как это необходимо. Рассмотрим
сегментные регистры более подробно.
