(Имя идентификатора не является именем сегмента либо уже оп- ределено в группе)
Либо имя идентификатора уже определено в группе, либо не яв- ляется именем сегмента. Например:
DATA SEGMENT DATA ENDS DGROUP GROUP DATA DGROUP2 GROUP DATA ; ошибка: DATA уже определено в DGROUP
Таблица виртуальных методов (ТВМ) представляет собой табли- цу адресов процедур, которые выполняют виртуальные методы. Обычно данная таблица размещается в сегменте данных программы. Любой объект, содержащий виртуальные методы, требует, чтобы где-либо в программе находился экземпляр таблицы виртуальных методов.
Для создания экземпляра таблицы виртуальных методов объекта используется директива TBLINST. Поскольку эта директива создает таблицу для последнего описанного объекта, ее следует помещать непосредственно после описания объекта, например:
INCLUDE list.aso DATASEG TBLINST
Текстовая макрокоманда - это идентификатор, представляющий строку текстовых символов. Когда Турбо Ассемблер обнаруживает идентификатор в выражениях (и в других ситуациях), он подставляет вместо него текстовые символы. Например, если DoneMsg - это текс- товая макрокоманда, имеющая значение "Returning to DOS", то сле- дующий оператор:
GoodBy DB DoneMsg
дает в результате:
GoodBy DB 'Returning to DOS'
В состав Турбо Ассемблера входят несколько справочных фай- лов: FILELIST.DOC. README, HELPME!.TSM, MANUAL.TSM, H2ASH.TSM и TCREF.TSM. Первые два файла содержатся на установочной дискете "Installation Disk" и копируются в основной каталог языка. Другие файлы находятся в подкаталоге DOC.
Независимо от содержимого тела макрокоманды, средство обра- ботки макрокоманд Турбо Ассемблера интерпретирует макрокоманду, состоящую из нескольких строк, как просто несколько строк текста. Турбо Ассемблер позволяет вам заменить идентификаторы в теле мак- рокоманды текстом, заданным при вызове макрокоманды. Это средство называется подстановкой аргументов. Идентификаторы в теле макро- команды, которые должны быть заменены, называются формальными (фиктивными) аргументами. Предположим, например, что идентифика- тор foo - это формальный аргумент в следующем теле макрокоманды:
PUSH foo MOV foo,1
Если при вызове данной макрокоманды вы присваиваете foo текстовую строку AX, то фактическим включаемым в модуль текст бу- дет:
PUSH foo MOV AX,1
Правила, которые Турбо Ассемблер использует для распознава- ния формальных аргументов, достаточно сложны. Рассмотрим, напри- мер, следующие строки тела макрокоманды, где формальный аргумент foo не распознается:
symfoo: DB 'It is foo time'
В общем случае Турбо Ассемблер не будет распознавать фор- мальный аргумент (без специального указания) в следующих ситуаци- ях:
- когда он является частью другого идентификатора;
- когда он находится внутри кавычек (' или ");
- в режиме Ideal, когда он указывается после двоеточия не внутри кавычек.
Для различных единиц объектно-ориентированного программиро- вания в C++ и Паскале используются различные термины. В этом смысле Турбо Ассемблер более близок к Паскалю, хотя не все терми- ны здесь совпадают. Различия между языками описываются в следую- щей таблице:
Терминология объектно-ориентированного программирования Таблица 4.1 ------------------------T----------------------T----------------¬ ¦Турбо Ассемблер ¦ Borland C++ ¦ Турбо Паскаль ¦ +-----------------------+----------------------+----------------+ ¦метод ¦ функция-элемент ¦ метод ¦ ¦ ¦ ¦ ¦ ¦процедура метода ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦объект ¦ класс ¦ объект ¦ ¦ ¦ ¦ ¦ ¦базовый объект ¦ базовый класс ¦ базовый объект ¦ ¦ ¦ ¦ ¦ ¦порождающий объект ¦ порождающий класс ¦ порождающий ¦ ¦ ¦ ¦ объект ¦ ¦ ¦ ¦ ¦ ¦порожденный объект ¦ порожденный класс ¦ порожденный ¦ ¦ ¦ ¦ объект ¦ ¦ ¦ ¦ ¦ ¦поле порожденного ¦ элемент данных ¦ поле ¦ ¦ объекта ¦ ¦ ¦ L-----------------------+----------------------+-----------------
Примечание: Эти термины подробнее поясняются в данной главе ниже.
(Расширение текстовой макрокоманды превышает максимально до- пустимую длину)
Это сообщение об ошибке выдается, когда расширение текстовой макрокоманды превышает максимально допустимую длину.
Каждый идентификатор имеет тип, который описывает его харак- теристики и связанную с ним информацию. Тип задается способом оп- ределения идентификатора. Например, вы можете определить иденти- фикатор, представляющий числовое выражение, текстовую строку, имя процедуры или переменную. Типы идентификаторов, поддерживаемых Турбо Ассемблером, перечислены в Таблице 5.4.
Типы идентификаторов Таблица 5.4 ----------------------------T------------------------------------¬ ¦ Тип идентификатора ¦ Описание ¦ +---------------------------+------------------------------------+ ¦ адрес ¦ Адрес. Подтипами данных являются ¦ ¦ ¦ типы UNKNOWN, BYTE, WORD, DWORD, ¦ ¦ ¦ PWORD, QWORD, TBYTE и адрес струк- ¦ ¦ ¦ туры или таблицы с указанным име- ¦ ¦ ¦ нем. Подтипами кода являются ¦ ¦ ¦ SHORT, NEAR, FAR. ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ текстовая макрокоманда ¦ Текстовая строка. ¦ ¦ ¦ ¦ ¦ псевдоним ¦ Эквивалентный идентификатор. ¦ ¦ ¦ ¦ ¦ числовое выражение ¦ Значение числового выражения. ¦ ¦ ¦ ¦ ¦ макрокоманда из ¦ Несколько текстовых строк с пус- ¦ ¦ нескольких строк ¦ тыми аргументами. ¦ ¦ ¦ ¦ ¦ структура/объединение ¦ Тип данных структуры или объеди- ¦ ¦ ¦ нения. ¦ ¦ ¦ ¦ ¦ таблица ¦ Табличный тип данных. ¦ ¦ ¦ ¦ ¦ элемент структуры/ ¦ Элемент структуры или таблицы. ¦ ¦ таблицы ¦ ¦ ¦ ¦ ¦ ¦ запись ¦ Данные типа записи. ¦ ¦ ¦ ¦ ¦ поле записи ¦ Поле записи. ¦ ¦ ¦ ¦ ¦ перечисление ¦ Перечислимый тип данных. ¦ ¦ ¦ ¦ ¦ сегмент ¦ Сегмент. ¦ ¦ ¦ ¦ ¦ группа ¦ Группа. ¦ ¦ ¦ ¦ ¦ тип ¦ Названный тип. ¦ L---------------------------+-------------------------------------
Хотя в программах Турбо Ассемблера можно свободно обращаться к любой переменной или данным любого размера (8, 16, 32 бита и т. д.), в общем случае хорошо обращаться к переменным в соответствии с их размером. Например, если вы записываете слово в байтовую пе- ременную, то обычно это приводит к проблемам:
. . . SmallCount DB 0 . . . mov WORD PTR [SmallCount],0ffffh . . .
Поэтому важно, чтобы в операторе Ассемблера EXTRN, в котором описываются переменные С++, задавался правильный размер этих пе- ременных, так как при генерации размера доступа к переменной С++ Турбо Ассемблер основывается именно на этих описаниях.
Если в программе на языке С++ содержится оператор:
char c
то код Ассемблера:
. . . EXTRN c:WORD . . . inc [c] . . .
может привести к весьма неприятным ошибкам, поскольку после того, как в коде на языке С++ переменная c увеличится очередные 256 раз, ее значение будет сброшено, а так как она описана, как пере- менная размером в слово, то байт по адресу OFFSET c + 1 будет увеличиваться некорректно, что приведет к непредсказуемым резуль- татам.
Между типами данных С++ а Ассемблера существует следующее соотношение:
--------------------------------T-------------------------------¬ ¦ Тип данных С++ ¦ Тип данных Ассемблера¦ +-------------------------------+-------------------------------+ ¦ unsigned char ¦ byte ¦ ¦ char ¦ byte ¦ ¦ enum ¦ word ¦ ¦ unsigned short ¦ word ¦ ¦ short ¦ word ¦ ¦ unsigned int ¦ word ¦ ¦ int ¦ word ¦ ¦ unsigned long ¦ dword ¦ ¦ long ¦ dword ¦ ¦ float ¦ dword ¦ ¦ double ¦ qword ¦ ¦ long double ¦ tbyte ¦ ¦ near* ¦ word ¦ ¦ far* ¦ dword ¦ L-------------------------------+--------------------------------
Турбо Ассемблер в режиме Ideal всегда использует 32-разряд- ную арифметику. В режиме MASM Турбо Ассемблер использует 16- или 32-разрядную арифметику, в зависимости от выбора процессора 80386. Таким образом, некоторые выражения, в зависимости от того, какой процессор выбирается, могут давать разные результаты. Нап- ример, при вычислении:
(1000h * 1000h) / 1000h
получается 1000h при выборе процессора 80386 или 0 при выборе процессоров 8086, 80186 или 80286.
(В команде не хватает операндов)
В команде должно быть указано большее число операндов. Нап- ример:
ADD ax ; отсутствует второй операнд
(Обнаружено слишком много ошибок)
Ассемблирование пользовательского файла прекращено, посколь- ку в этом файле содержится слишком много ошибок. Возможно, что на самом деле ошибок не так уж и много, однако они таковы, что вызы- вают эффект "снежного кома". Примером такой ошибки может быть не- верное определение имени идентификатора, которое используется во многих строках программы. На самом деле сделана лишь одна ошибка (неверно определено имя идентификатора), однако сообщение об ошибке будет выдано в каждой строке, где появляется это имя.
Турбо Ассемблер прекращает ассемблирование файла, когда об- щее число ошибок и предупреждающих сообщений достигает 100.
(Слишком много ошибок или предупреждений)
Сообщения об ошибках больше выдаваться не будут. Максималь- ное число сообщений об ошибках, которое выдается Турбо Ассембле- ром, равно 100. Это максимально допустимое число ошибок превыше- но. Ассемблирование программы тем не менее будет продолжено, однако далее будут печататься только предупреждающие сообщения.
(Слишком много начальных значений)
При инициализации структуры или объединения указано слишком много значений. Например:
XYZ STRUC A1 DB ? A2 DB ? XYZ ENDS ANXYZ XYZ <1,2,3> ; ошибка: в XYZ определены ; только два поля
При инициализации полей структур и объединений допускается указывать меньше значений, чем число полей, но нельзя указывать больше значений.
(В выражении содержится слишком много множителей для регист- ров)
Для процессора 80386 допускается коэффициент индексных опе- рандов. Однако коэффициент можно указывать не более, чем у одного регистра. Например:
mov EAX,[2*EBX+4*EDX] ; слишком много ; коэффициентов
(В выражении указано слишком много регистров)
В выражении указано более одного индексного и одного базис- ного регистра. Например:
mov ax,[BP+SI+DI] ; нельзя одновременно указывать SI и DI
(Слишком много регистров в директиве USES)
В директиве USES для текущей процедуры указано более 8 ре- гистров.
(Предполагается конечное пустое значение)
Директива определения данных (DB, DW и т.д.) оканчивается запятой. TASM интерпретирует ее как пустое значение. Например:
db 'привет',13,10 ; то же, что и db'привет',13,10?
Турбо Ассемблер работает на компьютерах семейства IBM PC, включая модели XT, AT и PS/2, а также на полностью совместимых с ними компьютерах. Для работы Турбо Ассемблера требуется операци- онная система MS-DOS (версии 2.0 или более поздняя) и не менее 256К оперативной памяти.
Турбо Ассемблер генерирует инструкции процессоров 8086, 80186, 80286, 80386 и i486, а также инструкции с плавающей точкой для арифметических сопроцессоров 8087, 80287 и 80387. (Подробнее об инструкциях процессором семейства 80х86/80х87 рассказывается в книгах фирмы Intel.)
Введение
Требования к программному и аппаратному обеспечению
Поддержка DPMI
О данной документации
Руководство пользователя
Соглашения по обозначениям
Как обратиться за помощью к фирме Borland
Ресурсы вашего пакета
Возможности фирмы Borland
ЧАСТЬ 1. ИСПОЛЬЗОВАНИЕ ТУРБО АССЕМБЛЕРА
Глава 1. Начало работы на Турбо Ассемблере
Установка Турбо Ассемблера в системе
Текстовые справочные файлы
Файл README
Файл HELPME!.TSM
Файл H2ASH.TSM
Файл TCREF.TSM
Оперативный справочник
Ваша первая программа на Турбо Ассемблере
Ассемблирование вашей первой программы
Компоновка программы
Запуск вашей первой программы
Что происходит?
Модификация вашей первой программы на Турбо Ассемблере
Вывод информации на устройство печати
Ваша вторая программа на Турбо Ассемблере
Запуск программы REVERSE.ASM
Литература по языку Ассемблера
Глава 2. Использование директив и параметров
Запуск Турбо Ассемблера из DOS
Параметры командной строки
Параметр /A
Параметр /B
Параметр /C
Параметр /D
Параметр /E
Параметр /H или /?
Параметр /I
Параметр /J
Параметр /KH
Параметр /L
Параметр /LA
Параметр /M
Параметр /ML
Параметр /MU
Параметр /MV#
Параметр /MX
Параметр /N
Параметр /O
Параметр /OP
Параметр /P
Параметр /Q
Параметр /R
Параметр /S
Параметр /T
Параметр /V
Параметр /W
Параметр /X
Параметр /Z
Параметр /ZD
Параметр /ZI
Параметр /ZN
Косвенные командные файлы
Файлы конфигурации
Глава 3. Общие принципы программирования
Режим Ideal Турбо Ассемблера
Для чего используется режим Ideal?
Переключение в режим Ideal и выход из него
Отличия режима Ideal и режима MASM
Выражения и операнды
Операции
Подавление корректировок
Операнд инструкции BOUND
Сегменты и группы
Доступ к данным в сегменте, принадлежащем группе
Комментарии в программах
Комментарии в конце строки
Директива COMMENT
Продолжение строки
Использование включаемых файлов
Предопределенные идентификаторы
Присваивание идентификаторам значений
Общая структура модуля
Директива VERSION
Директива .MODEL с параметром TPASCAL задает упрощенную сег- ментацию, модель памяти и языковую поддержку. Обычно используется большая модель памяти (large) Ранее мы уже видели, что нужно сде- лать в программах Ассемблера, чтобы можно было использовать про- цедуры и функции Паскаля. Преобразуем пример, используя в нем ди- рективы .MODEL и PROC:
.MODEL large, PASCAL .CODE MyProc PROC FAR i:BYTE,j:BYTE result:DWORD PUBLIC MyProc mov ax,i . . . ret
Заметим, что теперь не нужно задавать параметры в обратном порядке. Не требуется также масса других операторов. Использова- ние в директиве .MODEL ключевого слова PASCAL задает использова- ние соглашений Паскаля, определяет имена сегментов, выполняет инструкции PUSH BP и MOV BP,SP и задает также возврат с помощью инструкций POP BP и RETn (где n - число байт параметров).
Для удаления макрокоманд вы можете использовать директиву PURGE. Директива PURGE имеет следующий синтаксис:
PURGE имя_макрокоманды, [имя_макрокоманды].
Директива PURGE удаляет определение макрокоманды, состоящей из нескольких строк, с именем "имя_макрокоманды" После использо- вания директивы PURGE Турбо Ассемблер больше не интерпретирует идентификатор PURGE как макрокоманду, например:
ADD MACRO a1,a2 SUB a1,a2 ENDM ADD ax,bx ; этот вызов даст SUB ax,bx PURGE ADD ADD ax,bx ; теперь это не макрокоманда, поэтому ; вы получите ADD ax,bx
Вы можете сразу удалить этой директивой несколько макроко- манд, разделив их имена запятыми. Отметим однако, что идентифика- тор удаленной макрокоманды можно переопределить только другой макрокомандой.
Значения параметров для всех типов указателей заносятся не- посредственно в стек, как указатели дальнего типа: сначала слово, содержащее сегмент, затем другое слово, содержащее смещение. Сег- мент занимает старший адрес, в соответствии с соглашениями фирмы Intel. Для извлечения параметра-указателя в программе Турбо Ас- семблера можно использовать инструкции LDS или LES.
Унарная операция LENGTH возвращает информацию о счетчике или числе величин, представляющих идентификатор. Возвращаемое факти- ческое значение зависит от типа идентификатора, что показано в приведенной ниже таблице:
Значения, возвращаемые операцией LENGTH Таблица 5.11 --------------------------------T-------------------------------¬ ¦ Выражение ¦ Значение ¦ +-------------------------------+-------------------------------+ ¦ LENGTH имя_адреса ¦ Возвращает счетчик элементов, ¦ ¦ ¦ выделяемых при определении ¦ ¦ ¦ имени адреса. ¦ ¦ ¦ ¦ ¦ LENGTH имя_элемента_структуры/¦ Возвращает счетчик элементов, ¦ ¦ объединения ¦ выделенных при определении ¦ ¦ ¦ элемента (только режим MASM). ¦ L-------------------------------+--------------------------------
При применении ее ко всем другим типам идентификаторов опе- рация LENGTH возвращает значение 1. Приведем некоторые примеры использования операции LENGTH:
MSG DB "Hello" array DW 10 DUP (4 DUP (1),0) numbrs DD 1,2,3,4 lmsg = LENGTHG msg ; =1, нет операции DUP larray = LENGTH nsg ; =10, счетчик повторения DUP lnumbrs = LENGTH numbrs ; =1, нет операции DUP
Унарная операция SIZE
Унарная операция SIZE возвращает информацию о размере выде- ленного элемента данных. Возвращаемое значение зависит от типа заданного идентификатора. Список доступных для операции SIZE зна- чений приведен в следующей таблице: Значения, возвращаемые операцией SZIE Таблица 5.12 ------------------------------T---------------------------------¬ ¦ Выражение ¦ Значение ¦ +-----------------------------+---------------------------------+ ¦ SIZE имя_адреса ¦ В режиме Ideal возвращается ¦ ¦ ¦ фактическое число байт, выде- ¦ ¦ ¦ ленных для переменных данных. ¦ ¦ ¦ В режиме MASM возвращается ¦ ¦ ¦ размер подтипа имя_адреса ¦ ¦ ¦ (UNKNOWN=0, BYTE=1, WORD=2, ¦ ¦ ¦ DWORD=4, PWORD=FWORD=6, QWORD ¦ ¦ ¦ =8, TBYTE=10, SHORT=NEAR= ¦ ¦ ¦ 0ffffh, FAR=0fffeh, адрес ¦ ¦ ¦ структуры = размеру структу- ¦ ¦ ¦ ры), умноженный на значение ¦ ¦ ¦ LENGTH имя_адреса. ¦ ¦ SIZE имя_структуры/ ¦ Возвращает число байт, требу- ¦ ¦ объединения ¦ емых для представления струк- ¦ ¦ ¦ туры или объединения. ¦ ¦ SIZE имя_таблицы ¦ Возвращает число байт, необ- ¦ ¦ ¦ ходимых для представления ¦ ¦ ¦ таблицы. ¦ ¦ SIZE имя_элемента_таблицы/ ¦ Возвращает величину TYPE имя ¦ ¦ структуры ¦ _элемента_таблицы/структуры* ¦ ¦ ¦ LENGTH имя_элемента_таблицы/ ¦ ¦ ¦ объединения (только для ре- ¦ ¦ ¦ жима MASM). ¦ ¦ SIZE имя_записи ¦ Возвращает число байт, не- ¦ ¦ ¦ обходимых для представления ¦ ¦ ¦ общего числа бит, зарезерви- ¦ ¦ ¦ рованных в определении запи- ¦ ¦ ¦ си: 1, 2 или 4. ¦ ¦ SIZE имя_перечисления ¦ Возвращает число байт, необ- ¦ ¦ ¦ ходимых для представления ¦ ¦ ¦ максимального значения, при- ¦ ¦ ¦ сутствующего в перечислении: ¦ ¦ ¦ 1, 2 или 4. ¦ ¦ SIZE имя_сегмента ¦ Возвращает размер сегмента ¦ ¦ ¦ в байтах. ¦ ¦ SIZE имя_типа ¦ Возвращает число байт, необ- ¦ ¦ ¦ ходимых для представления ¦ ¦ ¦ названного типа, при этом ¦ ¦ ¦ ближние и дальние метки воз- ¦ ¦ ¦ вращают значение 0ffffh, а ¦ ¦ ¦ дальние - 0fffeh. ¦ L-----------------------------+----------------------------------
При применении ко всем другим типам идентификаторов операция SIZE возвращает значение 0.
Унарная операция MASK создает маску на основе битового поля, в котором биты в возвращаемом значении устанавливаются в 1 и со- ответствуют битам в поле, которое представляет идентификатор. Возвращаемое значение зависит от типа идентификатора, что показа- но в приведенной ниже таблице. Заметим, что для всех других иден- тификаторов использовать операцию MASK не разрешается.
Значения, возвращаемые MASK Таблица 5.14 --------------------------T-------------------------------------¬ ¦ Выражение ¦ Значение ¦ +-------------------------+-------------------------------------+ ¦ MASK имя_записи ¦ Возвращает маску, в которой биты, ¦ ¦ ¦ резервированные для представления ¦ ¦ ¦ битовых полей в определении записи, ¦ ¦ ¦ равны 1, а остальные равны 0. ¦ ¦ ¦ ¦ ¦ MASK имя_поля_записи ¦ Возвращает маску, в которой биты, ¦ ¦ ¦ резервированные для поля в определе-¦ ¦ ¦ нии записи, равны 1, а остальные ¦ ¦ ¦ равны 0. ¦ ¦ ¦ ¦ ¦ MASK имя_перечисления ¦ Возвращает маску, в которой биты, ¦ ¦ ¦ резервированные для представления ¦ ¦ ¦ максимального значения в определе- ¦ ¦ ¦ нии перечисления, равны 1, а ос- ¦ ¦ ¦ тальные равны 0. ¦ L-------------------------+--------------------------------------
Унарная операция WIDTH возвращает размер в битах поля запи- си. Это значение зависит от типа идентификатора. Эти типы иденти- фикаторов показаны в приведенной ниже таблице. Для всех других типов операцию WIDTH использовать не допускается.
Значения WIDTH Таблица 5.13 --------------------------T-------------------------------------¬ ¦ Выражение ¦ Значение ¦ +-------------------------+-------------------------------------+ ¦ WIDTH имя_записи ¦ Возвращает общее число бит, заре-¦ ¦ ¦ зервированных в определении записи.¦ ¦ ¦ ¦ ¦ WIDTH имя_поля_записи ¦ Возвращает число бит, зарезервиро-¦ ¦ ¦ ванных для поля в определении запи-¦ ¦ ¦ си. ¦ ¦ ¦ ¦ ¦ WIDTH имя_перечисления ¦ Возвращает число бит, необходимых ¦ ¦ ¦ для представления максимального ¦ ¦ ¦ значения в определении enum. ¦ L-------------------------+--------------------------------------
(Идентификатор не определен)
Оператор содержит идентификатор, который не был ранее опре- делен в исходном файле.
(Неожиданный конец файла (нет директивы END))
В исходном файле отсутствует директива END. Директива END обязательно должна быть указана в конце исходного файла.
(Неизвестный символ)
Текущая строка исходной программы содержит символ, который не принадлежит набору символов, допустимых для построения симво- лических имен и выражений в Турбо Ассемблере. Например:
add ax,!1 ; ошибка: восклицательный знак - ; недопустимый символ
(Непарная директива ENDP:_)
В директиве ENDP указано имя, не совпадающее с именем проце- дуры, которую закрывает данная директива. Например:
ABC PROC XYZ ENDP ; ошибка: вместо XYZ должно быть указано ABC
(Непарная директива ENDS:_)
В директиве ENDS указано имя, не совпадающее с именем сег- мента, который закрывает данная директива, либо не совпадающее с именем структуры или объединения, оканчивающегося этой директи- вой. Например:
ABC STRUC XYZ ENDP ; ошибка: вместо XYZ должно быть указано ABC DATA SEGMENT CODE ENDS ; ошибка: вместо CODE должно быть указано DATA
В следующей таблице показаны используемые по умолчанию для каждой модели памяти атрибуты сегмента.
Используемые по умолчанию сегменты и типы для модели памяти TINY Таблица A.1 ----------------------------------------------------------------¬ ¦ Директива Имя Выравнивание Комбинирование Класс Группа¦ +---------------------------------------------------------------+ ¦.CODE _TEXT WORD PUBLIC 'CODE' DGROUP ¦ ¦.FARDATA FAR_DATA PARA private 'FAR_DATA' ¦ ¦.FARDATA? FAR_BSS PARA private 'FAR_BSS' ¦ ¦.DATA _DATA WORD PUBLIC 'DATA' DGROUP ¦ ¦.CONST CONST WORD PUBLIC 'CONST; DGROUP ¦ ¦.DATA? _BSS WORD PUBLIC 'BSS' DGROUP ¦ ¦STACK* STACK PARA STACK 'STACK' DGROUP ¦ ¦ ¦ ¦ * - STACK не подразумевается размещенным в DGROUP или¦ ¦FARSTACK, заданным в директиве MODEL. ¦ L----------------------------------------------------------------
Используемые по умолчанию сегменты и типы для модели памяти SMALL Таблица A.2 ----------------------------------------------------------------¬ ¦ Директива Имя Выравнивание Комбинирование Класс Группа¦ +---------------------------------------------------------------+ ¦.CODE _TEXT WORD PUBLIC 'CODE' ¦ ¦.FARDATA FAR_DATA PARA private 'FAR_DATA' ¦ ¦.FARDATA? FAR_BSS PARA private 'FAR_BSS' ¦ ¦.DATA _DATA WORD PUBLIC 'DATA' DGROUP ¦ ¦.CONST CONST WORD PUBLIC 'CONST; DGROUP ¦ ¦.DATA? _BSS WORD PUBLIC 'BSS' DGROUP ¦ ¦STACK* STACK PARA STACK 'STACK' DGROUP ¦ ¦ ¦ ¦ * - STACK не подразумевается размещенным в DGROUP или¦ ¦ FARSTACK, заданным в директиве MODEL. ¦ L----------------------------------------------------------------
Используемые по умолчанию сегменты и типы для модели памяти MEDIUM
Таблица A.3 ----------------------------------------------------------------¬ ¦ Директива Имя Выравнивание Комбинирование Класс Группа¦ +---------------------------------------------------------------+ ¦.CODE имя_TEXT WORD PUBLIC 'CODE' ¦ ¦.FARDATA FAR_DATA PARA private 'FAR_DATA' ¦ ¦.FARDATA? FAR_BSS PARA private 'FAR_BSS' ¦ ¦.DATA _DATA WORD PUBLIC 'DATA' DGROUP ¦ ¦.CONST CONST WORD PUBLIC 'CONST; DGROUP ¦ ¦.DATA? _BSS WORD PUBLIC 'BSS' DGROUP ¦ ¦STACK* STACK PARA STACK 'STACK' DGROUP ¦ ¦ ¦ ¦ * - STACK не подразумевается размещенным в DGROUP или ¦ ¦ FARSTACK, заданным в директиве MODEL. ¦ L----------------------------------------------------------------
Директива .MODEL указывает Турбо Ассемблеру, что сегменты, создаваемые с помощью упрощенных директив определения сегментов, должны быть совместимы с выбранной моделью памяти (TINY - крохот- ной, SMALL - малой, COMPACT - компактной, MEDIUM - средней, LARGEбольшой или HUGE - громадной) и управляет назначаемым по умолчанию типом (FAR или NEAR) процедур, создаваемых по директиве PROC. Модели памяти, определенные с помощью директивы .MODEL, совместимы с моделями Borland C++ с соответствующими именами.
Наконец, упрощенные директивы определения сегментов .DATA, .CODE, .DATA?, .FARDATA, .FARDATA? и .CONST генерируют сегменты, совместимые с Borland C++.
Например, рассмотрим следующий модуль Турбо Ассемблера с именем DOTOTAL.ASM:
.MODEL SMALL ; выбрать малую модель памяти ; (ближний код и данные) .DATA ; инициализация сегмента данных, ; совместимого с Borland C++ EXTRN _Repetitions:WORD ; внешний идентификатор PUBLIC _StartingValue ; доступен для других модулей _StartValue DW 0 .DATA? ; инициализированный сегмент ; данных, совместимый с Borland C++ RunningTotal DW ? .CODE ; сегмент кода, совместимый с ; Borland C++ PUBLIC _DoTotal _DoTotal PROC ; функция (в малой модели памяти ; вызывается с помощью вызова ; ближнего типа) mov cx,[_Repetitions] ; счетчик выполнения mov ax,[_StartValue] mov [RunningTotal],ax ; задать начальное ; значение TotalLoop: inc [RunningTotal] ; RunningTotal++ loop TotalLoop mov ax,[RunningTotal] ; возвратить конечное ; значение (результат) ret _DoTotal ENDP END
Написанная на Ассемблере процедура _DoTotal при использова- нии малой модели памяти может вызываться из Borland C++ с помощью оператора:
DoTotal();
Заметим, что в процедуре DoTotal предполагается, что где-то в другой части программы определена внешняя переменная Repetitions. Аналогично, переменная StartingValue объявлена, как общедоступная, поэтому она доступна в других частях программы. Следующий модуль Borland C++ (который называется SHOWTOT.CPP) об- ращается к данным в DOTOTAL.ASM и обеспечивает для модуля DOTOTAL.ASM внешние данные:
После выбора модели памяти вы можете использовать упрощенные сегментные директивы для того, чтобы начинать отдельные сегменты. Эти упрощенные директивы вы можете использовать только после ди- рективы MODEL, которая задает для модуля модель памяти. В модуле допускается указывать столько директив сегментации, сколько необ- ходимо. Турбо Ассемблер для получения одного сегмента комбинирует все части с одинаковыми именами (как если бы вы ввели все эти фрагменты после одной директивы сегментации). Перечень директив содержится в Таблице 7.4.
--------------------------T-------------------------------------¬ ¦ Директива ¦ Описание ¦ +-------------------------+-------------------------------------+ ¦ CODESEG [имя] ¦ Начинает или продолжает сегмент кода¦ ¦ ¦ модуля. Для моделей с дальним типом¦ ¦ ¦ кода вы можете задать имя, являющее-¦ ¦ ¦ ся фактическим именем сегмента. За-¦ ¦ ¦ метим, что таким образом вы можете¦ ¦ ¦ генерировать для модуля более одного¦ ¦ ¦ сегмента кода. ¦ ¦ ¦ ¦ +-------------------------+-------------------------------------+ ¦ .CODE [имя] ¦ Эквивалентна директиве CODESEG. До-¦ ¦ DATASEG ¦ пускается только для режима MASM.¦ ¦ ¦ Начинает или продолжает ближний или¦ ¦ ¦ инициализируемый по умолчанию сег-¦ ¦ ¦ мент данных. ¦ ¦ ¦ ¦ +-------------------------+-------------------------------------+ ¦ .DATA ¦ Эквивалентна директиве DATASEG. До-¦ ¦ CONST ¦ пускается только для режима MASM.¦ ¦ ¦ Начинает или продолжает сегмент¦ ¦ ¦ констант модуля. Постоянные данные¦ ¦ ¦ всегда являются ближними (NEAR) и¦ ¦ ¦ эквивалентны инициализированным дан-¦ ¦ ¦ ным. ¦ ¦ ¦ ¦ +-------------------------+-------------------------------------+ ¦ .CONST ¦ Эквивалентна директиве CONST. До-¦ ¦ UDATASEG ¦ пускается только для режима MASM.¦ ¦ ¦ Начинает или продолжает ближний или¦ ¦ ¦ не инициализируемый по умолчанию¦ ¦ ¦ сегмент данных. Соблюдайте осторож-¦ ¦ ¦ ность и включайте в этот сегмент¦ ¦ ¦ только неинициализированные данные,¦ ¦ ¦ в противном случае получаемая выпол-¦ ¦ ¦ няемая программа будет иметь больший¦ ¦ ¦ чем нужно размер. Описание распреде-¦ ¦ ¦ ления неинициализированных данных¦ ¦ ¦ можно найти в Главе 12. ¦ ¦ ¦ ¦ +-------------------------+-------------------------------------+ ¦ .DATA? ¦ Эквивалентна директиве UDATASEG.¦ ¦ ¦ Действует только для режима MASM. ¦ ¦ ¦ ¦ +-------------------------+-------------------------------------+ ¦ STACK [размер] ¦ Начинает или продолжает сегмент ¦ ¦ ¦ стека модуля. Необязательный пара-¦ ¦ ¦ метр "размер" определяет объем ре-¦ ¦ ¦ зервируемой для стека памяти (в сло-¦ ¦ ¦ вах). Если вы не задаете размер,¦ ¦ ¦ Турбо Ассемблер резервирует по умол-¦ ¦ ¦ чанию 200h слов (1 килобайт). ¦ ¦ ¦ ¦ ¦ ¦ В режиме MASM все метки, код или¦ ¦ ¦ данные, следующие за оператором¦ ¦ ¦ STACK, не будут рассматриваться как¦ ¦ ¦ часть сегмента стека. Однако в режи-¦ ¦ ¦ ме Ideal резервируется специальная¦ ¦ ¦ область, и сегмент стека остается¦ ¦ ¦ открытым, благодаря чему вы можете¦ ¦ ¦ добавлять метки и другие неинициали-¦ ¦ ¦ зированные данные. ¦ ¦ ¦ ¦ ¦ ¦ Директивы стека обычно требуется ис-¦ ¦ ¦ пользовать, если вы пишете на языке¦ ¦ ¦ Ассемблера автономную программу.¦ ¦ ¦ Большинство языков высокого уровня¦ ¦ ¦ сами создают для вас стек. ¦ ¦ ¦ ¦ +-------------------------+-------------------------------------+ ¦ .STACK [размер] ¦ Эквивалентна директиве STACK. Дей-¦ ¦ ¦ ствует в режиме MASM. ¦ ¦ ¦ ¦ +-------------------------+-------------------------------------+ ¦ FARDATE [имя] ¦ Начинает или продолжает дальний не-¦ ¦ ¦ инициализированный сегмент данных¦ ¦ ¦ (FAR) с заданным именем. Если вы не¦ ¦ ¦ задаете имя, Турбо Ассемблер исполь-¦ ¦ ¦ зует сегментное имя FAR_DATA. В мо-¦ ¦ ¦ дуле может содержаться более одного¦ ¦ ¦ неинициализированного сегмента дан-¦ ¦ ¦ ных типа FAR. ¦ ¦ ¦ ¦ +-------------------------+-------------------------------------+ ¦ .FARDATA [имя] ¦ Эквивалентна FARDATA. Действует в¦ ¦ ¦ режиме MASM. ¦ ¦ ¦ ¦ +-------------------------+-------------------------------------+ ¦ UFARDATA ¦ Начинает или продолжает дальний не-¦ ¦ ¦ инициализированный сегмент данных с¦ ¦ ¦ заданным именем. Если вы не задаете¦ ¦ ¦ имя, то Турбо Ассемблер использует¦ ¦ ¦ имя сегмента FAR_BSS. В модуле у вас¦ ¦ ¦ может быть несколько неинициализиро-¦ ¦ ¦ ванных сегментов данных типа FAR. ¦ ¦ ¦ ¦ +-------------------------+-------------------------------------+ ¦ .FARDATA? [имя] ¦ Эквивалентна UFARDATA. Действует¦ ¦ ¦ только в режиме MASM. ¦ L-------------------------+--------------------------------------
Примечание: Если вам требуется знать фактические име- на, имена классов и выравнивание сегментов, создаваемых по упрощенным директивам сегментации, см. Приложение A.
(Ошибка, сгенерированная пользователем)
Ошибка выдана в результате выполнения одной из директив ге- нерирования ошибки. Например:
.ERR ; попадание в это место является ошибкой
USES has no effect without language (USES игнорируется без спецификации языка)
Это предупреждающее сообщение выдается, если оператор USES используется без предварительной спецификации языка.
Следующие директивы обеспечивают выполнение условного ас- семблирования или генерацию ошибки на основе текущего прохода Ас- семблера:
----------------------T-----------------------------------------¬ ¦ Директива IFxxx ¦ ассемблирует "тело_условия_true", если:¦ +---------------------+-----------------------------------------+ ¦ IF1 ¦ Турбо Ассемблер выполняет первый проход.¦ ¦ IF2 ¦ Турбо Ассемблер выполняет второй проход.¦ L---------------------+------------------------------------------
----------------------T-----------------------------------------¬ ¦ Директива ERRxxx ¦ генерирует ошибку user error, если: ¦ +---------------------+-----------------------------------------+ ¦ ERRIF1 ¦ Турбо Ассемблер выполняет первый проход.¦ ¦ ¦ ¦ ¦ .ERR1 ¦ Турбо Ассемблер выполняет первый проход¦ ¦ ¦ (только для режима MASM). ¦ ¦ ¦ ¦ ¦ ERRIF2 ¦ Турбо Ассемблер выполняет второй проход.¦ ¦ ¦ ¦ ¦ .ERR2 ¦ Турбо Ассемблер выполняет второй проход¦ ¦ ¦ (только для режима MASM). ¦ L---------------------+------------------------------------------
Обычно Турбо Ассемблер работает как однопроходный ассемблер. Если вы используете средство многопроходной работы Турбо Ассемб- лера (вызывая его с параметром командной строки /m), то при не- обходимости используется несколько проходов.
Поскольку Турбо Ассемблер всегда выполняет по крайней мере один проход, директива условного ассемблирования IF1 всегда будет ассемблировать код своего условного блока, а директивы .ERR1 и ERRIF1 всегда будут генерировать сообщение об ошибке (но только на первом проходе).
Если вы используете любую из этих директив и не разрешаете многопроходную работу, то Турбо Ассемблер будет генерировать для всех таких директив предупреждение "Pass dependent construction" ("Конструкция, зависящая от прохода"), чтобы предупредить вас о возможно опасном пропуске кода. Если вы разрешите многопроходную работу, Турбо Ассемблер будет выполнять точно два прохода и гене- рировать предупреждение Vaximum compatibility pass was done (Вы- полнен проход с целью обеспечения максимальной совместимости).
Эти директивы обеспечивают условное ассемблирование или ге- нерацию сообщения об ошибке на основе того, является ли опреде- ленным один или более идентификаторов. Данные идентификаторы объ- единены в выражение с идентификаторами.
Выражение с идентификаторами - это выражение, состоящее из имен идентификаторов, булевских операций AND, OR, NOT и круглых скобок. В выражении с идентификаторами каждое имя идентификатора интерпретируется как булевское значение, при вычислении которого получается значение true, если идентификатор существует (опреде- лен), или false, если идентификатор не существует (даже если он определяется в модуле позднее). Турбо Ассемблер комбинирует эти значения, используя булевские операции, для получения конечного значения true или false. В своей простейшей форме выражение с идентификаторами содержит имя единственного идентификатора и дает при вычислении значение true, если этот идентификатор определен. Синтаксические правила в выражении с идентификаторами аналогичны тем, которые используются в выражениях Турбо Ассемблера. Напри- мер, если идентификатор foo определен, а идентификатор bar - нет, то при вычислении выражения с идентификаторами получаются следую- щие результаты:
Вычисление определенных и неопределенных идентификаторов
Таблица 15.3 ------------------------------------T---------------------------¬ ¦ Выражение с идентификаторами ¦ Результат ¦ +-----------------------------------+---------------------------+ ¦ foo ¦ True ¦ ¦ ¦ ¦ ¦ bar ¦ False ¦ ¦ ¦ ¦ ¦ not foo ¦ False ¦ ¦ ¦ ¦ ¦ not bar ¦ True ¦ ¦ ¦ ¦ ¦ foo OR bar ¦ True ¦ ¦ ¦ ¦ ¦ foo AND bar ¦ False ¦ ¦ ¦ ¦ ¦ NOT (foo AND bar) ¦ True ¦ ¦ ¦ ¦ ¦ NOT foo OR NOT bar ¦ True (то же, что ¦ ¦ ¦ (NOT foo) OR (NOT bar) ¦ L-----------------------------------+----------------------------
В следующей таблице показаны директивы, которые управляют ассемблированием и используют выражение с идентификаторами:
Директивы, использующие выражение с идентификаторами Таблица 15.4 -------------------------T--------------------------------------¬ ¦Директива IFxxx ¦ Ассемблирует "тело_условия_true" если¦ +------------------------+--------------------------------------+ ¦IFDEF выражение_ид ¦ при вычислении выражения получается¦ ¦ ¦ значение true. ¦ ¦ ¦ ¦ ¦IFNDEF выражение_ид ¦ при вычислении выражения получается¦ ¦ ¦ значение false. ¦ ¦ ¦ ¦ ¦ELSEIFDEF выражение_ид ¦ при вычислении выражения получается¦ ¦ ¦ значение true. ¦ ¦ ¦ ¦ ¦ELSEIFNDEF выражение_ид ¦ при вычислении выражения получается¦ ¦ ¦ значение false. ¦ L------------------------+---------------------------------------
Эти директивы условное ассемблирование или генерацию сообще- ний об ошибке на основе содержимого текстовой строки. Текстовой строкой может быть либо строка, заключенная в угловые скобки (<>), либо имя текстовой макрокоманды с предшествующим символом %. Например:
<ABC> ; текстовая строка ABC %foo ; содержимое текстовой макрокоманды foo
Примечание: Об определении текстовых макрокоманд и ра- боте с ними рассказывается в Главе 14.
Директивы условного ассемблирования, использующие текстовую строку, показаны в следующей таблице:
Директивы условного ассемблирования, использующие текстовую строку Таблица 15.6 -----------------------T----------------------------------------¬ ¦ Директива IFxxx ¦ ассемблирует "тело_условия_true", если:¦ +----------------------+----------------------------------------+ ¦ IFNB текст_строка ¦ "текст_строка" не состоит из одних про-¦ ¦ ¦ белов. ¦ ¦ ¦ ¦ ¦ IFB текст_строка ¦ "текст_строка" не пуста. ¦ ¦ ¦ ¦ ¦ IFIDN текст_строка_1,¦ "текст_строка_1" и "текст_строка_2" ¦ ¦ текст_строка_2 ¦ идентичны. ¦ ¦ ¦ ¦ ¦ IFINDI текст_строка_1¦ "текст_строка_1" и "текст_строка_2" ¦ ¦ ,текст_строка_2 ¦ идентичны (регистр символов не учиты- ¦ ¦ ¦ вается. ¦ ¦ ¦ ¦ ¦ IFDIF текст_строка_1,¦ "текст_строка_1" и "текст_строка_2" ¦ ¦ текст_строка_2 ¦ различны. ¦ ¦ ¦ ¦ ¦ IFDEFI текст_строка_1¦ "текст_строка_1" и "текст_строка_2" ¦ ¦ ,текст_строка_2 ¦ различны (регистр символов игнорирует- ¦ ¦ ¦ ся. ¦ ¦ ¦ ¦ ¦ ELSEIFNB текст_строка¦ "текст_строка" не состоит из пробелов. ¦ ¦ ¦ ¦ ¦ ELSEIFB текст_строка ¦ "текст_строка" не пуста. ¦ ¦ ¦ ¦ ¦ ELSEIFIDN текст_стро-¦ "текст_строка_1" и "текст_строка_2" ¦ ¦ ка_1, текст_строка_2¦ идентичны. ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ELSEIDNI текст_стро- ¦ "текст_строка_1" и "текст_строка_2" ¦ ¦ ка_1,текст_строка_2 ¦ идентичны (регистр символов игнориру- ¦ ¦ ¦ ется). ¦ ¦ ¦ ¦ ¦ ELSEIFDIF текст_стро-¦ "текст_строка_1" и "текст_строка_2" ¦ ¦ ка_1,текст_строка_2 ¦ различны. ¦ ¦ ¦ ¦ ¦ ELSEIFDIFI текст_стро¦ "текст_строка_1" и "текст_строка_2" ¦ ¦ -ка_1,текст_строка_2¦ различны (регистр символов игнориру- ¦ ¦ ¦ ется). ¦ L----------------------+-----------------------------------------
Эти директивы обеспечивают условное ассемблирование или ге- нерацию сообщений об ошибке на основе результатов вычисления в Турбо Ассемблере выражения. Во всех этих директивах при вычисле- нии выражения должна получаться константа, и оно не может содер- жать опережающих ссылок. Если при вычислении выражения получается 0, Турбо Ассемблер рассматривает выражение, как ложное (false). в противном случае оно рассматривается как истинное (true).
В следующей таблице показаны директивы условного ассемблиро- вания, использующие выражения.
Директивы условного ассемблирования, использующие сообщения Таблица 15.1 ----------------------T-----------------------------------------¬ ¦ Директива IFxxx ¦ Ассемблирует "тело_условия_true" если: ¦ +---------------------+-----------------------------------------+ ¦ IF выражение ¦ при вычислении выражения получается ¦ ¦ ¦ значение true. ¦ ¦ ¦ ¦ ¦ IFE выражение ¦ при вычислении выражения получается ¦ ¦ ¦ значение false. ¦ ¦ ¦ ¦ ¦ ELSEIF выражение ¦ при вычислении выражения получается ¦ ¦ ¦ значение true. ¦ ¦ ¦ ¦ ¦ ELSEIFE выражение ¦ при вычислении выражения получается ¦ ¦ ¦ значение false. ¦ L---------------------+------------------------------------------
В следующей таблице показаны директивы генерации сообщений об ошибке, в которых используются выражения:
Директивы генерации сообщений об ошибке, использующие выражения
Таблица. 15.2 ---------------------T------------------------------------------¬ ¦ Директива ERRxxx ¦ Генерируется сообщение user error, если: ¦ +--------------------+------------------------------------------+ ¦ ERRIF выражение ¦ при вычислении выражения получается зна- ¦ ¦ ¦ чение true. ¦ ¦ ¦ ¦ ¦ .ERRNZ выражение ¦ при вычислении выражения получается зна- ¦ ¦ ¦ чение true (только в режиме MASM). ¦ ¦ ¦ ¦ ¦ ERRIFE выражение ¦ при вычислении выражения получается зна- ¦ ¦ ¦ чение false. ¦ ¦ ¦ ¦ ¦ .ERRE выражение ¦ при вычислении выражения получается зна- ¦ ¦ ¦ чение false (только в режиме MASM). ¦ L--------------------+-------------------------------------------
Перед тем, как познакомиться с программированием на Турбо Ассемблере, вам нужно сделать следующее. Возьмите дистрибутивные диски Турбо Ассемблера и сделайте для каждого из них (с помощью утилиты DOS) рабочую копию. После этого исходные (дистрибутивные) диски уберите в надежное место.
Если собираетесь использовать Турбо Ассемблер вместо MASM (макроассемблер фирмы Microsoft), прочитайте Главу 2 и посмотри- те, в чем поведение Турбо Ассемблера отличается от MASM.
На диске INSTALL находится программа INSTALL.EXE, которая поможет вам установить Турбо Ассемблер версии 3.0 в вашей систе- ме. При установке следует учесть два параметра:
1. Hard Disk Users (пользователям системы с жестким диском): этот параметр позволяет выбрать подкаталоги, в которые будут загружены файлы.
2. Floppy Disk Users (пользователям системы с гибкими диска- ми): этот параметр установит файлы, необходимые для рабо- ты Турбо Ассемблера, в системе с двумя дисководами для гибких дисков. До начала работы подготовьте четыре отфор- матированных диска. Для начала установки перейдите в каталог с программой INSTALL и наберите команду:
INSTALL
Вам будут даны инструкции относительно каждого приглашения в рамке в нижней части экрана установки.
При запуске INSTALL в системе портативного компьютера или в любой другой системе с жидкокристаллическим дисплеем запуск INSTALL следует выполнять с параметром /b, который позволяет пе- ревести систему в черно-белый режим:
INSTALL /b
В Турбо Паскале имеются средства, обеспечивающие устранение неиспользуемого кода. Это означает, что в полученный в результате файл .EXE не будет включаться код процедур и функций, который ни- когда не выполняется. Но поскольку нет полной информации о содер- жимом модулей Турбо Ассемблера, Турбо Паскаль может выполнять для них только ограниченную оптимизацию.
Турбо Паскаль будет устранять код модуля .OBJ в том и только в том случае, если к любой доступной процедуре или функции этого модуля нет обращения. Если же на какую либо процедуру или функцию имеется ссылка, то весь этот модуль используется.
Чтобы добиться большей эффективности использования средства Турбо Паскаля по устранению неиспользуемого кода, неплохо было бы разбить программу на Ассемблере на небольшие модули, которые со- держали бы только несколько процедур или функций. Это позволило бы Турбо Паскалю, если он может это сделать, уменьшить объем ва- шей конечной программы.
Модули Си и С++ в программе обычно совместно используют оп- ределение типов и структур данных. Это делается с помощью включения небольших файлов (файлов-заголовков), которые содержат определения типов и структуры данных, используемые в нескольких модулях. Файл заголовка в Си/С++ имеет обычно имя с расширением .H. Ассемблируемые модули обычно имеют файлы заголовков с расшире- нием .ASH (или .INC).
Программы, содержащие модули, написанные на Си/С++ и модули Турбо Ассемблера, должны иметь возможность совместного определе- ния типов и структур данных. Этому способствует утилита H2ASH.
Утилита H2ASH преобразует файлы заголовков Си/С++ в файлы заголовков языка Ассемблера. Как и исходные файлы с расширением .H полученные в результате файлы с расширением .ASH сами не со- держат программу. Если для вызова H2ASH вы используете следующий синтаксис:
H2ASH [[параметры] <имя_файла> [<имя_файла> .]]
где каждое поле "имя_файла" задает имя конвертируемого файла за- головка. Утилита H2ASH предполагает, что преобразуемый файл имеет по умолчанию расширение .H. Для каждого обрабатываемого файла со- ответствующий выходной файл имеет расширение .ASH.
"Параметры" соответствуют параметрам командной строки компи- лятора Borland C++, а также специфическим параметрам утилиты H2ASH (которые соответствуют параметрам -q Турбо Ассемблера). См. "Руководство пользователя Bоrland C++" и оперативный справочник, где можно найти описания данных параметров.
Утилита H2ASH преобразует следующие конструкции:
- все основные типы языка Си;
- типы ENUM (в типы ENUM TASM);
- #IFDEF (в эквивалентные IFDEF Ассемблера);
- #DEFINE (в определения EQU);
- структуры и объединения (в структуры и объединения Турбо Ассемблера);
- структуры с битовыми полями (в записи Ассемблера RECORD);
- определения TYPEDEF (в TYPEDEF Ассемблера);
- классы без множественного наследования и без виртуальных базовых классов;
- элементы классов;
- переопределения операций.
Утилита-преобразователь имеет следующие ограничения:
(Значение константы превышает допустимое значение)
Константа представляет собой, вообще говоря, число правиль- ного формата. Однако ее значение превышает допустимую в данном конкретном случае величину. Например:
DB 400
В программировании первой программой традиционно является программа, выводящая на экран сообщение "Привет!". Не будет иск- лючением и наша программа, поскольку это является хорошей отправ- ной точкой.
Войдите в текстовый редактор (один из тех редакторов, кото- рые формируют файлы в коде ASCII) и введите следующие строки программы под названием HELLO.ASM:
.MODEL SMALL .STACK 100h .DATA Message DB 'Привет!',13,10,'$' .CODE mov ax,@Data mov ds,ax ; установить регистр DS таким ; образом, чтобы он указывал ; на сегмент данных mov ah,9 ; функция DOS вывода строки mov dx,OFFSET Message ; ссылка на сообщение "Привет!" int 21h ; вывести "Привет!" на экран mov ah,4ch ; функция DOS завершения ; программы int 21h ; завершить программу END
После того, как вы введете эту программу, сохраните ее на диске.
Если вы знакомы с языками Си, С++ или Паскаль, вам может по- казаться, что эта версия программы несколько длинновата. Это действительно так, программы на Ассемблере длиннее, поскольку каждая инструкция Ассемблера выполняет меньше функций, чем инс- трукция Паскаля, С++ или языка Си. С другой стороны, вам предос- тавляется свобода, и вы можете комбинировать эти инструкции Ас- семблера так, как захотите. Это означает, что в отличие от языков Си и Паскаль, Ассемблер позволяет вам программировать компьютер таким образом, что он будет делать все, на что способен. Часто это стоит нескольких дополнительных строк.
Теперь вы готовы к тому, чтобы ввести и запустить программу, которая действительно что-то делает. Вернитесь в текстовый редак- тор и введите следующую программу REVERSE.ASM:
.MODEL SMALL .STACK 100h .DATA MAXIMUM_STRING_LENGTH EQU 1000 StringToReverse DB MAXIMUM_STRING_LENGTH DUP (?) ReverseString DB MAXIMUM_STRING_LENGTH DUP (?) .CODE mov ax,@Data mov ds,ax ; установить регистр DS таким ; образом, чтобы он указывал mov ah,3fh ; функция DOS чтения ввода mov bx,0 ; описатель стандартного ввода mov cx,MAXIMUM_STRING_LENGTH ; считать до максималь- ; ного числа символов mov dx,OFFSET StringToReverse ; сохранить строку int 21h ; получить строку and ax,ax ; были считаны символы? jz Done ; нет, конец mov cx,ax ; поместить длину строки в ; регистр СХ, который можно ; использовать, как счетчик push cx ; сохранить в стеке длину ; строки mov bx,OFFSET StringToReverse mov si,OFFSET ReverseString add si,cx dec si ; указывает на конец буфера ; строки ReverseLoop: mov al,[bx] ; получить следующий символ mov [si],al ; сохранить символы в ; обратном порядке inc bx ; указатель на следующий ; символ dec si ; указатель на предыдущую ; ячейку buffer loop ReverseLoop ; переместить следующий ; символ, если он имеется pop cx ; извлечь длину строки mov ax,40h ; функция записи DOS mov bx,1 ; описатель стандартного ; вывода mov dx,OFFSET ReverceString ; напечатать строку Done: mov ah,4ch ; функция DOS завершения ; программы int 21h ; завершить программу END
Скоро вы увидите, что сможет делать эта программа. Для нача- ла не забудьте ее сохранить (под именем REVERSE.ASM).
Параметры-значения вещественного типа (real) передаются, как 6 байт в стеке (в Турбо Паскале это тип представляет собой 6-бай- товый программно-эмулируемый тип с плавающей точкой). Это единс- твенный тип, превышающий 4 байта, который может передаваться че- рез стек.
В том случае, когда вы знаете, что ваш исходный файл будет всегда использовать подпрограммы заданной библиотеки, можно ис- пользовать директиву INCLUDELIB. Директива INCLUDELIB сообщает компоновщику, что нужно включить указанную библиотеку. В режиме Ideal эта директива имеет следующий синтаксис:
INCLUDELIB "имя_файла" ; обратите внимание на кавычки!
а в режиме MASM:
INCLUDELIB имя_файла
где "имя_файла" - это имя библиотеки, которую вы хотите включать с помощью компоновщика на этапе компоновки. Если вы не укажете в заданном имени файла расширение, то компоновщик подразумевает расширение .LIB.
Приведем пример:
INCLUDELIB "diskio" ; включает DISKIO.LIB
Назад | Содержание | Вперед
В особенно сложных макрокомандах иногда желательно поместить в теле макрокоманды комментарии, которые не должны включаться при ее расширении. Это также уменьшает объем необходимой Турбо Ас- семблеру для обработки макрокоманд памяти. Для этого используйте комментарий с предшествующей двойной точкой запятой (в начале строки). Например, следующее тело макрокоманды:
;; Это макрокоманда с комментарием DB 'макрокоманда с комментарием'
приведет к включению при ее вызове только следующего текста:
DB 'макрокоманда с комментарием'
Примечание: Комментарии с одиночной точкой с запятой при вызове макрокоманды всегда включаются в макрорасшире- ние.