Лекция № 4 «Способы адресации данных. Структура программы

advertisement
Системное программное обеспечение
Лекция № 4 «Способы адресации данных. Структура программы на языке Ассемблер»
Способы адресации данных
Способы адресации данных
Прямая
адресация
иногда
называется
адресацией
по
смещению, так как в команде указывается адрес смещения
переменной в памяти относительно любого базового сегмента. Если
базовый сегмент не указан, то по умолчанию используется DS.
При косвенной адресации до 80386 можно было использовать
только BX, SI, DI и BP, но потом эти ограничения были сняты и адрес
операнда разрешили считывать также и из EAX, EBX, ECX, EDX,
ESI, EDI, EBP и ESP (но не из AX, CX, DX или SP напрямую — надо
использовать
EAX,
ECX,
EDX,
ESP
соответственно
или
предварительно скопировать смещение в BX, SI, DI или BP). Как и в
случае прямой адресации, DS используется по умолчанию, но не во всех
случаях: если смещение берут из регистров ESP, EBP или BP, то в
качестве сегментного регистра используется SS.
Способы адресации данных
Различают следущие виды косвенной адресации:
• регистровая косвенная (смещение адреса хранится в одном из
указанных регистров)
• базовая (смещение адреса – сумма значений базового регистра и
смещения)
• индексная (смещение адреса – сумма значений индексного регистра
и смещения)
• базово–индексная (смещение адреса – сумма значений базового,
индексного регистра и смещения)
Как видно, способов адресации для процессоров 8086 и 80286
довольно много. Но с появлением процессора 80386 их стало
настолько больше, что глядя на рисунок, где они показаны, можно
подумать, что речь идет совсем о другом процессоре.
Структура программы на языке Ассемблер
Программа на языке Ассемблер состоит из одного или
нескольких сегментов. Сегменты программы имеют определенное
назначение: кода, данных и стека. Деление программы на сегменты
отражает сегментную организацию памяти процессоров Intel.
Каждый сегмент состоит из совокупности отдельных строк, в
терминах теории компиляции называемых предложениями языка
Ассемблер.
Предложения ассемблера бывают четырех типов:
• команды или инструкции, представляющие собой символические
аналоги машинных команд. В процессе трансляции инструкции
ассемблера
преобразуются
системы команд процессора
в
соответствующие
команды
Структура программы на языке Ассемблер
• макрокоманды — именованный блок команд языка ассемблера.
После того как макрокоманда определена в программе, ее можно
многократно вызывать в разных участках кода. При вызове
макрокоманды, в код программы будут помещены содержащиеся в
ней команды. Не следует путать вызов макропроцедуры с вызовом
обычной процедуры, поскольку в первом случае команда вызова
процедуры не используется
• директивы, являющиеся указанием транслятору ассемблера на
выполнение некоторых действий. У директив нет аналогов в
машинном представлении
• строки комментариев, содержащие любые символы, в том числе и
буквы
русского
транслятором
алфавита.
Комментарии
игнорируются
Структура программы на языке Ассемблер
Формат
синтаксической
предложения
диаграммой,
Ассемблера
отражающей
описывается
логику
работы
транслятора при разборе входных предложений программы:
Любой путь на диаграмме от входа до выхода соответствует
синтаксически правильному предложению языка.
Структура программы на языке Ассемблер
Формат директив Ассемблера описывается синтаксической
диаграммой вида:
Из
директив
Ассемблера
в
первую
очередь
следует
рассмотреть директивы сегментации программы. Физически сегмент
представляет собой область памяти, занятую командами и (или)
данными, адреса которых вычисляются относительно значения в
соответствующем сегментном регистре. Синтаксическое описание
сегмента на ассемблере:
Структура программы на языке Ассемблер
Операнды директивы SEGMENT:
• Атрибут выравнивания сегмента (тип выравнивания)
сообщает компоновщику о том, что нужно обеспечить
размещение начала сегмента на заданной границе. Это
важно, поскольку при правильном выравнивании доступ к
данным
быстрее.
в
процессорах
семейства
80х86
выполняется
Структура программы на языке Ассемблер
Допустимые значения этого атрибута следующие:
o BYTE — выравнивание не выполняется. Сегмент может
начинаться с любого адреса памяти
o WORD — сегмент начинается по адресу, кратному двум, то
есть последний (младший) значащий бит физического
адреса равен 0 (выравнивание на границу слова)
o DWORD — сегмент начинается по адресу, кратному
четырем, то есть два последних (младших) значащих бита
равны 0 (выравнивание на границу двойного слова)
o PARA — сегмент начинается по адресу, кратному 16, то
есть последняя шестнадцатеричная цифра адреса должна
быть 0h (выравнивание на границу параграфа)
Структура программы на языке Ассемблер
o PAGE — сегмент начинается по адресу, кратному 256,
то есть две последние шестнадцатеричные цифры
должны быть 00h (выравнивание на границу 256–
байтной страницы)
o MEMPAGE — сегмент начинается по адресу, кратному 4
Кбайт, то есть три последние шестнадцатеричные
цифры должны быть 000h (адрес следующей 4–Кбайтной
страницы памяти)
По умолчанию тип выравнивания имеет значение PARA.
• Атрибут комбинирования сегментов (комбинаторный тип)
сообщает
компоновщику,
как
нужно
комбинировать
сегменты различных модулей, имеющие одно и то же имя.
Структура программы на языке Ассемблер
o PRIVATE — сегмент не будет объединяться с другими
сегментами с тем же именем вне данного модуля
o PUBLIC — заставляет компоновщик соединить все сегменты с
одинаковыми именами. Новый объединенный сегмент будет
целым и непрерывным. Все адреса (смещения) объектов, а это
могут быть, в зависимости от типа сегмента, команды и
данные, будут вычисляться относительно начала этого нового
сегмента
o COMMON — располагает все сегменты с одним и тем же
именем по одному адресу. Все сегменты с данным именем
будут перекрываться и совместно использовать память.
Размер полученного в результате сегмента будет равен
размеру самого большого сегмента
Структура программы на языке Ассемблер
o AT xxxx — располагает сегмент по абсолютному адресу
параграфа.
Абсолютный
адрес
параграфа
задается
выражением xxx. Компоновщик располагает сегмент по
заданному адресу памяти (это можно использовать, например,
для доступа к видеопамяти или области ПЗУ), учитывая
атрибут комбинирования. Физически это означает, что
сегмент при загрузке в память будет расположен, начиная с
этого абсолютного адреса параграфа, но для доступа к нему в
соответствующий
сегментный
регистр
должно
быть
загружено заданное в атрибуте значение. Все метки и адреса в
определенном
таким
образом
сегменте
относительно заданного абсолютного адреса
отсчитываются
Структура программы на языке Ассемблер
o STACK — определение сегмента стека. Заставляет компоновщик
соединить все одноименные сегменты и вычислять адреса в этих
сегментах относительно регистра ss. Комбинированный тип
STACK (стек) аналогичен комбинированному типу PUBLIC, за
исключением того, что регистр ss является стандартным
сегментным регистром для сегментов стека. Регистр sp
устанавливается на конец объединенного сегмента стека. Если не
указано
ни
одного
сегмента
стека,
компоновщик
выдаст
предупреждение, что стековый сегмент не найден. Если сегмент
стека создан, а комбинированный тип STACK не используется,
программист должен явно загрузить в регистр ss адрес сегмента
(подобно тому, как это делается для регистра ds)
По умолчанию атрибут комбинирования – PRIVATE.
Структура программы на языке Ассемблер
• Атрибут класса сегмента (тип класса) — это заключенная в
кавычки
строка,
помогающая
компоновщику
определить
соответствующий порядок следования сегментов при собирании
программы
из сегментов
нескольких
модулей. Компоновщик
объединяет вместе в памяти все сегменты с одним и тем же
именем класса (имя класса, в общем случае, может быть любым, но
лучше, если оно будет отражать функциональное назначение
сегмента). Типичным примером использования имени класса
является объединение в группу всех сегментов кода программы
(обычно для этого используется класс “code”). С помощью
механизма
типизации
класса
можно
группировать
также
сегменты инициализированных и неинициализированных данных
Структура программы на языке Ассемблер
• Атрибут размера сегмента. Для процессоров 80386 и выше
сегменты могут быть 16 или 32–разрядными. Это влияет на
размер сегмента и порядок формирования физического адреса
внутри него. Атрибут может принимать следующие значения:
o USE16 — это означает, что сегмент допускает 16–разрядную
адресацию. При формировании физического адреса может
использоваться
только
16–разрядное
смещение.
Соответственно, такой сегмент может содержать до 64
Кбайт кода или данных
o USE32 — сегмент будет 32–разрядным. При формирования
физического адреса может использоваться 32–разрядное
смещение. Поэтому такой сегмент может содержать до 4
Гбайт кода или данных
Структура программы на языке Ассемблер
Директива
ASSUME,
имеющая
формат
сообщает
транслятору о том, какой сегмент к какому сегментному регистру
привязан.
Структура программы на языке Ассемблер
Если в качестве операнда используется только ключевое
слово nothing, то предшествующие назначения сегментных
регистров аннулируются, причем сразу для всех шести
сегментных регистров. Но ключевое слово nothing можно
использовать вместо аргумента имя сегмента; в этом случае
будет выборочно разрываться связь между сегментом с именем
имя сегмента и соответствующим сегментным регистром.
Для описания простых типов данных в программе
используются
специальные
директивы
резервирования
и
инициализации данных, которые, по сути, являются указаниями
транслятору на выделение определенного объема памяти:
Структура программы на языке Ассемблер
Здесь использованы следующие обозначения:
• ? показывает, что содержимое поля не определено, то есть
при задании директивы с таким значением выражения
содержимое
изменяться
выделенного
не
участка
будет.
неинициализированная переменная
физической
Фактически,
памяти
создается
Структура программы на языке Ассемблер
• значение инициализации — значение элемента данных,
которое
будет
занесено
в
память
после
загрузки
программы. Фактически, создается инициализированная
переменная,
в
качестве
которой
могут
выступать
константы, строки символов, константные и адресные
выражения в зависимости от типа данных
• имя — некоторое символическое имя метки или ячейки
памяти в сегменте данных, используемое в программе
Директивы резервирования и инициализации данных:
• db
—
резервирование памяти для данных в 1 байт
• dw
—
резервирование памяти для данных в 2 байта
• dd
—
резервирование памяти для данных в 4 байта
Структура программы на языке Ассемблер
• df, dp —
резервирование памяти для данных размером 6
байт (адрес в формате 16–битный селектор: 32–битное
смещение)
• dq
—
резервирование памяти для данных в 8 байт;
• dt
—
резервирование памяти для данных размером 10
байт (80–битные типы данных, используемые сопроцессором).
Очень важно уяснить себе порядок размещения данных в
памяти. Он напрямую связан с логикой работы микропроцессора с
данными. Микропроцессоры Intel требуют следования данных в
памяти по принципу: младший байт по младшему адресу.
Формат команд и макрокоманд Ассемблера описывается
синтаксической диаграммой вида:
Структура программы на языке Ассемблер
Макрокоманду можно определить в любом месте
исходного кода программы, воспользовавшись директивами
MACRO
и
ENDM.
Синтаксис
макроопределения
следующий:
Имя MACRO Параметр–1, Параметр–2. . .
Список–команд
ENDM
Структура программы на языке Ассемблер
Для вызова макрокоманды нужно просто
поместить ее имя в исходный код программы и при
необходимости указать передаваемые ей значения:
Имя Значение–1, Значение–2, ...
Имя должно быть определено в исходном коде
программы до ее вызова. Каждое значение является
обычной
текстовой
подставляется
вместо
параметра макрокоманды.
строкой,
которое
соответствующего
Download