Добавил:
kostikboritski@gmail.com Выполнение курсовых, РГР технических предметов Механического факультета. Так же чертежи по инженерной графике для МФ, УПП. Писать на почту. Дипломы по кафедре Вагоны Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

литература / Пухальский Проектирование микропроцессорных систем 2001

.pdf
Скачиваний:
334
Добавлен:
12.11.2017
Размер:
21.12 Mб
Скачать

4.4. Директивы ассемблера

415

1. Директивы сегментирования программы

Программа на языке ассемблера состоит из последовательности программных сегментов (сегменты стека, данных и кода), заканчивающейся директивой END. Начало и конец любого сегмента задаются директивами SEGMENT и ENDS. Программный сегмент представляет собой последовательность инструкций (команд МП) и/или полей данных, адресуемых относительно одного сегментного регистра CS, DS, SS или ES, присваиваемого сегменту директивой

ASSUME.

Директивами PROC и ENDP в сегментах кода выделяются процедуры, позволяющие ис­ пользовать часть программного кода многократно без его дублирования в разных частях про­ граммы^ Процедуры являются основным средством разделения кода программы на модули, которые легко по отдельности разрабатывать, тестировать и документировать.

Сегменты могут объединяться в группу при помощи директивы GROUP. Директивы ORG

иEVEN позволяют управлять адресами размещения команд МП.

Директивы SEGM ENT и ENDS. Директива SEGMENT (Segment Definition — определе­

ние сегмента) имеет формат:

seg_name SEGMENT [align] [combine] [‘c/ass’]

(параметры, заключенные в квадратные скобки, являются необязательными). Имя сегмента seg_name обязательно должно быть указано — назначается любое уникальное имя, не совпа­ дающее с зарезервированными. Сегмент — это набор команд МП и/или данных, адреса кото­ рых вычисляются относительно одного и того же сегментного регистра CS, DS, SS или ES.

Директива ENDS (End Segment — конец сегмента) имеет формат:

seg_name ENDS,

где seg_name — то же самое имя, что и в директиве SEGMENT (см. табл. 4.17: s_seg, d_seg и c_seg — имена сегментов стека, данных и кода). Таким образом, директивы SEGMENT и ENDS задают начало и конец сегмента, адресуемого относительно одного из сегментных регистров

SS, DS, ES

и CS. Между этими директивами располагаются другие директивы ассемблера,

в частности,

директивы определения данных для сегмента данных и директивы определения

процедур для сегмента кода. Исходный модуль может иметь несколько директив SEGMENT с одним и тем же именем, определяющих некоторые части целого сегмента. Все эти части компонуются в один сегмент. Параметры таких директив SEGMENT не должны противоречить друг другу.

Директива SEGMENT может содержать три типа необязательных параметров: align (вы­ равнивание), combine (объединение, или комбинирование) и ‘class’ (класс, или категория). Если они присутствуют, то должны описываться в указанном порядке, хотя любые из них могут и отсутствовать.

Параметр align сообщает компоновщику границу адреса относительно предыдущего сег­ мента, начиная с которого сегмент будет загружаться в память. Этот параметр может иметь значения:

BYTE — выравнивание не выполняется (сегмент располагается, начиная со следующего байта);

WORD — начало сегмента выравнивается на границу следующего слова;

DWORD — начало сегмента выравнивается на границу следующего двойного слова; PARA — начало сегмента выравнивается на границу следующего параграфа (16 байт); PAGE — начало сегмента выравнивается на границу следующей страницы (256 байт);

416 Глава 4. Микропроцессоры 8086/8088 и сопроцессор 8087

MEMPAGE — начало сегмента выравнивается на границу следующей страницы памяти

(4096 байт).

Значение PARA принимается по умолчанию, если параметр align не задан. Действитель­ ный начальный адрес сегмента не вычисляется до загрузки программы в компьютер (тип вы­ равнивания только накладывает на него ограничение).

Параметр combine сообщает компоновщику способ объединения одноименных сегментов, находящихся в нескольких объектных модулях. Этот параметр может иметь значения:

PRIVATE — сегмент не будет объединяться с сегментами, находящимися в других моду­ лях и имеющих такое же имя;

PUBLIC — все сегменты с одинаковыми именами и классами, находящиеся в разных мо­ дулях, объединяются в один непрерывный сегмент. Команды или данные нового сегмента бу­ дут адресоваться относительно одного сегментного регистра, а все смещения будут вычислять­ ся относительно начала этого сегмента;

STACK1— все сегменты с одинаковыми именами и классами объединяются в один непре­ рывный сегмент. Этот тип комбинирования отличается от типа PUBLIC лишь тем, что адреса­ ция в новом сегменте будет производиться относительно сегментного регистра SS (регистр SP при этом устанавливается на конец сегмента). Такой тип комбинирования обычно имеют сег­ менты стека. Параметр STACK автоматически обеспечивает инициализацию регистров SS и SP, и пользователю не нужно включать в свою программу команды для установки этих регистров. Если не указано ни одного сегмента типа STACK, то компоновщик выдаст предупреждение, что сегмент стека не найден (Warning: No stack). Если параметр STACK не был задан, пользова­ тель должен сам программным способом загрузить в регистры SS и SP необходимые адреса;

