Меню сайта

Урок 94. EXTRN и PUBLIC

Редактор связей не может, однако,выполнить все, о чем говорилось
— — — выше, самостоятельно. — Ассемблер должен получить от программиста
— — — информацию о подпрограммах, относящихся кдругому программному
— — — модулю. -Это ввполняется с помощью оператора PUBLIC, извещающего
— — — ассемблер о том, что данное символическоеимя доступно другим
— — — программам. — Кроме того, программист указывает ассмеблеру, какие из
— — — символических имен является внешними дляданного программного
— — — модуля. -В языке ассемблера это реализуется оператором EXTRN,
— — — который объявляет соответствующее имявнешним для текущего
— — — ассемблирования, чтобы оно могло бытьправильно обработано.
— — — Ассемблер помечает данную команду такимобразом, чтобы редактор
— — — связей мог впоследствии найти ее ивставить туда правильное
— — — значение адреса.

— — — — — Оператор EXTRN выполняет две фуекции.Во-первых, он сообщает
— — — ассемблеру, что указанное символическоеимя является внешним для
— — — текущего ассемблирования. Конечно, на этомэтапе ассемблер мог бы
— — — считать, что любое имя, неидентифицированное им в процессе
— — — ассемблирования, является внешним. Однако,если когда-нибудь вы
— — — ошиблись в указании имен, то ассемблеррешит, что имеется в виду
— — — внешнее имя, и не выдает сообщения обошибке. Это отложит индикацию
— — — ошибки до этапа редактирования связей. Длябольшинства
— — — программистов это слишком поздно,особенно, если речь идет о чем-то
— — — простом, вроде описки. Таким образом,ассемблер индицирует ошибку в
— — — случае любого не определенного имсимволического имени.

— — — — — Вторая функция оператора EXTRN состоит втом, что он указывает
— — — ассемблеру тип соответствующегосимволического имени. Так как
— — — ассемблирование является очень формальнойпроцедурой, то ассемблер
— — — должен знать, что представляет из себякаждый символ. Это позволяет
— — — ему генерировать правильные команды. Вслучае данных оператор EXTRN
— — — может указывать на байт, двойное слово илидругой типовой элемент.
— — — Тип имени подпрограммы или другойпрограммной метки может быть либо
— — — NEAR, либо FAR, в зависимости от того, вкаком сегменте она
— — — находится. От программиста требуетсяуказать в операторе EXTRN тип
— — — символического имени. Так как кроме тогоассемблером осуществляется
— — — посегментная адресация программы, тооператор EXTERN указывает на
— — — сегмент, в котором появляется данныйидентификатор. Это не входит в
— — — синтаксис оператора EXTRN, а определяетсяместоположением этого
— — — оператора в программе. Ассемблер считает,что внешнее имя относится
— — — к тому же сегменту, в котором появляетсяоператор EXTERN для этого
— — — символического имени.

— — — — — На Фиг. 5.13 приведен пример ассемблернойпрограммы,
— — — иллюстрирующей использование оператораEXTRN. Здесь имеются два
— — — имени, являющиеся внешними для даннойпрограммы. OUTPUT_CHARACTER
— — — обозначает однобайтовую переменную.Соответствующий этой переменной
— — — атрибут «:BYTE» указываетсяпосле имени переменной. Указатель NEAR
— — — программной метки OUTPUT_ROUTINE говорит отом, что она находится в
— — — том же сегменте. Хотя приведенная на Фиг.5.13 прогграмма содержит
— — — ссылки на эти символические имена, притрансляции ассемблер знает,
— — — как ему сегментировать правильные команды.Если бы оператор EXTRN
— — — отсутствовал в программе, то в этом случаеассемблер
— — — инициализировал бы ошибки. Изассемблерного листинга видно, что
— — — после поля адреса в командах, ссылающихсяна внешние имена, стоит
— — — символ E.

— — — — — — — — — -icrosoft (R) Macro Assembler Version 5.00 — — — — — — — — — — — -4/2/89 — 16:06:36
— — — — — — — — — -Фиг. 5.13 Основная программа — — — — — — — — — — — — — — — — — — — — Page — — — — — — — 1-1


— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — PAGE — — -,132
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — TITLE — -Фиг. 5.13
Основная программа

— — — — — — — — — — -0000 — — — — — — — — — — — — — — — — — STACK — -SEGMENT STACK
— — — — — — — — — — -0000 — 0040[ — — — — — — — — — — — — — — — — — — — — — — DW — — — — — 64 DUP (?) — — — — — — — — — — Резервирование места для стека
— — — — — — — — — — — — — — — — — -????
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — ]

— — — — — — — — — — -0080 — — — — — — — — — — — — — — — — — STACK — -ENDS

— — — — — — — — — — -0000 — — — — — — — — — — — — — — — — — CODE — — -SEGMENT PUBLIC

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — EXTRN — -OUTPUT_ROUTINE:NEAR, OUTPUT_CHARACTER:BYTE

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — ASSUME -CS:CODE

