Turbo Assembler 3.0. Руководство пользователя

         

Extra characters on line


(Лишние символы в строке)

Выражение имеет корректный синтаксис, однако вслед за ним, на той же строке имеются еще лишние символы. Например:

ABC = 4 shl 3 3 ; нет знака операции ; между двумя тройками

Данная ошибка обычно является следствием другой ошибки, в результате которой анализатор выражений преждевременно заканчива- ет обработку выражения.



Файл H2ASH.TSM


-----------------------------------------------------------------

Данный файл содержит подробную информацию об утилите-преоб- разователе файлов .h в .ahs. Краткое описание этой утилиты можно найти в Приложении D.



Файл HELPME!.TSM


На установочной дискете содержится также файл HELPME!.TSM. В нем можно найти ответы на вопросы, с которыми обычно сталкиваются пользователи. Он содержит также вопросы и ответы, касающиеся раз- личных режимов Турбо Ассемблера.



Файл README


Перед тем, как начать работу с Турбо Ассемблером, не за- будьте прочесть файл README. В нем находится последняя информация о программе, а также исправления и/или дополнения к руководствам. Там вы также найдете полный список всех поставляемых на дистрибу- тивных дисках файлов и их описания. В ответ на подсказку DOS вве- дите:

README

Вы можете также использовать программу README для чтения файлов документации (с расширением .DOC)





Файл TCREF.TSM


-----------------------------------------------------------------

В данном файле описывается использование для создании перек- рестных ссылок идентфикаторов и идентификации использующих их мо- дулей утилиты TCREF.



Файлы конфигурации


Турбо Ассемблер позволяет вам также поместить наиболее часто используемые параметры в файл конфигурации в текущем каталоге. Таким образом, когда вы запускаете Турбо Ассемблер, он будет в текущем каталоге искать файл TASM.CFG. При работе в операционной системе DOS 3.x и старше поиск будет также выполняться в катало- ге, из которого был загружен TASM или TASMX. Если Турбо Ассемблер находит этот файл, то он будет интерпретировать его, как косвен- ный файл, и обрабатывать его в командной строке первым.

Это может оказаться полезным, когда вы формируете "проект" программы, и все файлы проекта находятся в одном каталоге. При этом вы хотите, например, всегда выполнять ассемблирование с ис- пользованием эмулирования инструкций с плавающей точкой (пара- метр /E). Для этого вы можете поместить параметр в файл TASM.CFG, после чего его не нужно будет задавать каждый раз при запуске Турбо Ассемблера.

Содержимое файла конфигурации имеет тот же формат, что и косвенный файл. Этот файл может содержать любую допустимую в ко- мандной строке информацию и содержать столько строк, сколько не- обходимо. Параметры обрабатываются так, как если бы они содержа- лись на одной строке.

Содержимое файла конфигурации обрабатывается до всех других аргументов командной строки. Это позволяет вам отменить любой па- раметр, заданный в файле конфигурации, просто указав в командной строке параметр, который имеет противоположное действие. Напри- мер, если ваш файл конфигурации содержит параметры:

/A /E

и вы вызываете Турбо Ассемблер командой:

TASM /S /R MYFILE

где MYFILE - файл вашей программы, то ассемблирование будет вы- полнено с последовательным упорядочиванием сегментов (/S) и ре- альными инструкциями с плавающей точкой (/R), хотя в файле конфи- гурации содержатся директивы /A и /E, задающие упорядочивание сегментов по алфавитному порядку и эмулирование инструкций с пла- вающей точкой.

Назад | Содержание | Вперед



File not found


(Не найден файл)

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



File was changed or deleted while assembly in progress


(Файл был изменен или уничтожен в процессе ассемблирования)

Какая-либо другая программа, например, резидентная активизи- руемая утилита, уничтожила открытый Турбо Ассемблером файл. В Турбо Ассемблере не допускается повторное открытие файла, который был ранее успешно открыт.



Формат фирмы Microsoft для двоичных чисел с плавающей точкой


В ранних версиях макроассемблера MASM для чисел с плавающей точкой по умолчанию использовался формат, несовместимый с форма- том для чисел с плавающей точкой стандарта IEEE. В MASM версии 5.1 числа с плавающей точкой генерируются в формате IEEE, но име- ется директива .MSFLOAT, с помощью которой можно специфицировать использование ранее использовавшегося формата фирмы Microsoft.

В Турбо Ассемблере не поддерживается старый формат чисел с плавающей точкой и, следовательно, .MSFLOAT является для него не- допустимой директивой.

Назад | Содержание | Вперед



Формат листинга


В верхней части каждой страницы листинга выводится заголо- вок, содержащий версию Турбо Ассемблера, с помощью которой выпол- нено ассемблирование файла, дату и время ассемблирования и номер страницы в листинге.

