Модульные программы обычно состоят из нескольких независимых частей кода, называемых модулями. Компилятор обрабатывает каждый из этих модулей независимо, а компоновщик (TLINK) объединяет по- лученные части вместе для создания выполняемого файла. О том, как использовать TLINK, рассказывается в документации по компилятору, но важно также знать, как определить и включить все файлы и биб- лиотеки, которые могут понадобиться при компоновке. В данной Гла- ве рассказывается о том, как это сделать.Описание внешних идентификаторов
Может оказаться так, что вам потребуется использовать неко- торые переменные или процедуры во всех модулях вашей программы. Турбо Ассемблер обеспечивает несколько директив, которые позволя- ют вам определить идентификаторы и библиотеки таким образом, что вы сможете использовать их глобально, а также использовать общие переменные (для которых выделяет память компоновщик). Вам потре- буется также соблюдать аккуратность при назначении имен идентифи- каторов, поскольку различные языки имеют здесь конкретные требо- вания. В следующий нескольких разделах мы обсудим эти директивы и соглашения по наименованию.Соглашения для конкретного языка
Когда вы назначаете имена идентификаторам, которые планиру- ется использовать глобально, нужно помнить об использовании спе- цификатора языка. К именам переменных предъявляются следующие требования: - в Паскале имена указываются символами в верхнем регистре; - в Си/С++ имен должны начинаться с символа подчеркивания (_). Остальная часть имени записывается символами в нижнем регистре. Параметр /m (описанный в Главе 2) сообщает Турбо Ассемблеру, что во всех именах идентификаторов нужно различать регистр. Пара- метр /mx (также описанный в Главе 2) указывает, что различать ре- гистр символов нужно только во внешних и общедоступных идентифи- каторах, и что все другие идентификаторы в исходном файле записа- ны в верхнем регистре. Когда вы используете эти два параметра вместе, для идентификаторов, описанных в Паскале, они имеют спе- циальное значение: они приводят к тому, что рассматриваемые иден- тификаторы будут доступны компоновщику, как идентификаторы в верхнем регистре.Описание общедоступных идентификаторов
При описании общедоступного идентификатора вы предполагаете, что он должен быть доступен из других модулей. Общедоступными мо- гут быть следующие типы идентификаторов: - имена переменных; - метки программы; - числовые константы, определенные с помощь EQU. Для определения общедоступных идентификаторов можно исполь- зовать директиву PUBLIC, которая имеет следующий синтаксис: PUBLIC [язык] идентификатор [,[язык] идентификатор] . где "язык" представляет собой C, CPP, PASCAL, BASIC, FORTRAN, PROLOG или NOLANGUAGE и определяет соглашения конкретного языка, применяемые к имени переменной. Использование спецификатора языка в директиве PUBLIC временно переопределяет временно переопределя- ет текущую установку языка (по умолчанию NOLANGUAGE, если другой язык не задан в директиве .MODEL). Турбо Ассемблер описывает идентификатор в объектном модуле таким образом, что он будет доступен всем другим модулям. Если вы не сделаете идентификатор общедоступным, то сможете обращаться к нему только из текущего модуля, например: PUBLIC XYPROC ; процедура общедоступна XYPROC PROC NEARОписание идентификаторов библиотеки
Вы можете использовать идентификаторы, как динамические точ- ки входа для динамически компонуемых библиотек (DLL). Для описа- ния идентификаторов, которые будут доступны таким образом, ис- пользуйте директиву PUBLICDDL. Она имеет следующий синтаксис: PUBLICDLL [язык] идентификатор [,[язык] идентификатор] . Турбо Ассемблер описывает идентификатор в объектном файле, как динамически компонуемую точку входа, благодаря чему они могут быть доступны в других программах. Спецификатор "язык" приводит к применению специфических для языка соглашений к конкретному имени идентификатора. Допустимыми спецификаторами языка являются специ- фикаторы C, CPP, PASCAL, BASIC, FORTRAN, PROLOG и NOLANGUAGE. Приведем пример кода с использованием PUBLICDLL: PUBLICDLL XYPROC ; процедура XYPROC доступна как XYPOROXC PROC NEAR ; динамически компонуемая точка ; входаОпределение внешних идентификаторов
Внешние идентификаторы - это идентификаторы, которые опреде- лены вне модуля и которые вы можете использовать внутри модуля. Эти идентификаторы должны быть описаны с помощью директивы PUBLIC. Директива EXTRN имеет следующий синтаксис: EXTRN определение [,определение] . где "определение" описывает идентификатор и имеет следующий фор- мат: [язык] имя [[счетчик_1]] :сложный_тип [:счетчик_2]Описание глобальных идентификаторов
Глобальные идентификаторы действуют также, как общедоступ- ные, при этом вам не нужно определять PUBLIC или EXTRN. Если пе- ременная определена в модуле, она действует как общедоступная. Если нет, она действует как внешняя. Для определения глобальных идентификаторов вы можете использовать директиву GLOBAL. Директи- ва GLOBAL имеет тот же синтаксис, что директивы PUBLIC и EXTRN (их синтаксис описан в предыдущих разделах). Директива GLOBAL позволяет вам иметь включаемый файл, кото- рый будет включаться во все исходные модули. Включаемый файл со- держит все совместно используемые данные, определенные как гло- бальные идентификаторы. Когда вы в каждом модуле ссылаетесь на эти элементы данных, директива GLOBAL действует как директива EXTRN, описывая для другого модуля, как определены данные. Перед тем, как использовать его где-либо в исходном коде, вы должны описать идентификатор как GLOBAL. Кроме того заметим, что при задании аргументов директивы GLOBAL используется тот же син- таксис, что и в директиве EXTRN. Приведем пример: GLOBAL X:WORD, Y:BYTE X DW 0 ; идентификатор стал доступен в ; других модулях mov al, Y ; описан как внешнийОпределение общих переменных
Общие переменные действуют как внешние переменные, но здесь есть одно существенное различие: общие переменные распределяются компоновщиком. Общие переменные переменные на самом деле аналоги- чны глобальным переменным, но вы не можете присвоить им начальные значения. На эти неинициализированные переменные можно ссылаться из нескольких модулей. Для определения общей переменной вы можете использовать ди- рективу COMM. Она имеет следующий синтаксис: COMM определение [,определение]. Каждое "определение" описывает идентификатор и имеет следую- щий формат: [расстояние] [язык] имя_идентификатора[[счетчик_1]]: сложный_тип [счетчик_2] где поле "расстояние" не является обязательным и может быть FAR или NEAR. Если вы не зададите "расстояние", по умолчанию оно бу- дет соответствовать используемой модели памяти. Если вы не ис- пользуете упрощенные директивы сегментации, то по умолчанию ис- пользуется NEAR. В крошечной, малой и средней моделях по умолчанию также используется NEAR, а во всех других - FAR. Поле "язык" задает язык: C, PASCAL, BASIC, FORTRAN, PROLOG или NOLANGUAGE. Использование в директиве COMM спецификатора язы- ка временно переопределяет текущую установку языка (по умолчанию или заданную с помощью директивы .MODEL). Заметим, что для того, чтобы действовало данное средство, вам не обязательно использо- вать директиву .MODEL. Поле "имя_идентификатора" задает имя идентификатора, который должен быть общим, и память для которого должна выделяться на этапе компоновки. В этом поле можно также задавать коэффициент размера элемента массива "счетчик_1", который должен учитываться в вычисляемом объеме общей памяти. Если в качестве расстояния за- дано FAR, то компоновщик, использует значение "счетчика_2", чтобы указать, сколько имеется элементов с размером, равным произведе- нию основного размера элемента (который определяется его типом) на "счетчик_1". По умолчанию значение поля "счетчик_1" равно 1. "Сложный_тип" - это тип данных аргумента. Он может быть либо простым типом, либо сложным выражением с указателем. Более под- робно о синтаксисе сложного типа рассказывается в Главе 5. Необязательное значение "счетчик_2" определяет, сколько эле- ментов определяет эта общая переменная. Если вы не задаете это поле, то подразумевается значение 1. Полный объем памяти, выделя- емой для общей переменной, равен произведению значения "счет- чик_2" на длину, заданную полем "тип", и на значение "счетчик_1". В режиме MASM, предполагается, что общие идентификаторы, описанные вне любого сегмента, должны быть доступны с помощью ре- гистра DS, что не всегда может допустимым предположением. Убеди- тесь, что вы либо поместили в DS корректное значение сегмента, либо при ссылке на эти переменные используете переопределение сегмента. В режиме Ideal Турбо Ассемблер корректно проверяет, яв- ляются ли общие переменные адресуемыми, используя любой из теку- щих сегментных регистров, описанный в директиве ASSUME. Приведем пример использования директивы COMM: COMM buffer:BYTE:512 ; во время компоновки выделяет- ; ся 512 байт COMM abc[41]:WORD:10 ; на этапе компоновки выделяет- ; ся память 820 байт (10 эле- ; ментов из 41 слова каждый) COMM FAR abc[41]:WORD:10 ; на этапе компоновки выделяет- ; ся 10 элементов из 82 байт ; (2 байта * 41 элемент)Включение библиотеки
В том случае, когда вы знаете, что ваш исходный файл будет всегда использовать подпрограммы заданной библиотеки, можно ис- пользовать директиву INCLUDELIB. Директива INCLUDELIB сообщает компоновщику, что нужно включить указанную библиотеку. В режиме Ideal эта директива имеет следующий синтаксис: INCLUDELIB "имя_файла" ; обратите внимание на кавычки! а в режиме MASM: INCLUDELIB имя_файла где "имя_файла" - это имя библиотеки, которую вы хотите включать с помощью компоновщика на этапе компоновки. Если вы не укажете в заданном имени файла расширение, то компоновщик подразумевает расширение .LIB. Приведем пример: INCLUDELIB "diskio" ; включает DISKIO.LIB
Назад | Содержание | Вперед