╩юьрэф√ ьшъЁюяЁюЎхёёюЁэющ Єхїэшъш

         

ASSUME CS:CODSEG, DS:DATSEG


При этом организуется новый счетчик ячеек, в который загружается нулевое смещение.

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

Текущее значение счетчика ячеек может быть изменено программистом с помощью  директивы ORG (начало), имеющий формат

                                   ORG    <выражение>

При выполнении директивы ORG вычисляется значение выражения, а результат загружается в счетчик ячеек. Вычисление выражения производится по модулю 64 К.

Директива определения имен EQU.

            Директива EQU позволяет программисту определять символические имена для часто используемых выражений и имеет формат:

                                   Имя                 EQU                <выражение>

Поле <выражение> может определять:

            -константы;

            -адреса;

            -регистры;

            -мнемокоды команды.



            В поле "имя" находится имя, которое программист использует для представления выражения. Определяемые с помощью директивы EQU имена не разрешается переопределять. т.е. имя может появиться только в одной директиве EQU. Например:

                        CR                   EQU    0DH                ; численная константа

                        ADR    EQU    AR [SI]+3       ;адресное выражение

                        COUNТ          EQU    CX                  ; регистр

            Замечание!

Директива PURGE ( удалить, освободить) удалить имена из таблицы имен: После этого это имя можно определить заново.

Директивы процедур PROC и ENDР.

           

Директива PROC (procedure) отмечает точку входа процедуры, а директива ENDP - окончание процедуры. Формат директив

                                   Имя     PROC <тип> ;NEAR, по умолчанию, или FAR -

                                               .

                                               тело процедуры

                                               .

                                               .



                                   Имя     ENDP

            Имя является меткой, указывающей точку входа процедуры. Типом процедуры является NEAR или FAR (по умолчанию принимается тип NEAR). Ассемблер использует тип процедуры для определения того, какую команду CALL генерировать при вызове процедуры. Для процедур типа NEAR ассемблер генерирует команду внутрисегментного вызова. При обращении в процедуре в стеке запоминается , а затем восстанавливается только содержимое счетчика команд, т.е. для процедур типа FAR ассемблер генерирует длинную команду межсегментного вызова, которая содержит базу и смещение точки входа. При обращении к этой процедуре в стеке запоминается, а затем восстанавливается содержимое регистров CS и IP.

            Процедуры на языке ассемблера не имеют ограниченной области действия, т.е. из любого места программы можно обращаться к переменным и меткам внутри процедуры (т.е. пары директив PROC/ENDP ).

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

            Входными параметрами могут быть численные значения и адреса. Приведем два способа передачи параметров процедурам. В одном способе значения параметров размещаются в регистрах МП перед обращением к процедуре. В другом способе передача параметров процедурам организуется через стек с помощью регистра ВР, для которого сегментным является регистр SS.

            В языке ассемблера МП I8086 рекомендуется придерживаться следующего соглашения о возвращаемом процедурой значением выходного параметра.

                        -значение переменной типа WORD возвращается в аккумуляторе АХ;

                        -значение переменной типа BYTE возвращается в аккумуляторе AL;

                        -короткий указатель (смещение) возвращается в регистре BX;

                        -длинный указатель (база:смещение) возвращается в регистрах ES:BX.



Директива LABEL

            Директива LABEL выполняет несколько функций, например, обеспечивает несколько точек входа в процедурах или может создавать имена для любых ячеек памяти независимо от их содержимого и предполагаемого использования . Она содержит информацию о типе определяемого имени, а тип однозначно указывает допустимое употребление имени. Формат директивы:

                                   Имя     LABEL <тип>

            В качестве типа фигурирует одно из пяти ключевых слов: BYTE, WORD, DWORD, NEAR, FAR. Первые три типа указывают на то, что имя представляет собой переменную. Имена переменных допустимы во всех команда, оперирующих данными, но их нельзя употреблять в командах передачи управления. Имя с типом NEAR или FAR .является меткой, которая может быть операндом в командах передачи управления, но недопустима в командах, оперирующих данными. Например:

           BUF    LABEL            WORD

                                                                                  DW     1234H

Этот фрагмент программы аналогичен директиве:

BUF    DW     1234H

Директива

NED   LABEL            NEAR

определяет имя NED как метку.

            Директива LABEL удобна для определения значения указателя стека (т.е. вершины стека), например,

                        STACK_SEG             SEGMENT     WОRD            STACK

                                                                                   DW                 64 DUP(?)                   ; выделение размера стека

                        VSTK                                     LABEL                       WORD                       ;вершина стека

                        STACK_SEG             ENDS

            Директива DW резервирует 64 слова памяти без их инициализации. Директива LABEL присваивает имя VSTK слову, находящемуся после 64 слов от начала сегмента STACK_SEG. Смещение VSTK от начала сегмента STACK_SEG представляет собой то значение , которое будет содержать указатель стека SP когда стек пустой.



