Объединение модулей
V
А теперь проверим все представленные в данной главе программы на предмет их трансляции средствами пакета TASM.
С программами на Рисунок 1.2-1.3 дело обстоит просто. Для их трансляции достаточно выполнить команды:
TASM32 /ml PROG1.ASM TLINK32 -аа PROG1.OBJ
Обратимся теперь к модулям PROG2.ASM и PROG1.ASM, приведенным на Рисунок 1.4 и 1.5 соответственно.
Получение объектных модулей происходит без каких-либо трудностей. Просматривая модуль PROG2.OBJ, мы увидим, что внешняя процедура представлена просто именем PROC1.
Следовательно, единственное, что нам следует сделать, это заменить в модуле PROC1.ASM имя PROC1@0 на PROC1.
Объединение модулей далее производится элементарно:
TLINK32 -аа PROG1.OBJ PROG2.OBJ
Для работы с библиотекой в пакете TASM имеется программа — библиотекарь TLIB.ЕХЕ. Создание библиотеки, состоящей из модуля PROG2.OBJ, производится по команде
TLIB LIB1.LIB+PROG2.OBJ
В результате на диске появится библиотека LIB1.LIB. Далее компонуем модуль PROG1.OBJ с этой библиотекой:
TLINK32 -аа PROG1,PROG1,PROG1,LIB1
В результате получается загружаемый модуль PROG1.EXE.
Вообще, стоит разобраться с командной строкой TLINK32 более подробно. В расширенном виде11 эта строка выглядит следующим образом:
TLINK32 -аа OBJFILES, EXEFILE, MAPFILE, LIBFILES
OBJFILES - один или несколько объектных файлов (через пробел). Первый главный модуль.
EXEFILE - исполняемый модуль.
MAPFILE - МАР-файл, содержащий информацию о структуре модуля.
LIBFILES - одна или несколько библиотек (через пробел).
В TASM отсутствует директива INVOKE, поэтому в дальнейшем я буду избегать ее использования12.
В начале книги я объявил о своем намерении примирить два ассемблера. Поскольку различие между ними заключается в директивах и макрокомандах (см. Гл.1.5), то напрашивается вывод, что совместимости можно добиться, избегая таких директив и макрокоманд. Основой программы для Windows является вызов API-функций (см. Гл. 1.2), а мы знаем, что различие в вызове внешней процедуры заключается в том, что в именах для MASM в конце есть добавка @N. И здесь не обойтись без макроопределений, и начинается самое интересное. Но об этом, дорогой читатель, Вы узнаете в свое время.
И MASM и TASM поддерживают так называемую упрощенную сегментацию. Я являюсь приверженцем классической структуры ассемблерной программы и должен признаться, что упрощенная сегментация довольно удобная штука, особенно при программировании под Windows. Суть такой сегментации в следующем: начало сегмента определяется директивой .CODE, а сегмента данных - .DATA13. Причем обе директивы могут появляться в тексте программы несколько раз. Транслятор затем собирает код и данные вместе, как положено. Основной целью такого подхода, по-видимому, является возможность приблизить в тексте программы данные к тем строкам, где они используются. Такая возможность, как известно, в свое время была реализована в C++. На мой взгляд, она приводит к определенному неудобству при чтении текста программы. Кроме того, не сочтите меня за эстета, но когда я вижу данные, перемешанные в тексте программы с кодом, у меня возникает чувство дискомфорта.
Ниже представлена программа, демонстрирующая упрощенный режим сегментации.
.386P ; плоская модель .MODEL FLAT, STDCALL ;-------------------------------------------------- ; сегмент данных .DATA SUM DWORD 0 ; сегмент кода .CODE START: ; сегмент данных .DATA A DWORD 100 ; сегмент кода .CODE MOV EAX,A ; сегмент данных .DATA B DWORD 200 ; сегмент кода .CODE ADD EAX,B MOV SUM,EAX RET ; выход END START