COMMON — для всех сегментов с одинаковыми именами и классами компоновщик уста­ навливает общий базовый адрес (адреса данных и команд в каждом из таких сегментов являют­ ся смещениями по отношению к общему стартовому адресу). Сегменты будут загружаться в память, начиная с одного адреса (таким способом можно создавать оверлейные программы). Размер области загрузки определяется самым большим сегментом;

AT address — задает абсолютный стартовый адрес сегмента. Адреса всех меток и пере­ менных сегмента вычисляются относительно фиксированного параметра address (определение абсолютного сегмента). Параметр address является 16-разрядным адресом начала параграфа для сегмента. Адрес может быть представлен любым допустимым выражением, не содержащим ссылок вперед. Сегмент с этим типом комбинирования обычно не содержит программного кода или инициализируемых данных, а включает в себя только адресные значения, фиксированные для компьютера (видеобуфер, таблица векторов прерывания, ROM BIOS и др.). Тип комбиниро­ вания АТ нельзя использовать для загрузки кодов или данных в определяемую им область па­ мяти.

Значение PRIVATE принимается по умолчанию, если параметр combine не задан. Параметр ‘class’ сегмента используется компоновщиком для задания порядка следования

сегментов в памяти. Сегменты одного класса загружаются в память один после другого до того, как начнут загружаться сегменты другого класса. В качестве класса сегмента может быть ука­ зано любое допустимое имя, заключенное в апострофы. Поскольку класс сегмента рассматри­ вается как идентификатор, то в программе он не может быть определен еще где-либо. Наиболее часто для сегментов стека и кода используются идентификаторы ‘Stack’ и ‘Code’.

Если параметр ‘class' не указан, то компоновщик копирует сегменты в загрузочный мо­ дуль в той последовательности, в которой они расположены в объектном модуле. Эта последо­ вательность сохраняется до тех пор, пока компоновщик не обнаружит два или более сегмента

4.4. Директивы ассемблера

417

одного класса, после чего компоновщик начинает объединение сегментов. Сегменты одного класса копируются в последовательные блоки загрузочного модуля.

Все сегменты имеют класс — сегменты, для которых параметр ‘class’ не указан, считаются принадлежащими к классу с пустым именем и копируются в последовательные блоки памяти вместе с такими же сегментами. Число сегментов, принадлежащих к одному классу, не ограни­ чено, но их суммарный объем не должен превышать 64 Кбайт.

Д иректива ASSUME. Эта директива используется для привязки сегментов к сегментным регистрам, т. е. для каждого сегмента задает сегментный регистр, который будет использовать­ ся по умолчанию для вычисления исполнительных адресов всех меток и переменных, опреде­ ленных под заданным именем сегмента. Директива ASSUME (присваивать) имеет два формата:

ASSUME seg_reg: seg_name [,

...] или ASSUME NOTHING,

где segjreg — любой сегментный регистр из CS, DS, ES и SS; seg_name — имя сегмента, пред­ варительно определенное директивой SEGMENT (см. табл. 4.17), имя группы, определенное директивой GROUP, или ключевое слово NOTHING (ничего). Если используется ключевое слово NOTHING, то предшествующий выбор сегмента аннулируется. При использовании в ис­ ходном модуле второго формата директивы ASSUME аннулируется выбор сегментов для всех четырех сегментных регистров.

Д иректива GROUP. Эта директива используется для сбора сегментов с разными имена­ ми, но одного типа (код, данные, стек), под одно имя. Директива ASSUME имеет формат:

grjname GROUP seg__name [, ...] ... [, ...],

где gr_name — имя группы, seg_name — имя сегмента, заранее определенное директивой SEGMENT. Объединение нескольких сегментов в одну группу с заданным именем позволяет адресовать все метки и переменные в этих сегментах относительно начала группы, а не начала содержащего их сегмента.

Директива GROUP не влияет на порядок загрузки сегментов, который зависит от классов сегментов и их расположения в объектном файле. Сегменты одной группы не обязательно бу­ дут занимать непрерывную область памяти. Они могут быть перемешаны с сегментами, не принадлежащими этой группе. Однако расстояние между первым и последним элементами группы не должно превышать 64 Кбайт. Если сегменты группы расположены последовательно, группа может занимать до 64 Кбайт памяти.

Имя группы можно использовать в директиве ASSUME и в качестве префикса замены сегмента, если предварительно имя группы присвоено сегментному регистру директивой ASSUME. В исходном модуле имя группы может быть употреблено только с одной директивой

GROUP.

Д ирективы ORG и EVEN. Для определения относительного адреса программных эле­ ментов в сегментах данных и кода ассемблер использует счетчик адресов. Текущее значение адреса обозначается символом $ (можно использовать в директивах). Начальное значение счет­ чика адресов равно 0000/;. Все программные элементы (данные и команды МП) располагаются по смежным адресам в том порядке, в котором они следуют в программе. В итоге сегмент представляет собой непрерывную область памяти, занятую данными и/или командами МП. Ди­ ректива ORG (Origin — начало) позволяет изменять значение счетчика адресов и соответствен­ но адрес следующего определяемого элемента. Директива ORG имеет следующий формат:

ORG expression,

где expression — выражение, значение которого присваивается счетчику адресов (указателю позиции). Адреса следующих за директивой ORG инструкций МП и/или данных будут начи­

27 Г. И. Пухальский