— — — — — — — — — — -0000 — — — — — — — — — — — — — — — — — START — -PROC — — — FAR

— — — — — — — — — — -0000 — 1E — — — — — — — — — — — — — — — — — — -PUSH — — — DS — — — — — — — — — — — — — Сегмент адреса возврата
— — — — — — — — — — -0001 — B8 0000 — — — — — — — — — — — — — — — — — — — — MOV — — — — AX, 0
— — — — — — — — — — -0004 — 50 — — — — — — — — — — — — — — — — — — -PUSH — — — AX — — — — — — — — — — — — — Смещение адреса возврата
— — — — — — — — — — -0005 — FC — — — — — — — — — — — — — — — — — — -CLD — — — — — — — — — — — — — — — — — — — — Установка направления
— — — — — — — — — — -0006 — 8C C8 — — — — — — — — — — — — — — — — — — — — — — MOV — — — — AX, CS — — — — — — — — — — — — — — Установка сегментного регистра
— — — — — — — — — — -0008 — 8E D8 — — — — — — — — — — — — — — — — — — — — — — MOV — — — — DS, AX
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — ASSUME -DS:CODE — — — — — — — — — — — — — — Индикация состояния регистра
— — — — — — — — — — -000A — 8D 36 001D R — — — — — — — — — — — — — — -LEA — — — — SI, MESSAGE — — — — — — — — — Адрес строки сообщения
— — — — — — — — — — -000E — — — — — — — — — — — — — — — — — CLOOP:
— — — — — — — — — — -000E — AC — — — — — — — — — — — — — — — — — — -LODSB — — — — — — — — — — — — — — — — — — Выборка следующего байта сообщения
— — — — — — — — — — -000F — A2 0000 E — — — — — — — — — — — — — — — — — — MOV — — — -OUTPUT_CHARACTER, AL — — — -Сохранение в памяти символа
— — — — — — — — — — -0012 — E8 0000 E — — — — — — — — — — — — — — — — — — CALL — — — OUTPUT_ROUTINE — — — — — — -Вывод символа
— — — — — — — — — — -0015 — 80 3E 0000 E 0A — — — — — — — — — — — -CMP — — — — OUTPUT_CHARACTER, 10 — — — — Проверка на символ конца сообщения
— — — — — — — — — — -001A — 75 F2 — — — — — — — — — — — — — — — — — — — — — — JNE — — — — CLOOP — — — — — — — — — — — — — — — Обработка следующего символа

— — — — — — — — — — -001C — CB — — — — — — — — — — — — — — — — — — -RET — — — — — — — — — — — — — — — — — — — — Возврат в ДОС

— — — — — — — — — — -001D — 9D E2 A0 20 AF E0 AE — — — — MESSAGE DB — — — — — ‘Эта программа — тест’, 13, 10
— — — — — — — — — — — — — — -A3 E0 A0 AC AC A0 20
— — — — — — — — — — — — — — -2D 20 E2 A5 E1 E2 0D
— — — — — — — — — — — — — — -0A
— — — — — — — — — — -0033 — — — — — — — — — — — — — — — — — START — -ENDP
— — — — — — — — — — -0033 — — — — — — — — — — — — — — — — — CODE — — -ENDS
— — — — — — — — — — — — — — — — — -&n
bsp- — — — — — — — — — — — — — — — — — — — — — END — — — -START

— — — — — — — — — — — Фиг. 5.13 Главная процедура
— — — — — — — — — -Microsoft (R) Macro Assembler Version 5.00 — — — — — — — — — — — — 1/1/80 04:02:28
— — — — — — — — — -Фиг. 5.14 Подпрограмма вывода — — — — — — — — — — — — — — — — — — — Page — — — — — — — 1-1


— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — PAGE — — -,132
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — TITLE — -Фиг. 5.14 Подпрограмма вывода

— — — — — — — — — — -0000 — — — — — — — — — — — — — — — — — CODE — — -SEGMENT PUBLIC
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — ASSUME -CS:CODE,DS:CODE — — — — — — Это должно быть так при вызове

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — PUBLIC -OUTPUT_CHARACTER, OUTPUT_ROUTINE

— — — — — — — — — — -0000 — ?? — — — — — — — — — — — — -OUTPUT_CHARACTER — — — — — -DB — — — — — ?