Директива связи модулей и сегментов.

Директивы связи модулей.

При структурном программировании сложная программа разделяется на несколько сравнительно автономных блоков (модулей). Модульная программа состоит или из нескольких исходных модулей, допускающих ассемблирование, независимо друг о друга, или может содержать несколько процедур. При модульном программировании возникают проблемы объединения (связи, связывания, редактирования связей, компоновки) отдельных модулей в единую программу. Для этого необходимы соответствующие директивы ассемблера и специальная программа, называемая редактором связей или компоновщиком.

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



С помощью межмодульных обращений модули объединяются в единую программу.

            При ассемблировании каждого исходного модуля порождается объектный модуль (объектный файл), содержащий служебную информацию о межмодульных обращениях. Редактор связей использует эту информацию для объединения отдельных объектных файлов в единый объектный файл, в котором учтены все межмодульные обращения. Рассмотрение директив связей модулей и сегментов начнем с директив PUBLIC и EXTRN

Директивы PUBLIC и EXTRN .

Директива PUBLIC объявляет имя, определенное в данном модуле, глобальным, т.е. доступным для обращений из других модулей. Директива EXTRN, сообщает, что используемое в данном модуле имя определено в другом месте, т.е. является для данного модуля внешним. Директивы PUBLIC и EXTRN имеют формат:

                                                PUBLIC          Имя, [Имя]

EXTRN .        Имя:тип,<Имя :тип>

            Имя в обеих директивах может быть именем переменной, метки или константы, ,определенной директивой = . Типом для переменной может быть BYTE, WORD, DWORD.

Типом для метки может быть NEAR, FAR, а для константы -ABS (абсолютное значение)



Каждое имя, определяемое в данном модуле, может быть указано в директиве PUBLIC только один раз. Рекомендуется директивы PUBLIC и EXTRN сгруппировать в начале модуля.

            Тип, фигурирующий в директиве EXTRN, должен совпадать с типом имени , определенным в другом модуле.

            Примеры:

                                   PUBLUC                    NED, MUR, SVAL

                                   EXTRN                       DAD:BYTE, IVN:FAR, KRN:ABS

            Если ассемблер встречает обращение к внешнему имени, он в команде резервирует необходимое место (с учетом типа имени), а в объектном файле делается отметка об этом. При объединении нескольких объектных файлов редактор связей просматривает такие отметки и, используя доступную ему информацию о глобальных именах, подставляет необходимые адреса или значения.

Директива END.

            Каждый модуль должен заканчиваться этой директивой, для указания транслятору, что текст данного модуля закончен.

Директива END  имеет формат

                                               END [<пусковой адрес>]

В каждом исходном модуле может быть только одна директива END в последней строке модуля. Пусковым адресом является метка той команды, с которой должно начаться выполнение программы. При объединении нескольких модулей только в одном из модулей (главном) должен быть указан пусковой адрес.

Директивы объединения логических элементов.

            При объединении модулей в одну программу возникает задача объединения логических сегментов, из которых состоит каждый модуль. Если эту задачу не решать, то при передаче управления одного модуля к другому необходимо изменять содержимое сегментного регистра CS, а при обращении к данным - сегментного регистра DS. Возникают сложности и при организации стека при объединении модулей.

            Поэтому, если объединенный размер сегментов кода объединенных модулей размером меньше 64 Кбайт, то сегменты кодов модулей лучше объединять так, чтобы к содержащимся в них командам можно было обращаться при одном и том же содержимом регистра CS.



            Аналогично следует объединять сегменты данных и сегменты стеков.

            Необходимая информация о способах объединения логических сегментов объединяемых модулей содержится в директивах SEGMENT в виде списка атрибутов. Полный формат директивы SEGMENT  имеет вид:

   Имя  SEGMENT     [<тип выравнивания>]        [<тип объединения>]           [<'имя класса'>]

При этом объединяемые сегменты должны иметь одинаковые имена. Каждое из указанных полей операндов директивы является необязательным, но если они есть, то они должны следовать в указанном порядке.

Рассмотрим более подробно атрибут типа объединения .

Тип объединения.

Этот атрибут показывает, каким образом данный логический сегмент должен объединяться с другим логическим сегментом имеющим такое же имя. Если для сегмента этот атрибут не определен, то сегмент считается необъединяемым, даже с сегментами, имеющими такое же имя. Тип объединения в случае необходимости нужно указывать в первом определении сегмент. В последующих директивах SEGMENT для сегментов с данным именем этот атрибут можно опускать. Могут использоваться следующие типы объединения : PUBLIC, STACK, AT, COMMON, MEMORY.

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



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



Тип объединения AT с конструкцией

 AT <выражение>

позволяет программисту задать начальный адрес логического сегмента т.е. фиксировать сегмент в нужной области памяти. Значение выражения задает номер параграфа памяти, т.е. это значение загружается в соответствующий сегментный регистр. Например:



ааааааааааа START: ааааааааа MOVааааааааааааа AX, DATSEG

аааааааааааааааааааааа MOVааааааааааааа DS, AX

аааааааааааааааааааааааааааааааааааааааааааааааааааааааааа -

аааааааааааааааааааааааааааааааааа -ааааааааа ааааааааааа ъюьрэф√ ш фшЁхъЄшт√

аааааааааааааааааааааааааааааааааааааааааааааааааааааааааа -

CODSEGаааааааааааааааааа ENDS

─шЁхъЄштр ASSUME эх чруЁєцрхЄ ёхуьхэЄэ√х рфЁхёр т ёхуьхэЄэ√х ЁхушёЄЁ√. ╟руЁєчър ёхуьхэЄэ√ї ЁхушёЄЁют, ъЁюьх ЁхушёЄЁр CS, яЁюшчтюфшЄё   тэ√ьш яхЁхфрўрьш, юс√ўэю ъюьрэфющ MOV. ╥ръ. ъръ ъюьрэфр MOV эх ьюцхЄ яхЁхфртрЄ№ эхяюёЁхфёЄтхээ√щ юяхЁрэф т ёхуьхэЄэ√щ ЁхушёЄЁ, яю¤Єюьє фы  ърцфюую ЁхушёЄЁр ЄЁхсєхЄё  фтх ъюьрэф√. ╚ь  DATSEG  ты хЄё  шьхэхь ёхуьхэЄр (яюёЄю ээ√ь чэрўхэшхь), р эх яхЁхьхээющ, яю¤Єюьє рёёхьсыхЁ ЄЁрэёышЁєхЄ яхЁтє■ ъюьрэфє MOV т ъюьрэфє, є ъюЄюЁющ юяхЁрэф -а шёЄюўэшъ  ты хЄё  эхяюёЁхфёЄтхээ√ь чэрўхэшхь (ёхуьхэЄэ√ь рфЁхёюь).

╧юёъюы№ъє Ёрчьх∙хэшх ёхуьхэЄют т ярь Єш юёє∙хёЄты хЄ ЁхфръЄюЁ ёт чхщ, Єю юяхЁрэф - шёЄюўэшъ ЇръЄшўхёъш ЇюЁьшЁєхЄ ЁхфръЄюЁ ёт чхщ. ╬фшэ ш ЄюЄ цх ёхуьхэЄ ьюцэю эрчэрўрЄ№ эхёъюы№ъшьш ёхуьхэЄэ√ь ЁхушёЄЁрь .╧ЁшьхЁ :

ааааааааааа ASSUMEааааааа CS:CODE, DS:CODE

╥юуфр чруЁєчър ёхуьхэЄэюую ЁхушёЄЁр DS юёє∙хёЄты хЄё  ъюьрэфрьш:

аааааааааааааааааааааа MOVаа AX, CS

аааааааааааааааааааааа MOVаа DS, AX

╤хуьхэЄэ√щ ЁхушёЄЁ CS юс√ўэю чруЁєцрхЄё  ъюьрэфющ ьхцёхуьхэЄэюую яхЁхїюфр яЁш шэшЎшшЁютрэшш ёхуьхэЄэюую ъюфр. ┼ёыш фшЁхъЄштр ASSUME юЄёєЄёЄтєхЄ , Єю тю тёхї юсЁр∙хэш ї ъ яхЁхьхээющ т ярь Єш эхюсїюфшью  тэю єърч√трЄ№ ёхуьхэЄэ√щ ЁхушёЄЁ, ёюфхЁцр∙шщ срчє фы  ъюэъЁхЄэюую юсЁр∙хэш  ъ ярь Єш.

─шЁхъЄштр ORG.

 

╬ёэютэющ тэєЄЁхээхщ яхЁхьхээющ рёёхьсыхЁр  ты хЄё  ёўхЄўшъ  ўххъ (рфЁхёют), ъюЄюЁ√щ яЁш рёёхьсышЁютрэшш т√яюыэ хЄ ЇєэъЎш■, рэрыюушўэє■ ЇєэъЎшш яЁюуЁрььэюую ёўхЄўшър (ёўхЄўшър ъюьрэф) яЁш т√яюыэхэшш яЁюуЁрьь√.

╤ўхЄўшъ  ўххъ ёююс∙рхЄ рёёхьсыхЁє рфЁхё ёыхфє■∙хщ  ўхщъш ярь Єш (Єюўэхх ёьх∙хэшх т ёхуьхэЄх), т ъюЄюЁє■ сєфхЄ яюьх∙хэ ёыхфє■∙шщ срщЄ ъюьрэф√ шыш фрээ√ї.

╧хЁтюх яю тыхэшх фшЁхъЄшт√ SEGMENT юяЁхфхы хЄ эрўрыю ёхуьхэЄр ё чрфрээ√ь шьхэхь.

╤юфхЁцрэшх Ёрчфхыр