Анализ систем адресации
1. ОТЛИЧИЯ МИНИ- И МИКРОЭВМ.
В конце 60-х годов начался серийный выпуск сравнительно небольших и дешевых
мини-ЭВМ. Их предназначали для предприятий и организаций, где установка
высокопроизводительных ЭВМ была экономически невыгодной. В их задачу
первоначально входила автоматизация профессиональной работы в различных
организациях, работа на предприятиях в качестве проблемноориентированных ЭВМ. В
1977-78 году был начат выпуск семейства малых ЭВМ (СМ ЭВМ). Их часто называли
управляющими вычислительными комплексами, так как они чаще всего использовались
в системах управления различного рода. Однако, СМ 3-ей очереди, разработанные в
последние годы относятся уже к ЭВМ четвертого поколения и имеют большую
производительность, поэтому круг их применения резко расширился, и их активно
используют в качестве автоматизированных рабочих мест, объединяют в
вычислительные системы, и поручают им расчет экономических и статистических
задач. С появлением больших интегральных схем связано развитие другого класса
машин - микроЭВМ, и, как достижение этого направления - появление мощных
профессиональных ПЭВМ, которые используются на рабочих местах для автоматизации
труда, несложных расчетов и различного рода проектирования. Основным отличием
мини- от микроЭВМ несомненно является ориентация. Машины СМ ЭВМ выпускались как
проблемно ориентированные ЭВМ и поддерживались большим количеством различных
модулей определяющих их специализацию, в то время как ПЭВМ - это универсальные
ЭВМ, рассчитанные помимо применения в профессиональной деятельности еще и на
применение в качестве обучающих и бытовых ЭВМ. По функциональным возможностям
мини- и микроЭВМ имеющие примерно один и тот же уровень не отличаются друг от
друга, как это должно быть для машин разного класса, т.е. учитывая что мини-ЭВМ
считается более мощной чем микроЭВМ, а в частности ПЭВМ. Для сравнения возьмем
супермини-ЭВМ СМ 1700 и современную персональную ЭВМ на базе 32-разрядного
процессора.
СМ 1700AMD 80386 DX 40Mhz
Производительность, млн.оп./с39.6
Разрядность3232
Емкость ОЗУМбайт5-151-128
Все данные по процессору AMD386 взяты из документации на Ali 386 MINI ISA System
Board. Как видно с развитием элементной базы ПЭВМ, задуманные как менее мощные,
чем мини-ЭВМ персональные компьютеры обогнали их по производительности.
2. СИСТЕМЫ АДРЕСАЦИИ ИСПОЛЬЗУЕМЫЕ В МИНИ-ЭВМ
В этой главе будут рассмотрены способы адресации данных, используемые в мини-ЭВМ
на примере СМ1700. Это первый представитель 32-разрядных ЭВМ семейства СМ.
Вычислительный комплекс СМ1700 представляет собой универсальную ЭВМ. Одна из
основных целей его создания - это расширение виртуального адресного пространства
по сравнению с 16-разрядной СМ4. Хотя некоторые инструкции вычислительного
комплекса СМ1700 имеют сходство с инструкциями СМ4, СМ1700 представляет собой
полностью новую архитектуру. Аппаратные средства СМ1700 ориентированы на
реализацию языков высокого уровня и системных программ, которые используются
операционной системой и компилятором. Система команд СМ1700 в настоящее время
включает 304 инструкции и более 20 режимов адресации операндов. Все это дает
возможность программисту составлять эффективные по объему и времени выполнения
программы. Какие же способы адресации предусмотрены в СМ1700? Мы рассмотрим
несколько способов адресации, которые в общем можно поделить на регистровые,
косвенные, индексные и специальные.
2.1 РЕГИСТРОВЫЙ РЕЖИМ АДРЕСАЦИИ
В этом режиме операндом является содержимое регистра.Рассмотрим инструкцию MOVL
R2,R3. Для СМ ЭВМ характерно, что приемником всегда является второй операнд для
двух- и третий для трех-операндных инструкций. Поэтому инструкция MOVL R2,R3
пересылает содержимое регистра R2 в регистр R3, а не наоборот, как было бы с
аналогичной инструкцией MOV AX,BX из набора команд процессоров cемейства 8086
фирмы Intel. Приведем пример использования этого способа адресации на примере
инструкции MOVL R2,R3. Ее машинная запись будет выглядеть, как D0 52 53, где D0
- код инструкции, а 52 и 53 - прямая адресация, 2ой регистр и прямая адресация,
3ий регистр соответственно.
Пусть содержимое регистров до операции было:
R2 = 00000010
R3 = 00001000
Тогда после они будут выглядеть так:
R2 = 00000010
R3 = 00000010
Как видно из примера, содержимое регистра R2 было скопировано в R3.
2.2 КОСВЕННО-РЕГИСТРОВЫЙ РЕЖИМ
В этом режиме содержимое регистра является адресом операнда. Мнемоника на
ассемблере (Rn), где (Rn) является регистром содержащим либо адрес операнда
источника {MOVL (R2),R3} либо адрес операнда приемника {MOVL R2,(R3)}. В
качестве примера опять приведем инструкцию пересылки двойного слова MOVL
R2,(R3). Код операции останется тот же, а операнды будут представлены как 52 63,
где 63 - это уже косвенная адресация с использованием 3го регистра. При том же
содержимом регистров, что и в предыдущем примере, будем иметь:
До операции MOVL R2,(R3):
R2 = 00000010
R3 = 00001000
(00001000) = 00000200 (R3)
После...
R2 = 00000010
R3 = 00001000
(00001000) = 00000010
После операции пересылки значение ячейки памяти, адрес которой содержался в R3
(00001000) изменился с 000000200 на 00000010.
2.3 РЕЖИМ С АВТОУВЕЛИЧЕНИЕМ
Специально для обработки массивов данных в CM1700 предусмотрена адресация с
автоувуличением. В этом режиме содержимое выбранного регистра является адресом
операнда, как ипри косвенно-регистровой адресации, однако после выполнения
операции содержимое регистра увеличивается на N, в зависимости от типа операнда:
N = 1, если операндом является байт,
N = 2, если операндом является слово,
N = 4, если операндом является двойное слово,
N = 8, если операндом является учетверенное слово или слово с плавающей запятой,
N =16, если операндом является целое слово длиной 128 разрядов или двойное слово
с плавающей запятой.
Рассмотрим этот режим адресации используя команду MOVL (R0),(R2)+. В памяти
инструкция будет представлена как D0 60 82, где 60 - как уже говорилось
косвенная адресация с регистром R0, а 82 - косвенная адресация с использованием
регистра R2 и автоувеличение. Восьмерка в последнем случае как раз и означает
данный режим адресации.
До операции MOVL (R0),(R2)+
R0 = 00001000
R2 = 00001050
(00001000) = 000000AC (R3)
(00001050) = 00000000 (R2)
После...
R0 = 00001000
R2 = 00001054 <—— Увеличилось на 4
(00001000) = 000000AC
(00001050) = 000000AC
Как видно произошла пересылка числа из ячейки 00001000 в 00001050 и значение
регистра R2 увеличилось на 4. ( Инструкция MOVL пересылает двойные слова. Об
этом говорит суффикс 'L' - Long - длинное или двойное слово. Поэтому R2
увеличился на 4. Вообще предусмотрены операции работающие с байтами, словами,
двойными словами и иногда с учетверенными словами и имеющие суффиксы B,W,L и Q
соответственно.)
2.4 РЕЖИМ С АВТОУМЕНЬШЕНИЕМ
Этот режим идентичен режиму с автоувеличением, однако здесь после выполнения
операции следует не увеличение, а уменьшение операнда по тем же правилам. Для
примера рассмотрим команду CLRB -(R5), которая в памяти будет выглядеть как 94
75. Здесь 94 - код операции, а 75 - значит: использовать регистр R5 ( ?5 ) и
произвести уменьшение после исполнения ( 7? ).
До операции CLRB -(R5)
R5 = 00001000
(00000FFF) = 0000001A
(000001000) = 0000001A (R5)
После...
R5 = 00000FFF <—— уменьшилось на 1
(00000FFF) = 0000001A (R5)
(000001000) = 00000000 <—— 0
Изменения хорошо видны. Ячейка 00001000, на которую первоначально указывал
регистр R5 очистилась ( CLRB - CLeaR Byte - очистить байт ),значение регистра R5
уменьшилось на 1 и теперь указывает на ячейку памяти расположенную перед ячейкой
00001000, т.е. 00000FFF.
2.5 КОСВЕННЫЙ РЕЖИМ С АВТОУВЕЛИЧЕНИЕМ
В этом режиме содержимое выбранного регистра является адресом адреса операнда, а
после выполнения операции производится увеличение содержимого этого регистра на
4, независимо от размера операнда. Это определяется тем, что регистр содержит
адрес адреса ( т.е. адрес ячейки, содержимое которой в свою очередь используется
как адрес для получения действительного операнда ), а адрес всегда
представляется как двойное слово.
Для примера возьмем операцию очистки байта, мнемоника которой на ассемблере
будет выглядеть как CLRB @(R5)+. Символ '@' ( зюха ) означает использование не
просто режима с автоувеличением, а именно косвенного. Представление этой
операции в памяти будет 94 95, где 94 - код операции, 95 - означает
использование регистра R5 и косвенной адресации с автоувеличением (цифра 9).
До операции CLRB @(R5)+
R5 = 00001000
(00001000) = 000000AC (R5)
(000000AC) = 0A (00001000)
После...
R5 = 00001004 <—— увеличилось на 4
(00001000) = 000000AC
(000000AC) = 00 <—— 0
В результате выполнения этой команды содержимое ячейки 000000AC, адрес которой
cодержался в ячейке 00001000, на которую указывал регистр R5 обнулилось, а
значение регистра R5 увеличилось на 4.
2.6 РЕЖИМ СМЕЩЕНИЯ
В этом режиме содержимое выбранного регистра складывается с содержимым байта,
слова или двойного слова, следующего непосредственно за спецификатором операнда.
Полученная сумма является адресом операнда. Мнемоники на ассемблере для 3ех
случаев имеют вид: B^X(Rn), W^X(Rn), L^X(Rn), где X смещение, относительно (Rn).
Возможность задавать размерность смещения предусмотрена для экономии памяти.
Рассмотрим этот способ адресации на примере команды CLRB B^2(R4), которая
очистит 3ий байт байтового массива, адрес которого содержится в регистре R5. Ее
машинное представление выглядит как 94 A4 02, где 94 - код операции, A4 -
регистр R4 и смещение представлено байтом ( для слова и двойного слова было бы
C4 и E4 соответственно, а третье поле представляло бы смещение как слово или
двойное слово ), а 02 собственно смещение, представленное в виде байта.
До операции CLRB B^2(R4)
R4 = 00001000
(00001000) = 00 (R4)
(00001001) = 01
(00001002) = 02 (R4)+2
После...
R4 = 00001000
(00001000) = 00 (R4)
(00001001) = 01
(00001002) = 00 <—— 0
В результате выполнения команды действительно произошло очищение ячейки
00001002, заданной начальным адресом 00001000 и смещением 2. Этот режим
адресации позволяет легко обращаться к отдельным элементам массивов, что очень
удобно.
2.7 КОСВЕННЫЙ РЕЖИМ СМЕЩЕНИЯ
В этом режиме содержимое выбранного регистра складывается со смещением ( байт,
слово или двойное слово следующее непосредственно за спецификатором операнда ) и
полученная сумма рассматривается как адрес двойного слова, которое является
адресом операнда. Мнемоническое представление на ассемблере @B^X(Rn), @W^X(Rn) и
@L^X(Rn) для смещения X в байт, слово или двойное слово соответственно. Rn - это
регистр,используемый в данном способе адресации.
В качестве примера возьмем инструкцию MOVW @B^8(R5),(R2), которая должна занести
в память по адресу (R2) число, на которое указывает двойное слово, по адресу
получаемому при сложении содержимого регистра R2 со смещением 8. На машинном
языке эта инструкция будет иметь вид B0 B5 08 62, где В0 - код инструкции, B5 -
регистр R5 и байтовое смещение, 08 - смещение и 62 - косвенная адресация с
использованием регистра R2.
До операции MOVW @B^8(R5),(R2)
R5 = 00001000
R2 = 00000400
(00001000) = 00000100 (R5)
(00001004) = 00000200
(00001008) = 00000300 (R5)+8
(00000300) = AAAA @(R5)+8
(00000400) = 0000 (R2)
После...
R5 = 00001000
R2 = 00000400
(00001000) = 00000100 (R5)
(00001004) = 00000200
(00001008) = 00000300 (R5)+8
(00000300) = AAAA
(00000400) = AAAA
Как видно из примера в ячейку 00000400 было занесено содержимое ячейки 00000300.
Адрес 0000300 был вычислен как содержимое R5 ( 00001000 ) плюс 8 т.е. 00001008.
Эта ячейка, как видно, действительно содержит адрес 00000300.
2.8 РЕЖИМ КОРОТКОГО ЛИТЕРАЛА
Так как многие литералы (числа), используемые в программах, имеют небольшой
размер, то в СМ1700 предусмотрен специальный режим адресации, называемый режимом
короткого литерала. В этом режиме константа содержится непосредственно в самом
спецификаторе операнда. Любой спецификатор операнда, два старших разряда
которого равны нулю содержит литеральную константу в младших шести разрядах.
00 ?????? <—— байт спецификатор операнда
литерал
С помощью литерала в инструкции могут быть представлены целые числа в диапазоне
от 0 до 63. Мнемоника на ассемблере S^#n, где n - литерал. Рассмотрим инструкцию
MOVL S^#18,R3 которая в памяти будет представлена в виде D0 18 53. Здесь D0 -
код инструкции, 18 - литерал, 53 - регистр R3 при прямой адресации.
До операции MOVL S^#18,R3
R3 = 00001234
После...
R3 = 00000018
Из примера видно, что литерал был занесен в регистр R3
2.9 ИНДЕКСНЫЙ РЕЖИМ
Одним из наиболее мощных средств адресации в СМ1700 является использование
регистров общего назначения для определения индекса элемента в массива данных.
Вот формат спецификатора команды:
15 11 7 3 0
КБРА НБР КИР НИР
где КБРА - код базового режима адресации,
НБР - номер базового регистра,
КИР - код индексного режима (0100),
НИР - номер индексного регистра.
Как видно разряды 15 - 8 содержат второй спецификатор операнда, который
называется базовым. Он может определять любой режим адресации, кроме
регистрового, короткого литерала и индексного. Если базовый спецификатор требует
расширения, то это расширение следует непосредственно за спецификатором.
Спецификатор обычно определяет адрес начала массива, а в индексном регистре Rx
содержится номер элемента массива. При определении эффективного адреса операнда
сначала вычисляется базовый адрес массива или таблицы. Затем содержимое
индексного регистра умножается на 1, 2, 4 или 8, в зависимости от размера
операнда и прибавляется к базовому адресу. Используя этот режим адресации
совместно с уже описанными можно получить следующие режимы адресации :
Косвенно-регистровый индексный, (Rn)[Rx].
С автоувеличением индексный, (Rn)+[Rx].
Косвенный с автоувеличкнием индексный, @(Rn)+[Rx].
С автоуменьшением индексный, -(Rn)[Rx].
Смещения индексный, N^X(Rn)[Rx], где N может принимать значения B, W, L.
Косвенный смещения индексный, @N^X(Rn)[Rx]
При работе со структурами данных индексный режим гораздо удобнее, чем просто
режим смещения. Во-первых, здесь имеется мощный режим задания начального адреса
массива с помощью одного из основных режимов адресации, что позволяет легко
модифицировать этот адрес. Во вторых, программист в индексном регистре [Rx]
указывает только номер элемента, а необходимое смещение вычисляется
автоматически из контекста операнда. Так, инструкция CLRB B^2(R4), реализующая
режим смещения ( пункт 2.6 ) может выглядеть как CLRB (R0)[R4] и если в R0
находится адрес массива, а в R4 смещение, то она аналогично первой инструкции
очистит 3ий элемент массива.
До операции CLRB (R0)[R4]
R0 = 00001000
R4 = 00000002
(00001000) = 00 (R0)
(00001001) = 01
(00001002) = 02 (R0)+[R4]*1
После...
R0 = 00001000
R4 = 00000002
(00001000) = 00 (R0)
(00001001) = 01
(00001002) = 00 <—— 0
Пример доказывает абсолютную идентичность этих инструкций.
2.10 РЕЖИМЫ АДРЕСАЦИИ С ИСПОЛЬЗОВАНИЕМ СЧЕТЧИКА ИНСТРУКЦИЙ.
Одним из неудобств описанных выше способов адресации является то, что во всех
них требуется предварительная загрузка одного из регистров общего назначения.
Только после того, как регистр загружен, содержимое его может быть использовано
в качестве указателя начала массива, адреса элемента и т.д. При однократном
обращении к произвольной ячейке такой способ является неудобным и неэффективным,
так как требует по сути выполнения двух операций вместо одной - предварительной
загрузки адреса в регистр и собственно обращение к памяти через этот регистр с
помощью одного из режимов адресации. Однако эту операцию можно реализовать
гораздо проще, если использовать счетчик инструкций. Регистр R15 является
счетчиком инструкций, и одновременно регистром общего назначения, то есть
доступен программисту для использования в качестве базового регистра и т.д. Это
очень упрощает жизнь программисту, однако требует повышенной внимательности,так
как использование этого регистра например при адресации с автоуменьшением
приведет к непредсказуемому результату. Фактически со счетчиком инструкций
используются только четыре режима адресации: с автоувеличением, косвенный с
автоувеличением, смещения и косвенный смещения. Это дает с точки зрения
программиста ( но не аппаратно ) четыре дополнительных режима адресации:
непосредственный, абсолютный, относительный и косвенно-относительный.
Рассмотрим алгоритм выполнения режима с автоувеличением при использовании
счетчика инструкций в качестве регистра общего назначения. По определению режима
с автоувеличением операция производится над операндом, на который указывает
выбранный регистр. Если мы используем счетчик инструкций, то он в этот момент
будет указывать на ячейку непосредственно следующую за спецификатором операнда.
Таким образом операнд оказывается непосредственно в потоке инструкций. После
выборки операнда содержимое счетчика увеличится на размер операнда, определяемый
кодом операции. Длина константы должна соответствовать типу инструкции, даже
если ее фактический размер меньше, только тогда после автоувеличения содержимого
счетчика инструкций он будет содержать правильный адрес следующей команды. Для
примера рассмотрим инструкцию MOVB #10,(R2)
До операции MOVB #10,(R2)
00000305 : 90 КОП
00000306 : 8F <——— представление '(R15)+'
00000307 : 10 <——— константа
00000308 : 62 <——— представление '(R2)'
R2 = 00001000
R15 = 00000305
(00001000) = FF (R2)
После...
R2 = 00001000
R15 = 00000309
(00001000) = 10 (R2)
При компиляции инструкция MOVB #10,(R2) была заменена на MOVB (R15)+(R2), а
константа была помещена в поток инструкций, и была успешно адресована и
скопирована по адресу (00001000).
Если использовать косвенный режим с автоувеличением, то по определению режима
содержимое счетчика инструкций является не адресом операнда, а адресом адреса
операнда, а после выполнения инструкции значение счетчика увеличится на 4, так
как мы передаем 32-разрядные адреса. Таким образом мы имеем возможность задать
прямо в коде инструкции абсолютный адрес операнда. Если в предыдущем примере
использовать этот пример, то по адресу (00001000) будет занесено не число 10, а
значение ячейки 10. На ассемблере такая инструкция будет иметь мнемонику MOVB
@#10,(R2):
До операции MOVB @#10,(R2)
00000305 : 90 КОП
00000306 : 9F <——— представление '@(R15)+'
00000307 : 10
00000308 : 00
00000309 : 00
0000030A : 00
0000030B : 62 <——— представление '(R2)'
R2 = 00001000
R15 = 00000305
(00000010) = 00
(00001000) = FF (R2)
После...
R2 = 00001000
R15 = 00000309
(00000010) = 00
(00001000) = 00 <——— 0
Есть определенный класс программ, которые называются позиционно-независимыми.
Они могут быть загружены и запущены в любой области памяти без перетрансляции,
перелинковки или модификации адресов операндов. При перемещении в памяти
программы, использующей косвенно-регистровый режим адресации адрес адресуемой
ячейки не изменяется. Если данные в памяти перемещаются вместе с программой, как
это чаще всего бывает, то адресоваться будут совсем не те данные, которые должны
бы. Что делать в таких случаях ? Рассмотрим как использовать счетчик инструкций
в режиме со смещением. Содержимое регистра счетчика инструкций складывается со
смещением, которое расположено непосредственно в потоке инструкций. Полученная
сумма является адресом операнда. Очевидно, что в этом случае данные будут
адресоваться правильно, так как если подобрать смещение равное разнице между
адресом операнда и адресом текущей команды, то эта разность всегда будет
постоянной. Этот режим адресации называется относительным и на ассемблере
записывается просто как Addr, где Addr - адрес операнда. Рассмотрим выполнение
инструкции MOVB 10,(R2)
До операции MOVB 10,(R2)
00000305 : 90 КОП
00000306 : CF <——— представление '@(R15)'
00000307 : 07 отрицательное смещение (309-10),
00000308 : FD представленное в доп. коде
00000309 : 62 <——— представление '(R2)'
R2 = 00001000
R15 = 00000305
(00000010) = 00
(00001000) = FF (R2)
После...
R2 = 00001000
R15 = 0000030A <——— + 5
(00000010) = 00
(00001000) = 00 <——— 0
Отметим, что смещение в данном примере отрицательное и представлено в
дополнительном коде. Длина смещения и соответствующий конкретный код режима
вычисляется автоматически на этапе компилирования. Если использовать счетчик
инструкций в косвенном режиме со смещением, то получим еще один способ
адресации, который называется косвенно-относительным. Здесь сумма содержимого
счетчика инструкций складывается со смещением и рассматривается как адрес адреса
операнда. Для программиста этот режим является просто режимом косвенной
адресации с использованием произвольной ячейки для хранения адреса. Как и в
предыдущем примере смещение должно быть равно разнице между адресом данной
ячейки и текущим положением инструкции. На ассемблере этот режим обозначается
@Addr, где Addr - адрес ячейки, в которой находится адрес операнда. Рассмотрим
инструкцию MOVB @10,(R2):
До операции MOVB @10,(R2)
00000305 : 90 КОП
00000306 : CC <——— представление '@W^FD7(R15)'
00000307 : 07 отрицательное смещение (309-10),
00000308 : FD представленное в доп. коде
00000309 : 62 <——— представление '(R2)'
R2 = 00001000
R15 = 00000305
(00000000) = EE (00000010)
(00000010) = 00
(00001000) = FF (R2)
После...
R2 = 00001000
R15 = 0000030A <—— + 5
(00000000) = EE
(00000010) = 00
(00001000) = EE <—— EE
2.11 АДРЕСАЦИЯ ПЕРЕХОДОВ.
Последний способ адресации, который будет рассмотрен - это адресация переходов.
Вот формат инструкции условного перехода:
7--------------------------------------------0
КОД ОПЕРАЦИИ
СМЕЩЕНИЕ
Адресация в этих инструкциях отличается от всех рассматриваемых тем, что здесь
нет спецификатора операнда. Каждая инструкция условного перехода состоит из кода
операции и следующего за ним байтного смещения со знаком. При формировании
адреса перехода смещение складывается с содержимым счетчика инструкций подобно
тому, как это делалось при относительной адресации. Почему всего 128 байт ? Это
обусловлено тем, что большинство переходов адресованы к ячейкам, находящимся на
небольшом расстоянии от самой инструкции перехода. Лишь в некоторых случаях
требуется использование более эффективных режимов адресации.
3. СИСТЕМЫАДРЕСАЦИИ ИСПОЛЬЗУЕМЫЕ В ПЭВМ
Системы адресации используемые в персональных ЭВМ будут рассмотрены на примере
32-разрядного процессора 80386 фирмы Intel. Все что касается этого процессора,
системы его команд и способов адресации можно так же отнести к 386-ым
процессорам фирм Cyrix и AMD (Advanced Micro Devices), которые полностью
совместимы с I80386. МП 80386 представляет собой высокопроизводительный
32-разрядный микропроцессор, выполняющий 3-4 МОПС (MIPS). Он отличается полной
32-разрядной архитектурой с физическим адресным остранством 4 Гбайт и
встроенными средствами страничной виртуальной памяти, МП 80386 может адресовать
64 Тбайт виртуальной памяти. Система команд МП 80386 содержит 9 категорий
команд: пересылки данных, арифметических, сдвига, обработки строк, обработки
битов, передачи управления, поддержки языков высокого уровня, поддержки
операционной системы и управления процессором. Длина команды в среднем
составляет 2-3 байта. Операнды могут иметь длину 8,16 или 32 разряда.
МП 80386 реализует сегментную организацию памяти, при которой физический адрес
ячейки вычисляется путем сложения базового адреса сегмента и относительного
адреса ячейки внутри сегмента. Базовый адрес определяется содержимым
16-разрядного сегментного регистра и зависит от режима работы микропроцессора.
Если микропроцессор работает в режиме обработки 16-разрядных данных ( режим
реальных адресов или режим виртуального процессора 8086), то 20-разрядный
базовый адрес формируется путем сдвига содержимого сегментного регистра на
четыре разряда влево. Т.е. если в сегментном регистре содержится число 45F7, то
базовый адрес будет 45F70. Если микропроцессор работает в режиме обработки
32-разрядных данных ( защищенный режим ), то 32-разрядный базовый адрес
содержится в дескрипторе, выбор которого из таблицы дескрипторов осуществляется
с помощью селектора - содержимого соответствующего сегментного регистра. В
зависимости от типа обращения к памяти производится выбор сегментного регистра и
способа определения относительного адреса. Для некоторых способов обращения к
памяти возможны варианты выбора сегментных регистров. Эти варианты могут быть
выбраны с помощью префикса замены сегмента SEG. На мнемонике ассемблера это
выглядит просто как DS:[?], ES:[?], CS:[?], FS:[?] и т.д. В качестве
относительного адреса используется содержимое регистров EIP(IP), ESP(SP),
ESI(SI), EDI(DI) или эффективный адрес EA, который формируется в соответствии с
заданным способом адресации (косвенный, индексный и т.д.).
1. Выборка команд.
Сегментный регистр CS ( Code Segment )
Относительный адрес EIP(IP) ( Instruction Pointer )
2. Обращение к стеку.
Сегментный регистр SS ( Stack Segment )
Относительный адрес ESP(SP) ( Stack Pointer )
3. Адресация операнда.
Сегментный регистр DS или (CS,SS,ES,FS,GS)
Относительный адрес EA
4. Адресация элемента строки-источника.
Сегментный регистр DS или (CS,SS,ES,FS,GS)
Относительный адрес ESI(SI)
5. Адресация элемента строки-приемника.
Сегментный регистр ES
Относительный адрес EDI(DI)
6. Адресация операнда с использованием в качестве базового регистра EBP(BP) или
ESP(SP).
Сегментный регистр SS или (CS,DS,ES,FS,GS)
Относительный адрес EA
Эффективный адрес операнда EA является 16- или 32-разрядным и формируется в
зависимости от значения определенных полей в представлении команды. В общем
случае EA образуется путем сложения трех компонент:
содержимого базового регистра EBP(BP) или EBX(BX);
содержимого индексного регистра ESI(SI) или EDI(DI);
8-, 16- или 32-разрядного смещения, заданного непосредственно в команде.
разных случаях для формирования EA используются либо все либо часть этих
слагаемых. Теперь рассмотрим конкретные способы адресации.
3.1 НЕПОСРЕДСТВЕННАЯ АДРЕСАЦИЯ.
В качестве операнда используется один, два или четыре последних байта команды.
Такой способ адресации реализуется при выполнении ряда команд пересылки (MOV,
PUSH), арифметических операциях (ADD, ADC, SUB, SBB, CMP, IMUL), и логических
(AND, OR, XOR, TEST). Рассмотрим простой пример - умножение содержимого
регистра на константу:
Регистры до выполнения IMUL AX,5
AX = 10
После...
AX = 50
3.2 РЕГИСТРОВАЯ АДРЕСАЦИЯ.
При этом способе адресации операндом берется содержимое регистра. Например для
операции занесения на стек реализация регистрового способа адресации будет
выглядеть как PUSH DS.
Регистры до выполнения PUSH DS
DS = 5678h
SP = FFFEh
SS:FFFE = 0000h
После...
DS = 5678
SP = FFFDh
SS:FFFD = 5678
SS:FFFE = 0000
Как видно из примера значение регистра DS было занесено на стек.
3.3 КОСВЕННО-РЕГИСТРОВАЯ АДРЕСАЦИЯ.
При такой адресации относительный адрес содержится в индексном (SI, DI, ESI,
EDI) или базовом ( BX, BP, EBX, EBP) регистрах или в регистрах общего
назначения EAX, ECX, EDX. Адрес операнда вычисляется как сегмент:смещение.
Смещение представлено эффективным адресом.
Для примера рассмотрим команду MOV EBX,[EDI], которая пересылает содержимое
ячейки DS:[EDI] в регистр EBX. ( В качестве размера операнда берется двойное
слово - 4 байта.
Регистры до выполнения MOV EBX,[EDI]
EBX = 5678h
EDI = 0100h
DS:0100h = 1221h (edi)
После...
EBX = 1221h <——— 1221h
EDI = 0100h
DS:0100h = 1221h
Пример в комментариях не нуждается. Число, адрес которого DS:EDI было успешно
занесено в регистр EBX. Регистр DS использовался по умолчанию.
3.4 ПРЯМАЯ АДРЕСАЦИЯ.
При этом способе адресации смещение в сегменте до операнда задано в виде слова
или двойного слова в коде команды. Для примера возьмем операцию MOV
EAX,[1994h], пересылающую двойное слово по адресу DS:1994 в регистр EAX.
Регистры до выполнения MOV EAX,[1994h]
EAX = 0000h
DS:1994h = 5000h
После...
EAX = 5000h <—— 5000h
DS:1994h = 5000h
Из примера видно, что число, прямо адресованное как ds:[1994h] было
скопировано в заданный регистр.
3.5 БАЗОВАЯ АДРЕСАЦИЯ.
Относительный адрес операнда формируется при сложении содержимого базового
регистра с непосредственным смещением. Смещение может быть представлено словом
или двойным словом. Рассмотрим инструкцию ADD AX,[BP+10h], которая к
содержимому регистра AX прибавляет число, адрес которого DS:[BP+10h]...
Регистры до выполнения ADD AX,[BP+10h]
AX = 0067h
BP = 0100h
DS:0100h = 0000h (bp)
DS:0101h = 0001h
· · · · · ·
DS:0109h = 0009h
DS:0110h = 0010h (bp+10h)
После...
AX = 0077h <—— (67h+10h = 77h)
BP = 0100h
DS:0100h = 0000h
DS:0101h = 0001h
· · · · · ·
DS:0109h = 0009h
DS:0110h = 0010h
Как видно из примера, к содержимому BP было добавлено 10h и получилось
смещение 110h, по которому и было взято число, прибавленное к AX.
3.6 ИНДЕКСНАЯ АДРЕСАЦИЯ.
Примерно тоже самое, что и базовая адресация, однако здесь и используются
индексные регистры ( SI,DI ) и смещение заданное байтом или словом. При
формировании 32-разрядных адресов, в качестве базового или индексного может
использоваться любой из регистров EAX, ECX, EDX, EBX, EBP, ESI, EDI.. Для
примера возьмем инструкцию MOV WORD PTR ES:[DI+2],AX, которая по адресу
ES:[DI+2] зашлет слово из AX.
Регистры до выполнения MOV WORD PTR ES:[DI+2],AX
AX = 0099h
DI = 000Dh
ES:000Dh = 0000h (di)
ES:000Fh = 0000h (di+2)
После...
AX = 0099h
DI = 000Dh
ES:000Dh = 0000h
ES:000Fh = 0099h <—— 99h
Адрес ячейки ES:000Fh был посчитан как содержимое DI плюс 2 = F. Число 99h из
регистра AX успешно скопировано в эту ячейку памяти.
3.7 БАЗОВО-ИНДЕКСНАЯ АДРЕСАЦИЯ.
При использовании этого способа относительный адрес образуется путем сложения
содержимых базового ( BX,BP ) и индексного ( SI,DI ) регистров. Например для
операции MOV AX,[BP+SI] мы получим:
Регистры до выполнения MOV AX,[BP+SI]
AX = 00AAh
BP = 0100h
SI = 0050h
DS:0100h = 0001h (bp)
DS:0150h = 0002h (bp+si)
После...
AX = 0002h <—— 02h
BP = 0100h
SI = 0050h
DS:0100h = 0001h
DS:0150h = 0002h
Адрес ячейки DS:0150h получен путем сложения значений регистров BP и SI, после
чего число из этой ячейки памяти был загружен в регистр AX.
3.8 БАЗОВО-ИНДЕКСНАЯ АДРЕСАЦИЯ СО СМЕЩЕНИЕМ.
Это вариант базово индексной адресации, при котором к относительному адресу
прибавляется 8- или 16-разрядное смещение. Дополнительные способы адресации
реализуются при использовании 32-разрядных адресов, когда задано специальное
поле (SIB) в коде команды. Тогда возможны конструкции типа [EAX+EBX],
[EAX+EAX], [ECX+EDX], В качестве индексного регистра можно использовать любой
регистр кроме ESP. Содержимое этого регистра умножается на масштабный
коэффициент F т.е. сдвигается влево на число разрядов 0,1,3 или 4. Значение F
зависит от размера данных. Для примера рассмотрим инструкцию MOV
EAX,[EAX+EAX].
Регистры до выполнения MOV EAX,[EAX+EAX]
EAX = 0010h
DS:0010h = 000Ah (eax)
DS:0020h = 000Bh (eax+eax)
После...
EAX = 000Bh <—— 0Bh
DS:0010h = 000Ah
DS:0020h = 000Bh
Базовый адрес берется из EAX, складывается со смещением из EAX и двойное слово
по адресу DS:0020h заносится в EAX.
3.9 ИНДЕКСНАЯ АДРЕСАЦИЯ С МАСШТАБИРОВАНИЕМ
При использовании этого способа адресации относительный адрес формируется при
сложении масштабированного индекса ( содержимого индексного регистра ) и
32-разрядного смещения. Поясним идею масштабирования индекса: содержимое
индексного регистра умножается на масштабный коэффициент, чтобы правильно
адресовать данные размером более одного байта. Для примера рассмотрим фрагмент
программы, осуществляющей работу с цепочкой двойных-слов.
Start: jmp Begin
Var dd 5 dup (0)
Begin:
mov edi,2 ; 1
mov [Var+edi*4],12345678h ; 2
Переменная Var представляет собой массив из 5 32-разрядных слов. В строке 1 мы
заносим в индексный регистр 2, имея ввиду обработку второго элемента массива,
а далее в строке 2 мы заносим во второй элемент число 1234567h. На паскале это
выглядело-бы как Y[2]:=$1234567 Если бы мы не произвели масштабирование, то
число 1234567h было-бы занесено по адресу [Y+2], а при масштабировании
реальный адрес был вычислен как [Y+2*4] т.е. [Y+8] и число попало "по адресу".
Использование масштабирования имеет огромную роль при работе с массивами слов
и двойных слов, избавляя программиста от необходимости дополнительного
индексирования переменных и работы с удвоенными и учетверенными индексами
элементов. Все это за него выполняет процессор, сокращая и размер кода и
скорость его выполнения.
3.10 БАЗОВО-ИНДЕКСНАЯ АДРЕСАЦИЯ С МАСШТАБИРОВАНИЕМ
Относительный адрес формируется сложением масштабированного индекса и базы, в
качестве которой используется содержимое одного из регистров
EAX,EBX,ECX,EDX,ESI или EDI. Приведем пример такой адресации данных:
Инструкция MOV [EAX+EDI*4],666h поместит число 666h по адресу EAX плюс
учетверенное содержимое EDI.
Регистры до выполнения MOV [EAX+EDI*4],666h
EAX = 0100h
EDI = 0002h
DS:0100h = 000Ah (eax)
DS:0104h = 000Bh
DS:0108h = 000Ch (eax+edi*4)
После...
EAX = 0100h
EDI = 0002h
DS:0100h = 000Ah (eax)
DS:0104h = 000Bh
DS:0108h = 0666h <—— 666h
Масштабирование позволило адресовать именно 2-е 32-разрядное слово, а не
записать число 666h по адресу EAX+2 т.е. 102h, который попадает по середине
двух элементов массива.
3.11 БАЗОВО-ИНДЕКСНАЯ АДРЕСАЦИЯ СО СМЕЩЕНИЕМ И МАСШТАБИРОВАНИЕМ
Этот способ адресации рассмотрен в пункте 3.6 при использовании 32-разрядной
адресации. Поэтому приведем лишь пример инструкции и опишем ее действия.
Инструкция INC [EAX+EDI*4+12345678h] увеличит на единицу число, адрес которого
вычисляется, как базовый плюс 32-разрядное смещение 12345678h и плюс
масштабированный по основанию 4 индекс, содержащийся в регистре EDI.
3.12 ОТНОСИТЕЛЬНАЯ АДРЕСАЦИЯ
Относительная адресация используется в микропроцессоре 80386 при выполнении
ряда команд управления ( условные и безусловные переходы, вызовы подпрограмм,
управление циклами и т.д. ), чтобы адресовать ячейку памяти, содержащую
следующую команду. При этом способе адрес формируется как сумма содержимого
регистра EIP(IP) ( instruction pointer - указатель инструкции ),
соответствующего текущей команде, и 8-, 16- или 32-разрядного смещения,
определяющего положение следующей команды, относительно текущей. Например
рассмотрим операцию безусловного перехода в приведенном фрагменте:
.
.
mov ax,5
jmp @1
sub ax,ax
@1: mov bx,ax
.
.
Безусловный переход будет представлен как JMP 02, т.е. на 2 байта вперед,
после инструкции. SUB AX,AX занимает в памяти слово, значит переход будет
передан на команду MOV BX,AX т.е. по адресу CS:IP+2. (Это немного упрощенный
пример внутрисегментного перехода. На самом деле при переходах менее чем на
128 байт используется короткий переход EB??90, где ?? - это размер кода
который надо пропустить + 1 байт. Дополнительный байт прибавляется за счет
кода 90h следующего за смещением. Этот код представляет собой код инструкции
NOP ( no operation ), присутствие его абсолютно бесполезно, но сложилось
исторически, и больше не исправлялось. Байт ?? - это байт со знаком, так что
переход возможен как вперед, так и назад. А вот при переходах более чем на 127
байт используется команда E9???? , описанная выше ).
4. ЗАКЛЮЧЕНИЕ. СРАВНИТЕЛЬНЫЙ АНАЛИЗ СИСТЕМ АДРЕСАЦИИ ИСПОЛЬЗУЕМЫХ В CM1700 И В
ПЭВМ НА БАЗЕ ПРОЦЕССОРА 80386.
В двух предыдущих разделах мы привели примеры и описали основные способы
адресации, используемые в машинах двух разных семейств - мини- и микроЭВМ.
Конечно это не все, что можно сказать о системах адресации для компьютеров
этих семейств, тем не менее основные способы задания адресов и адресации
операндов были рассмотрены и можно попытаться проанализировать, сравнить и
привести примеры использования тех способов адресации, которые были описаны.
Для начала, рассмотрим самые простые способы адресации, такие как регистровая,
прямая, непосредственная и короткого литерала. Про регистровую адресацию
трудно написать больше, чем уже было написано. Естественно, что этот способ
адресации поддерживается и на СМ1700 и 80386 процессором, как впрочем вообще
всеми процессорами семейства 80х86 и многими другими процессорами, которые
имеют регистровую память. Несмотря на простоту этого способа адресации, он
достаточно часто используется для манипуляции регистрами, их очистки,
модификации их содержимого. Регистровая память отличается очень большой
скоростью, и поэтому большинство вычислений, особенно несложных программисты
пытаются делать в этих регистрах. В них помещают начальные значения,
производят вычисления, модификацию и как-то используют полученные результаты.
Для всех этих действий естественным является применение именно регистрового
способа адресации. Большим подспорьем регистровому способу адресации является
режим непосредственной адресации. Конечно в основном он используется для
загрузки в регистры начальных значений, заранее известных адресов, сравнения с
константой и так далее. Но если копнуть чуть глубже, то этот способ адресации
дает еще множество удобств. Например для перехода по заранее известному адресу
представленному в виде сегмента со смещением можно использовать такой код:
push 0f000h
push 0ffffh
ret
Команда RET берет из стека значения сегмента и смещения, а потом делает
межсегментный переход. Представим себе, выполнение подобного кода без
возможности помещать на вершину стека непосредственное значение:
mov ax,0f000h
push ax
mov ax,0ffffh
push ax
ret
Как видим, выглядит это не слишком компактно, в сравнении с предыдущим
примером, и можете быть уверены, что выполняется это на несколько тактов
дольше. Это самый простой пример применения непосредственной адресации, на
самом деле ее применение гораздо шире, особенно если интенсивно используются
работа с операционной системой, где все значения, адреса и параметры
стандартизированы и в основном заранее известны. На СМ 1700 режим
непосредственной адресации реализуется программно, с использованием счетчика
инструкций, а в машинах на базе i386 он реализуется аппаратно. Трудно сказать
что лучше, однако в СМ 1700 предусмотрен еще и режим короткого литерала,
преимущества которого перед обычной непосредственной адресацией данных меньших
чем 64 беспорны. В 80386 процессоре ничего подобного не предусмотрено, хотя
может быть это лучше - не увеличивает систему команд и следовательно упрощает
структуру процессора.
Прямая адресация это тоже достаточно простой, но очень часто используемый
инструмент. Чаще всего используется для обращения к одиночным переменным,
областям данных операционных систем и т.д. Реализован и в i386 процессоре и на
СМ 1700, опять же через счетчик инструкций.
Более сложными, однако и более продуктивными являются косвенные способы
адресации. Косвенно регистровый, косвенный со смещением, индексные режимы
адресации реализованы в полной мере и на СМ 1700 и в ПЭВМ. Они дают наибольший
эффект при обработке массивов, таблиц, различного рода списков. Для сравнения
приведем таблицу аналогичных по смыслу инструкций СМ 1700 и процессора 80386.
1. Косвенно регистровый.
СМ 1700 MOVB R1,(R2)
i386 MOV [EBX],EAX
2. Смещения.
СМ 1700 MOVB W^32769(R4),R1
i386 MOV EAX,[EDX+32769]
3. Косвенный смещения.
СМ 1700 MOVW @B^8(R5),(R2)
i386 MOV ESI,[EDI+8]
MOV AX, word ptr [ESI]
MOV word ptr [EDX],AX
4. Косвенно регистровый индексный.
СМ 1700 MOVB (R1)[R2],R3
i386 MOV CX,[BP+DI]
5. Смещения индексный.
СМ 1700 MOVB B^5(R1)[R2],R3
i386 MOV EAX,[EBX+ECX+5]
В таблице приведены лишь некоторые режимы адресации, и сейчас мы поясним
почему. Если обратить внимание на пункт 3, то видно, что команда, аналогичная
косвенному режиму смещения заменена на 3 инструкции из набора команд
процессора 80386. Действительно 386-ой процессор не понимает конструкций типа
"адрес адреса", поэтому подобные манипуляции приходится делать с помощью
дополнительного регистра. Более того система адресации процессора 80386 не
допускает использования команд с обращением память-память. Это опять
заставляет использовать дополнительные регистры. Однако в системе команд i386
предусмотрены команды обработки строк. Эти команды во многих случаях позволяют
обойтись без подобных проблем. Вот эти команды:
MOVS{B,W,D} - переслать строку
STOS{B,W,D} - занести в память из {AL,AX,EAX}
LODS{B,W,D} - занести из памяти в {AL,AX,EAX}
CMPS{B,W,D} - сравнить строки
SCAS{B,W,D} - сканировать строку
Все эти команды можно использовать с префиксом повторения REP. У этого
префикса есть и условные модификации REPE, REPZ, REPNE REPNZ и другие,
прекращающие повторение по какому-то признаку до исчерпания счетчика. С
помощью первых трех команд и реализуется основная работа с памятью. Эти
инструкции можно охарактеризовать, как использующие автоувеличение или
автоуменьшение, так как они после выполнения модифицируют текущее смещение,
которое хранится в регистрах ESI(SI),EDI(DI). В тоже время MOVS реализует
адресацию "память-память". С первого взгляда этого недостаточно для того,
чтобы эффективно использовать например подобие косвенного с автоувеличением
индексного режима. Однако эти сложные инструкции легко заменяются набором
инструкций процессора 80386. Например перепишем команду MOVL @(R1)+[R3],(R2)+
для машин на базе i80386.
CLD
MOV ESI,[EAX+EBX]
MOVSD
Если положить, что EDI = R2, то результат будет тем же. Далее ESI и EDI будут
увеличены на 4 и для дальнейшей пересылки можно было бы написать
MOV CX,1000
REP MOVSB
Что привело бы к пересылке 4000 байт из DS:[ESI] в ES:[EDI]. Конечно нужна
некоторая предварительная подготовка, к примеру задание начальных адресов,
установка счетчика в ECX, задание направления (CLD/STD - прибавлять или
отнимать в ESI и(или) EDI), однако примерно такие же приготовления необходимы
и в первом случае.
Таким образом, рассматривая и сравнивая возможные способы адресации на СМ ЭВМ
и персональных ЭВМ на базе процессора i386 можно сформировать вполне
определенное представление о возможностях этих машин. Несомненно СМ 1700
является более мощной машиной, рассчитанной на решение достаточно сложных
экономических и других задач. Имея более совершенный набор возможных способов
адресации позволяет качественнее и компактнее записывать задачи
ориентированные на работу с большим количеством различной нформации, по
сравнению с возможной реализацией подобных задач на ПЭВМ.Прямая или косвенная
адресация "память-память" несомненно имеет огромные преимущества, и резко
снижает размер кода и количество дополнительных ресурсов ( регистры, лишние
такты и т.д.), используемых при подобных пересылках. Однако, несмотря на это,
перепрограммирование подобных задач для процессора 80386 вполне реально и даже
имеет смысл. Благодаря развитию элементной базы, новым архитектурным решениям,
повышению производительности внутренних и внешних запоминающих устройств общая
производительность современных ПЭВМ достигает, и часто обходит
производительность таких классических вычислительных систем, какВС на основе
СМ и ЕС ЭВМ. Поэтому, несмотря на некоторую неприспособленнось машин этого
класса для решения сложных задач, последнее время очень большой процент
подобных вычислений приходится на ПЭВМ. И конечно не последнюю роль здесь
играет их относительно небольшая стоимость, глобальное распространение и
огромное количество прикладных программ, а следовательно и программистов,
способных писать грамотное ПО для решения экономических задач.