— — — — — — — — — — -0001 — — — — — — — — — — — — — — — — — OUTPUT_ROUTINE — PROC — — — NEAR
— — — — — — — — — — -0001 — A0 0000 R — — — — — — — — — — — — — — — — — — MOV — — — — AL,OUTPUT_CHARACTER — — — — Выборка выводимогосимвола
— — — — — — — — — — -0004 — B4 0E — — — — — — — — — — — — — — — — — — — — — — MOV — — — — AH, 14 — — — — — — — — — — — — — — Функция вывода в BIOS
— — — — — — — — — — -0006 — BB 0000 — — — — — — — — — — — — — — — — — — — — MOV — — — — BX, 0 — — — — — — — — — — — — — — — Установка номера страницы
— — — — — — — — — — -0009 — BA 0000 — — — — — — — — — — — — — — — — — — — — MOV — — — — DX, 0
— — — — — — — — — — -000C — CD 10 — — — — — — — — — — — — — — — — — — — — — — INT — — — — 10H — — — — — — — — — — — Вызов подпрограммы вывода на экран
— — — — — — — — — — -000E — C3 — — — — — — — — — — — — — — — — — — -RET — — — — — — — — — — — — — — — — — — — — Возврат в вызывающую программу

— — — — — — — — — — -000F — — — — — — — — — — — — — — — — — OUTPUT_ROUTINE — ENDP
— — — — — — — — — — -000F — — — — — — — — — — — — — — — — — CODE — — — ENDS
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — END

— — — — — — — — — — — — — — — — — — — — — — Фиг. 5.14 Процедура вывода

— — — — — Рассмотрим эту же задачу с другой стороны.Каким образом
— — — редактор связей узнает о местоположениивнешних имен? На Фиг. 5.14
— — — приведена подпрограмма, на которуюссылается другая программа,
— — — относящаяся к Фиг. 5.13. Переменные ипрограммные метки, на которые
— — — имеются ссылки в программе, на Фиг. 5.13,объявлены в подпрограмме
— — — с помощью оператора PUBLIC. Это означает,что их имена доступны для
— — — другого программного модуля. Ни на какиедругие переменные или
— — — программные метки в этой программе, неуказанные в операторе
— — — PUBLIC, ссылки в других программахневозможны. Хотя это может
— — — показаться неудобным, однако, если всеимена имели бы атрибут
— — — PUBLIC, то возникла бы другая трудность.Это означало бы, что
— — — каждое имя в любом из модулей, которые вымогли бы связать между
— — — собой, должны быть уникальными, т.е. выникогда бы не смогли
— — — использовать одно и то же символическоеимя дважды в разных
— — — модулях. Это может быть серьезнымпрепятствием для повторного
— — — использования некоторых подпрограмм, таккак такое использование
— — — возможно и через несколько лет, а помнитьвсе символические имена и
— — — следить за тем, чтобы ни одно из них неповторялось дважды довольно
— -&nbs
p- сложно. Заметьте, что в операторе PUBLICне требуется указывать
— — — атрибуты имен: об этом заботятся обычныеоператоры языка
— — — ассемблера.
— — — — — Программа LINK устанавливает соответствиемежду всеми внешними
— — — именами и соответствующими операторамиPUBLIC, которые их
— — — объявляют. После этого редактор связейзаписывает правильные
— — — значения адресов в команды, гдк естьссылки на внешние имена.
— — — Обрабатываются те поля в командах, рядом скоторыми в ассемблерном
— — — листинге стоял символ «E».

— — — — — Кроме того, ассемблер осуществляетобъединение любых сегментов
— — — с одними тем же именем. В случае программна Фиг. 5.13 и П5.14
— — — основная программа и подпрограммапринадлежат одному и тому же
— — — сегменту с именем CODE. Так как воператоре EXTRN основной
— — — программы для программы OUTPUT_ROUTINEуказан атрибут NEAR, то
— — — желательно, чтобы эта программа была в томже сегменте. Атрибут
— — — PUBLIC в операторе SEGMENT указываетредактору связей объединить
— — — оба программных модуля в один выполняемыйсегмент.

— — — — — В программе на Фиг. 5.13 есть еще одинсегмент, который следует
— — — рассмотреть. Данная программа выполняетсякак программа типа .EXE.
— — — При передаче управления программе типа.EXE система DOS организует
— — — для этой программы стек. Информация длястека поступает от
— — — редактора связей, который записывает ее вголовную метку файла типа
— — — .EXE. Подготовить все для стека обязанпрограммист. Если он этого
— — — не сделает, то редактор связей выдаетсоответствующее сообщение. В
— — — обычной ситуации это не может служитьпрепятствием для выполнения
— — — программы. Однако в таком случае параметрыстека для программы
— — — выбираются по умолчанию, т.е.местоположение и размер стека могут
— — — оказаться неподходящими. За подготовкустека отвечает сегмент
— — — STACK, входящий в программу на Фиг.5.13.Его имя STACK и задание
— — — соответствующего атрибута равным STACKговорят о том, что это
— — — область памяти предназначена для стека.Редактор связей, кроме
— — — того, проверяет, правильно ли установленуказатель стека в момент,
— — — когда управление передается программе.

Категория: Программирование на Ассемблере | Дата: 27.01.13

Меню раздела
Блок