Файл листинга содержит две части: аннотированный листинг ис- ходного кода и таблицу идентификаторов. Сначала выводится исход- ный ассемблируемый код с заголовком, содержащим имя файла, в ко- тором находится исходный код. Вывод исходного кода Ассемблера сопровождается информацией о машинном коде, который ассемблирует Турбо Ассемблер. Все ошибки или предупреждения, обнаруженные в процессе ассемблирования, включаются в листинг непосредственно за содержащей ошибку строкой.

Строки кода в файле листинга имеет следующий формат:

<глубина> <номер_строки> <смещение> <машинный_код> <исходный_код>

где <глубина> показывает уровень вложенности включаемых файлов или макрокоманд в файле листинга.

Поле <номер_строки> содержит номер строки в файле листинга (не включая заголовки). Номера строк особенно полезны при исполь- зовании перекрестных ссылок Турбо Ассемблера, в которых указыва- ются номер строк. Учтите, что поле <номер_строки> не соответству- ет номерам строк исходного модуля. Например, если в файл включается другой файл или выполняется макрорасширение, то значе- ние поля <номер_строки> продолжает увеличиваться, хотя текущая строка в исходном файле остается той же. Чтобы преобразовать но- мер строки обратно в строку исходного кода, вы должны найти стро- ку в файле листинга, и найти такую же строку в исходном коде (по ее внешнему виду, а не по номеру).

Поле <смещение> представляет смещение в текущем сегменте на- чала машинного кода, сгенерированного из соответствующей исходной строки Турбо Ассемблером.

Поле <машинный_код> показывает фактическую последователь- ность шестнадцатиричных значений размером в байт или слово, кото- рые ассемблированы из соответствующей исходной строки на Ассемб- лере.

Поле <исходный_код> - это просто исходная строка Ассемблера, с комментариями и всем, что в ней содержится. Некоторые исходные строки (например те, которые содержат только комментарии) не ге- нерируют никакого машинного кода. Эти строки не содержат полей <смещение> и <машинный_код>, но имеют номер строки.



Forward reference needs override


(Ошибка при использовании умолчания для ссылки вперед)

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

ASSUME cs:DATA call A ; по умолчанию - ближний вызов A PROC FAR ; а здесь переопределяется как дальний mov ax,MEMVAR ; не известно, что требуется другой сегмент DATA SEGMENT MEMVAR DW ? ; здесь ошибка: требуется переопределение

Эти ошибки исправляются путем явного указания сегмента или типа перехода FAR.



Начало работы на Турбо Ассемблере


Если вы никогда ранее не программировали на языке Ассембле- ра, то начните с данной главы. Возможно вам приходилось слышать, что программирование на Ассемблере - это дело темное, доступное только посвященным и мудрецам. Не верьте этому. Язык Ассемблера - это не более чем человеческая форма языка самого компьютера, а он, как и можно было предположить, в высшей степени логичен. Как вы можете также догадаться, язык Ассемблера - это очень мощный язык. Фактически, программирование на Ассемблере представляет со- бой единственный способ реализации всего спектра возможностей процессоров серии 80х86 фирмы Intel, являющихся "сердцем" всех компьютеров семейства IBM PC и совместимых с ними компьютеров.

Вы можете писать программы целиком на языке Ассемблера или, если захотите, использовать язык Ассемблера в программах, напи- санных на Турбо С++, Турбо Паскале и других языках. В любом слу- чае с помощью языка Ассемблера вы сможете разрабатывать компакт- ные и быстрые программы. Наряду со скоростью большое значение в программе на языке Ассемблера имеет также возможность управления всеми аспектами работы компьютера, до последнего такта системного таймера.

В данной главе вы познакомитесь с языком Ассемблера и опро- буете уникальные свойства программирования на нем. Сначала вы введете и запустите несколько работающих программ, написанных на Ассемблере. Это даст вам возможность как почувствовать сам язык, так и познакомиться с работой на Ассемблере.

Разумеется, мы не сможем при помощи этих нескольких глав сделать вас крупным специалистом по программированию на языке Ас- семблера; мы просто дадим вам введение в язык Ассемблера и помо- жем написать первые программы. Мы очень надеемся, что у вас есть хотя бы одна из множества замечательных книг, полностью посвящен- ных программированию на языке ассемблера и архитектуре PC (см. ссылки на литературу в конце данной книги). Кроме того, полезные справочные материалы содержатся в "Техническом справочнике по IBM DOS", "Техническом справочнике по интерфейсу BIOS" и "Техническом справочнике по персональным компьютерам XT"; в этих руководствах документируется интерфейс при программировании на языке ассембле- ра с программным и аппаратным обеспечением системы персональных компьютеров IBM.

Вы можете следовать данному руководству поэтапно, вводя все примеры программ по мере их изучения, либо можете распаковать на- ходящийся на диске файл с примерами (во время установки Турбо Ас- семблера) и иметь все эти программы под рукой. (Независимо от ва- шего решения, имена программ приводятся для удобства в самом начале примеров этих программ).



Использование директив и параметров


Данная глава познакомит вас с необязательными параметрами командной строки Турбо Ассемблера. Мы опишем каждый параметр ко- мандной строки, который вы можете использовать для того, чтобы изменить поведение Ассемблера, и покажем, как и где используются командные файлы. Наконец, мы опишем также файл конфигурации и то, как можно управлять выводом предупреждающих сообщений и сообщений об ошибках.



Общие принципы программирования


Данная глава знакомит вас с основными принципами Турбо Ассемблера. Мы сравним режимы Турбо Ассемблера Ideal и MASM, рассмотрим, как можно комментировать программы и продолжать стро- ки исходного кода, использовать включаемые файлы, предопределен- ные идентификаторы и как использовать некоторые директивы, гене- рирующие информацию для модулей. Хотя диапазон охваченным тем велик, это даст вам хорошее представление о том, что собой предс- тавляет язык ассемблера.



Объектно-ориентированное программирование


Объектно-ориентированное программирование - это подход к разработке программного обеспечения, основанный на объектах, а не на процедурах. Этот подход позволяет максимизировать принципы мо- дульности и "сокрытия информации". Объектно-ориентированное прог- раммирование базируется на связывании или инкапсуляции структур данных и процедуры, которая работает с данными в структуре, с мо- дулем.

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

Если вы не имеете большого опыта работы с Турбо Ассемблером, то можете пропустить данную главу, но вернитесь к ней позднее, после того, как прочтете другие главы руководства. Мы включили здесь эту главу, чтобы вы имели представление о данных средствах, на объектно-ориентированное представление в Турбо Ассемблере на самом деле представляет собой достаточно продвинутую тему. Она будет иметь больший смысл, когда вы изучите остальные главы руко- водства.



Использование выражений и значений идентификаторов


Выражение и идентификаторы - это основные компоненты прог- раммы на языка Ассемблера. Выражения используются для вычисления значений и адресов в памяти. Идентификаторы представляют различ- ные виды значений. В данной главе описываются различные типы этих компонентов языка и рассказывается о том, как их использовать.



Директивы выбора процессора и идентификаторы процессора


Процессор 8086 представляет собой на самом деле только один из процессоров семейства iAPx86. Это семейство включает в себя:

- процессор 8088 (который содержит 8-разрядную шину данных), 8086 (содержит 16-разрядную шину данных);

- процессоры 80186 и 80188 (аналогичны процессорам 8086 и 8088, но содержат дополнительные инструкции и работают быстрее своих предшественников);

- процессор 80286 (который содержит инструкции защищенного режима);

- процессор 80386 (который может обрабатывать 16- и 32-раз- рядные данные);

- процессор 80486 (улучшенная версия процессора 80386, кото- рая отличается более высокой скоростью работы).

Математические сопроцессоры, такие как 8087, 80287 и 80387, работающие с процессорами семейства iAPx86, позволяют выполнять операции с плавающей точкой.

В Турбо Ассемблере предусмотрены директивы и предопределен- ные идентификаторы, которые позволяют вам использовать инструкции конкретного процессора. Эти директивы и идентификаторы описывают- ся в данной главе.



Использование моделей памяти программы и сегментации


Каждый процессор семейства 80х86 имеет не менее 4 сегментных регистров (CS, DS, ES и SS). Эти регистры содержат значение сег- мента, которое описывает физический блок памяти объемом до 64К (или до 4 гигабайт в процессоре 80386 и старше). Все адреса вы- числяются с использованием в качестве базового значения одного из сегментных регистров.

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

Операционная система или среда программы определяет, работа- ет программа в реальном или защищенном режиме. Если вы используе- те защищенный режим процессоров 80386 или 80486, то операционная система определяет также, допустимы ли большие сегменты (до 4 ги- габайт). Турбо Ассемблер в одинаковой степени поддерживает все эти операционные среды.

В случае общей модели 80х86 программы состоят из одного или более сегментов, где каждый сегмент представляет собой физически различные части кода или данных (или код и данные), к которым можно обращаться через сегментный регистр. На основе этой общей схемы можно построить много производных схем. Чтобы упорядочить их, разработаны стандартные схемы памяти. Так как этих соглашений придерживаются многие языки высокого уровня, в программах на Ас- семблере также следует это делать.

Один из очевидных способов состоит в разбиении программы на инструкции программы и ее данные. Каждый фрагмент данных програм- мы можно определить как инициализированный (содержащий начальные значения, например, текстовое сообщение) и неинициализированный (не содержащий начального значения). Турбо Ассемблер обычно прис- ваивает неинициализированным данным отдельный сегмент, который можно разместить в конце программы, уменьшив объем выполняемой программы.

Обычно достаточно большую часть неинициализированных данных занимает стек. Он также специализирован, так как регистры SS и SP при выполнении программы инициализируются обычно автоматически областью стека. Таким образом, в стандартных моделях памяти стек инициализируется, как отдельный сегмент.

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

В данной главе описывается, как использовать в вашей прог- рамме модели и сегменты, и какие директивы позволяют это делать.



Определение типов данных


Символьное определение типов данных помогает вам писать мо- дульный код. Отделяя определения типа данных от того кода, в ко- тором он используется, вы можете легко изменять или расширять структуры данных без необходимости переписывать код. Это позволя- ет также организовать символьный доступ к типу данных и его ком- понентам.

Турбо Ассемблер определяет столько же символьных типов дан- ных, сколько поддерживается в языках высокого уровня. В данной главе описывается, как можно определить различные типы данных.



Задание и использование счетчика адреса


Счетчик адреса отслеживает при ассемблировании исходного файла текущий адрес. Это позволяет вам в любой момент в процессе ассемблирования программа знать, где вы находитесь. Турбо Ассемб- лер предоставляет директивы, которые позволяют работать со счет- чиком адреса и помещать в него нужно значение адреса.

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

В данной главе описываются имеющиеся директивы, которые ис- пользуются для работы со счетчиком адреса и описания метод по те- кущему адресу.



Описание процедур


Турбо Ассемблер позволяет вам описывать процедуры нескольки- ми способами. В данной главе описываются процедуры NEAR и FAR, объявление языка процедур, использование в процедурах аргументов и переменных, сохранение регистров, вложенные процедуры и описа- ние процедур методов для объектов.



Управление областью действия идентификаторов


В Турбо Ассемблере и большинстве других языков программиро- вания идентификатор в зависимости от того, где он находится в мо- дуле, может иметь разное значение. Например, некоторые идентификаторы могут иметь одно и то же значение во всем модуле, а другие определены только для конкретной процедуры.

Под областью действия понимается диапазон строк, в котором идентификатор имеет определенное значение. Для разработки прог- рамм, использующих принципы модульного программирования, правиль- ное задание области действия идентификатора имеет важное значе- ние. Управляя областью действия идентификатора, вы можете управлять его использованием. Кроме того, правильный выбор облас- ти действия идентификатора может устранить проблемы, возникающие при многократном определении идентификатора с одним и тем же име- нем.



Определение данных


Директивы определения данных используются для выделения байт в сегменте. Вы можете также использовать их для заполнения этих байт начальными данными и определения переменных данных.

Все директивы определения данных имеют некоторые общие средства. Во первых они могут генерировать инициализированные данные и резервировать место для неинициализированных данных. Для инициализированных данных определяется некоторое начальное значе- ние. Неинициализированные данные определяются без задания началь- ного значения (говорят, что их начальное значение является неоп- ределенным). В директивах определения данных неинициализированные данные указываются с помощью символа ?. Все прочее должно предс- тавлять значение инициализированных данных. О том, как следует различать инициализированные и неинициализированные данные, расс- казывается в Главе 7.

Другим средством, которое применяется во всех директивах определения данных, является использование для указания повторе- ния блока данных ключевого слова DUP. Приведем общий синтаксис всех директив распределения данных:

[имя_директивы [выражение_dup [выражение_dup.]]

Турбо Ассемблер инициализирует "имя" таким образом, чтобы оно указывало на резервируемую директивой область. Тип данной пе- ременной зависит от фактически используемой директивы.

Каждое "выражение_dup" может иметь следующий синтаксис:

- ?;

- значение;

- выражение_счетчик DUP( выражение_dup[,выражение_dup.]);

где "выражение_счетчик" задает, сколько раз будет повторяться блок данных. "Выражение_счетчик" не может быть относительным и иметь опережающие ссылки.

Если вы хотите получить неинициализированные данные, исполь- зуйте идентификатор ?. Объем резервируемой для неиницализирован- ных данных памяти зависит от фактически используемой директивы.

"Значение" предназначено для фактического описания отдельно- го элемента данных в каждой директиве. В некоторых директивах поле значения может быть очень сложным и содержать много элемен- тов, другие могут потребовать только простого выражения.

В следующем примере используется директива DW, которая выде- ляет слова:

DW 2 DUP (3 DUP (1,3),5) ; эквивалентно директиве ; DS 1,3,1,3,1,35,1,3,1,3,1,3,5



Расширенные инструкции


Турбо Ассемблер распознает все стандартные мнемоники инс- трукций Intel, применимые к текущему выбранному процессору. Дан- ная глава представляет собой обзор этих инструкций. Подробный перечень данных инструкций вы можете найти в кратком справочном руководстве.



Использование макрокоманд


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



Использование условных директив


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

Директивы условного ассемблирования позволяют вам генериро- вать во время ассемблирования сообщения об ошибках при наступле- нии определенных событий. Турбо Ассемблер выводит сообщение об ошибке на экран и в файл листинга и предотвращает создание объек- тного файла. В данной главе описывается, как можно использовать имеющиеся условные директивы.



Интерфейс с компоновщиком


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



Генерация листинга


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

Примечание: См. в Главе 2 описание параметров команд- ной строки /l и /la.

Турбо Ассемблер может также по запросу генерировать таблицу перекрестных ссылок для всех меток, используемых в исходном фай- ле, в которой показано, где определяется каждая метка, и где на нее имеется ссылка.

Примечание: См. в Главе 2 описание параметра командной строки /c.



Интерфейс Турбо Ассемблера и Borland C++


Хотя некоторые программисты могут разрабатывать программы целиком на языке Ассемблера (и делают это), другие предпочитают писать основную часть программы на языке высокого уровня, обраща- ясь к языку Ассемблера только для осуществления управления нижне- го уровня, или когда требуется высокая производительность. Неко- торые предпочитают писать преимущественно на Ассемблере, только иногда используя конструкции и библиотечные средства языков высо- кого уровня.

Данная глава объясняет использование Турбо Ассемблера с ком- пиляторами С++. В этой главе они называются компиляторами семейс- тва Borland С++. Однако Турбо Ассемблер можно использовать также с Турбо C++ и Турбо Си. Приводимая ниже таблица содержит перечень компиляторов этого семейства.

Компиляторы Borland С++ и Си Таблица 18.1 ---------------------T------------------------------------------¬ ¦ Название продукта ¦ Имя файла компилятора ¦ +--------------------+------------------------------------------+ ¦ Borland С++ ¦ bcc.exe, bccx.exe, bc.exe или bcx.exe ¦ ¦ Турбо C++ ¦ tcc.exe или tc.exe ¦ ¦ Турбо Cи ¦ tcc.exe ¦ L--------------------+-------------------------------------------

Например, если мы говорим, чтобы вы выполнили компиляцию строкой:

bcc -S plusone.cpp

а вы работаете с Турбо С++, то вместо нее вы можете ввести следу- ющую командную строку:

tcc -S plusone.cpp

Если при интерфейсе с Турбо Ассемблером вы используете Турбо Си, то вы ограничены использованием только компилятора командной строки. В случае же Borland С++ и Турбо С++ вы можете работать как с компиляторами командной строки, так и с компилятором интег- рированной среды.

Borland C++ дает хорошие возможности поддержки смешанного программирования на С++ и на языке Ассемблера на произвольной ос- нове и предоставляет не один, а целых три механизма объединения модулей на Ассемблере и на С++. Имеющееся в С++ средство встроен- ного ассемблирования позволяет быстро и просто вставить текст на языке Ассемблера прямо в функцию С++. Вы можете выполнить ассемб- лирование встроенного кода при помощи Турбо Ассемблера или встро- енного Ассемблера Borland С++. Те, кто предпочитает держать ас- семблерные части программы в отдельных модулях, написанных цели- ком на языке Ассемблера, может ассемблировать их при помощи Турбо Ассемблера и затем скомпоновать с модулями Borland С++.

Сначала мы рассмотрим использование встроенного в Borland C++ Ассемблера. Далее мы подробно обсудим компоновку отдельно ас- семблированных в Турбо Ассемблере модулей с Borland C++ и иссле- дуем процесс вызова функций, написанных с помощью Турбо Ассембле- ра, из программы, созданной в Borland C++. И наконец, мы рассмот- рим вызов функций Borland C++ из программы на Турбо Ассемблере.



Интерфейс Турбо Ассемблера с Турбо Паскалем


В Турбо Ассемблере предусмотрены расширенные и мощные средства, позволяющие вам добавлять код Ассемблера к программам Турбо Паскаля. В данной главе мы подробно расскажем вам о том, что нужно знать, чтобы полностью использовать данные средства, приведем множество примеров и дадим некоторую более глубокую ин- формацию.

Большинство программ, которые вы захотите написать, можно реализовать целиком на Турбо Паскале. В отличие от большинства других компиляторов Паскаля, Турбо Паскаль позволяет вам с по- мощью массивов Port[], Mem[], MemW[] и MemL[] непосредственно об- ращаться ко всем ресурсам компьютера, а с помощью процедур Intr() и MsDos() вы можете обращаться к базовой системе ввода-вы- вода (BIOS) и операционной системе.

Для чего же тогда может потребоваться использовать совместно с Турбо Паскалем Ассемблер? Для этого существуют две вероятные причины: выполнение некоторого небольшого числа операций, которые непосредственно в Турбо Паскале недоступны, и использование преи- муществ высокой скорости работы, которые дает Ассемблер. (Сам Турбо Паскаль работает достаточно быстро, потому что он написан на языке Ассемблера.) В данной главе мы покажем вам, как можно использовать в Турбо Паскале преимущества Ассемблера.



Global type doesn't match symbol type


(Тип, указанный в директиве GLOBAL не совпадает с действи- тельным типом имени идентификатора)

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



Грамматика выражений в режиме Ideal


Синтаксис начинается, как id_выражение.

id_выражение ::=

указатель

i_тип ::= UNKNOWN BYTE WORD DWORD FWORD QWORD PWORD TBYTE SHORT NEAR FAR PROC DATAPTR CODEPTR имя_структуры имя_таблицы имя_перечисления имя_записи TYPE указатель

указатель ::= SMALL указатель ; если 386 LARGE указатель ; если 386 i_тип PTR указатель i_тип LOW указатель i_тип HIGH указатель i_тип указатель указатель_2

указатель_2 ::= указатель_3.идентификатор (Операция выбора элемента структуры) указатель_3

указатель_3 ::= выражение:указатель_3 выражение

выражение ::= SYMTYPE выражение (Операция определения типа символическо- го имени) выражение_2

выражение_2 ::= выражение_3 OR выражение_3. выражение_3 ХOR выражение_3. выражение_3

выражение_3 ::= выражение_4 AND выражение_4. выражение_4

выражение_4 ::= NOT выражение_4 выражение_5

выражение_5 ::= выражение_6 ЕQ выражение_6. выражение_6 NE выражение_6. выражение_6 LT выражение_6. выражение_6 LE выражение_6. выражение_6 GT выражение_6. выражение_6 GE выражение_6. выражение_6

выражение_6 ::= выражение_7 + выражение_7. выражение_7 - выражение_7. выражение_7

выражение_7 ::= выражение_8 * выражение_8. выражение_8 / выражение_8. выражение_8 MOD выражение_8. выражение_8 SHR выражение_8. выражение_8 SHL выражение_8. выражение_8

выражение_8 +выражение_8 -выражение_8 выражение_9

выражение_9 HIGH выражение_9 LOW выражение_9 выражение_10

выражение_10 OFFSET указатель SEG указатель SIZE идентификатор LENGTH идентификатор WIDTH идентификатор MASK идентификатор THIS идентификатор идентификатор константа ( указатель ) [ указатель ] (Всегда означает "содержимое")



Грамматика выражений в режиме MASM


Синтаксис выражений начинается как MASM_выражение.

MASM_выражение ::= выражение_1

м_выражение_1 ::= SHORT м_выражение_1 .TYPE м_выражение_1 SMALL м_выражение_1 (преобразование в 16-битовое смещение [только для процессора 386]) LARGE м_выражение_1 (преобразование в 32-битовое смещение [только для процессора 386]) м_выражение_2

м_выражение_2 ::= м_выражение_3 OR м_выражение_3. м_выражение_3 ХOR м_выражение_3. м_выражение_3

м_выражение_3 ::= м_выражение_4 AND м_выражение_4. м_выражение_4

м_выражение_4 ::= NOT м_выражение_4 м_выражение_5

м_выражение_5 ::= м_выражение_6 'EQ' м_выражение_6. м_выражение_6 'NE' м_выражение_6. м_выражение_6 'LT' м_выражение_6. м_выражение_6 'LE' м_выражение_6. м_выражение_6 'GT' м_выражение_6. м_выражение_6 'GE' м_выражение_6. м_выражение_6

м_выражение_6 ::= м_выражение_7 '+' м_выражение_7. м_выражение_7 '-' м_выражение_7. м_выражение_7

м_выражение_7 ::= м_выражение_8 '*' м_выражение_8. м_выражение_8 '/' м_выражение_8. м_выражение_8 'MOD' м_выражение_8. м_выражение_8 'SHR' м_выражение_8. м_выражение_8 'SHL' м_выражение_8. м_выражение_8

м_выражение_8 ::= + выражение_8 - выражение_8 выражение_12

м_выражение_10 ::= OFFSET указатель SEG указатель SIZE идентификатор LENGTH идентификатор WIDTH идентификатор MASK идентификатор THIS цел_тип идентификатор ( указатель ) [ указатель ]

м_выражение_10 ::= м_выражение_11 PTR м_выражение_10 м_выражение_11 OFFSET м_выражение_10 SEG м_выражение_10 LOW м_выражение_10 HIGH м_выражение_10 TYPE м_выражение_10 THIS м_выражение_10

м_выражение_11 ::= м_выражение_8 : м_выражение_8.

м_выражение_12 ::= м_выражение_13 [м_выражение_13.(подразумеваемое сложение, только если есть '[' или '(') м_выражение_13 (м_выражение_13.(подразумеваемое сложение, только если есть '[' или '(') м_выражение_13'.'м_выражение_10

м_выражение_13 ::= LENGTH идентификатор SIZE идентификатор WIDTH идентификатор MASK идентификатор ( м_выражение_1 ) [ м_выражение_1 ] м_выражение_10



ID not member of structure


(Идентификатор не является полем структуры)

В режиме Ideal после точки (селектора поля структуры) указа- но имя идентификатора, которое не является именем поля структуры. Например:

IDEAL STRUC DEMO DB ? ENDS COUNT DW 0 mov ax,[(DEMO bx).COUNT] ; COUNT не является ; полем структуры

После точки может быть указано только имя поля той структу- ры, имя которой указано перед точкой.

Данная ошибка обычно является следствием другой ошибки, в результате которой анализатор выражений преждевременно заканчива- ет обработку выражения.



Идентификатор @32Bit


Идентификатор @32Bit содержит значение, определяющее, явля- ются ли сегменты в текущей модели 16- или 32-разрядными. Если вы задали в модели MODEL 16-разрядные сегменты, то это значение рав- но 0, а если 32-разрядные - то 1.



Идентификатор @CodeSize


Идентификатор @CodeSize указывает используемый по умолчанию размер указателя кода в текущей модели памяти. Если он установлен в 0, то модели памяти используют ближние указатели кода типа NEAR (модeли TINY, SMALL, FLAT, COMPACT, TPASCAL), а значение 1 указы- вает, что модели памяти используют дальние указатели FAR (все другие модели).



Идентификатор @Cpu


Функция: Числовое значение, возвращающее информацию о теку- щем процессоре.

Замечания: Значение, возвращаемое @Cpu, дает в битовых полях информацию о типе процессора:

------------T--------------------------------------¬ ¦ Бит ¦ Описание ¦ +-----------+--------------------------------------+ ¦ 0 ¦ Разрешены инструкции процессора ¦ ¦ ¦ 8086. ¦ ¦ ¦ ¦ ¦ 1 ¦ Разрешены инструкции процессора ¦ ¦ ¦ 80186. ¦ ¦ ¦ ¦ ¦ 2 ¦ Разрешены инструкции процессора ¦ ¦ ¦ 80286. ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ 3 ¦ Разрешены инструкции процессора ¦ ¦ ¦ 80386. ¦ ¦ ¦ ¦ ¦ 4 ¦ Разрешены инструкции процессора ¦ ¦ ¦ i486. ¦ ¦ ¦ ¦ ¦ 7 ¦ Разрешены привилегированные ¦ ¦ ¦ инструкции процессоров (80286, ¦ ¦ ¦ 386, 486). ¦ ¦ ¦ ¦ ¦ 8 ¦ Разрешены инструкции математи- ¦ ¦ ¦ ческого сопроцессора 8087. ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ 10 ¦ Разрешены инструкции математи- ¦ ¦ ¦ ческого сопроцессора 80287. ¦ ¦ ¦ ¦ ¦ 11 ¦ Разрешены инструкции математи- ¦ ¦ ¦ ческого сопроцессора 80387. ¦ L-----------+---------------------------------------

Не определенные здесь биты зарезервированы для будущего ис- пользования. При использовании идентификатора @Cpu замаскируйте их, это обеспечит совместимость вашей программы с будущими верси- ями Турбо Ассемблера.

Так как семейство процессоров 8086 совместимо снизу-вверх, то когда вы разрешаете тип процессора по директиве .286, автома- тически разрешаются также младшие типы сопроцессоров (8086, 80186).

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

Пример:

IPUSH = @Cpu AND 2 ; разрешает непосредственную ; инструкцию push процессора ; 186 и старше IF IPUSH PUSH 1234 ELSE mov ax,1234 push ax ENDIF



Идентификатор @DataSize


Идентификатор @DataSize указывает используемый по умолчанию размер указателя данных в текущей модели памяти. Если он установ- лен в 0, то модели памяти используют ближние указатели данных ти- па NEAR (модeли TINY, SMALL, FLAT, COMPACT, TPASCAL), а значение 1 указывает, что модели памяти используют дальние указатели FAR (все другие модели).



Идентификатор @Interface


Идентификатор @Interface дает информацию о языке и операци- онной системе, которые выбраны в операторе MODEL. Данная тексто- вая макрокоманда содержит число, биты которого представляют сле- дующие значения:

Модификаторы модели Таблицы 7.3 -----------------T----------------------------------------------¬ ¦ Биты 0-7 ¦ Значение ¦ +----------------+----------------------------------------------+ ¦ 0 ¦ NOLANGUAGE ¦ ¦ 1 ¦ C ¦ ¦ 2 ¦ SYSCALL ¦ ¦ 4 ¦ PASCAL ¦ ¦ 5 ¦ FORTRAN ¦ ¦ 6 ¦ BASIC ¦ ¦ 7 ¦ PROLOG ¦ ¦ 8 ¦ CPP ¦ L----------------+-----------------------------------------------

Бит 8 имеет нулевое значение для DOS и равен 1 для OS/2.

Например, значение идентификатора @Interface показывает, что вы выбрали операционную систему OS/2 и язык Си.



Идентификатор @Model


Идентификатор @Model содержит числовое значение, представля- ющее текущую используемую модель. Вы можете задавать его как текстовую макрокоманду с одним из следующих значений:

1 = действует модель tiny (крошечная) 2 = действует модель small (малая) или flat 3 = модель compact (компактная) 4 = medium (средняя) 5 = large (большая) 6 = huge (огромная) 7 = tchuge (Турбо Си) 0 = tpascal (Турбо Паскаль)



Идентификатор счетчика адреса $


Предопределенный идентификатор $ представляет текущий счет- чик адреса. Счетчик адреса состоит из двух частей: сегмента и смещения. При ассемблировании счетчик адреса представляет собой смещение в текущем сегменте.

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

helpkMessage DB 'это справочное сообщение программы' helpLength = $ - helpMessage

Когда эти две строки ассемблируются, идентификатор helpLength равен длине справочного сообщения.



Идентификатор @Startup


Идентификатор @Startup помещается в начало кода инициализа- ции, который генерируется по директиве STARTUPCODE. Он представ- ляет собой ближнюю метку, отмечающую начало программы.



Идентификатор @WordSize


Функция: Числовое значение, указывающее 16- или 32-разрядные сегменты.

Примечания: @WordSize возвращает значение 2, если текущим сегментом является 16-разрядный сегмент, и 4, если это 32-разряд- ный сегмент.

Пример:

IF @WordSize EQ 4 mov esp,0100h ELSE mov sp,0100h ENDIF



Идентификаторы


Идентификатор представляет значение, которое может быть пе- ременной, меткой адреса или операндом ассемблируемой инструкции и директивы.



Идентификаторы, генерируемые директивой MODEL


Когда вы используете директиву MODEL, Турбо Ассемблер созда- ет и инициализирует отдельные переменные, отражающие детали выб- ранной модели. Эти переменные путем использования операторов ус- ловного ассемблирования могут вам помочь написать код, зависящий от модели. О том, как можно использовать эти переменные для изме- нения процесса ассемблирования, рассказывается в Главе 15.



Идентификаторы, определяемые расширенной директивой STRUC


Расширенная директива STRUC определяет и использует несколь- ко идентификаторов, которые отражают определяемый объект. Эти идентификаторы показаны в следующей таблице:

Идентификаторы, определяемые расширенной директивой STRUC Таблица 8.4 ---------------------------T------------------------------------¬ ¦ Идентификатор ¦ Значение ¦ +--------------------------+------------------------------------+ ¦ @Object ¦ Текстовая макрокоманда, содержащая¦ ¦ ¦ текущий объект. ¦ ¦ ¦ ¦ ¦ @Table_<имя_объекта> ¦ Табличный тип данных, содержащий¦ ¦ ¦ таблицу методов объекта. ¦ ¦ ¦ ¦ ¦ @Tableaddr_<имя_объекта>¦ Метка, описывающая адрес таблицы¦ ¦ ¦ виртуальных методов объекта. ¦ L--------------------------+-------------------------------------

Назад | Содержание | Вперед



Идентификаторы, создаваемые упрощенными директивами сегментации


Когда вы используете упрощенные директивы определения сег- ментов, они создают переменные, отражающие детали распределения сегмента (аналогично тому, как это делает директива MODEL). Под- робнее об этом рассказывается в Главе 15.

Идентификаторы упрощенных директив сегментации Таблица 7.5 ----------------------------T-----------------------------------¬ ¦ Идентификатор ¦ Значение ¦ +---------------------------+-----------------------------------+ ¦ @code ¦ Сегмент или группа, которые подра-¦ ¦ ¦ зумеваются для сегмента CS. ¦ ¦ ¦ ¦ ¦ @data ¦ Сегмент или группа, которые подра-¦ ¦ ¦ зумеваются для сегмента DS. ¦ ¦ ¦ ¦ ¦ @fardata ¦ Имя текущего сегмента FARDATA. ¦ ¦ ¦ ¦ ¦ @fardata? ¦ Имя текущего сегмента UFARDATA. ¦ ¦ ¦ ¦ ¦ @curseg ¦ Имя текущего сегмента. ¦ ¦ ¦ ¦ ¦ @stack ¦ Сегмент или группа, которые подра-¦ ¦ ¦ зумеваются для сегмента SS. ¦ L---------------------------+------------------------------------



Идентификаторы в выражениях


Когда вы используете в выражении идентификатор, возвращаемое значение зависит от типа идентификатора. Вы можете использовать идентификатор сам по себе или в сочетании с определенными унарны- ми операциями, которые созданы для выделения другой информации из величины, представляемой идентификатором.



Illegal forward reference


(Недопустимая ссылка вперед)

Имя идентификатора, на которое происходит ссылка, еще не бы- ло определено, а в соответствующей директиве не допускается ис- пользовать ссылки вперед. Например:

IF MYSYM ; ошибка: MYSYM еще не определена ; ENDIF MYSYM EQU 1

Ссылки вперед нельзя использовать в директивах вида IFxxx, а также в качестве счетчика выражений в операции DUP.



Illegal immediate


(Недопустим непосредственный операнд)

Команда содержит непосредственный операнд (т.е. константу) там, где он недопустим. Например:

mov 4,al



Illegal indexing mode


(Недопустимый режим индексации)

Команда содержит операнд, использующий недопустимую комбина- цию регистров. Например:

mov al,[si+ax]

Для всех процессоров, за исключением 80386, допустимыми ком- бинациями индексных регистров являются следующие: BX, BP, SI, DI, BX+SI, BX+DI, BP+SI, BP+DI.



Illegal instruction


(Недопустимая команда)

Строка исходной программы начинается с имени идентификатора, которое не является ни именем директивы, ни мнемоникой команды. Например:

move ax,4 ; должно быть "MOV"