Директивы управления файлами
Директивы управления файлами позволяют управлять исходным и объектным файлами, а также листингом ассемблерной программы. Под управлением понимается указания о том, как трактовать элементы входного (исходного) файла и задание содержимого и объема вывода для выходных (объектный файл и листинг) файлов.
Управление исходным файлом
Для управления исходным файлом предназначены директивы INCLUDE, .RADIX иCOMMENT.
Директива INCLUDE имеет следующий формат:
INCLUDE имя-файла
Содержимого файла с указанным именем, трактуемое как текст, вставляется в исходный файл на место директивы INCLUDE. Имя-файла должно определять существующий файл. Имя-файла может включать в себя полную или частичную информацию о пути поиска файла. Если имя-файла не содержит информацию о местонахождении файла, поиск осуществляется в директориях, заданных опцией /I MASM, а если файл там не будет найден, то — в текущей директории. Если файл не найден, MASM выдает сообщение об ошибке.
Когда Ассемблер обнаруживает директиву INCLUDE, он открывает указанный исходный файл и начинает ассемблировать содержащиеся в нем предложения. После обработки всех предложений этого файла Ассемблер продолжает ассемблирование с предложения, непосредственно следующего за INCLUDE.
ДирективыINCLUDE могут быть вложенными. Файл, подключаемый по этой директиве, также может содержать директивыINCLUDE.
В листинге предложения из подключаемых файлов помечаются символом C.
При спецификации путей поиска файла могут использоваться символы / или \, что введено для совместимости с XENIX.
Если необходимо, чтобы местоположение подключаемых файлов задавалось динамически после формирования исходного файла, следует в директивах INCLUDE опустить спецификацию путей поиска и определять их опцией /I или установкой текущего директория.
Примеры:
INCLUDE entry
INCLUDE b:\include\record
INCLUDE /include/as/stdio
INCLUDE local\define.inc
Директива .RADIX устанавливает умалчиваемое основание чисел во входном файле и имеет формат:
RADIX выражение
В качестве выражения задается число в пределах от 2 до 16, которое определяет, в какой системе счисления трактовать числа при отсутствии явного указания. Могут быть указаны следующие значения:
u 2 — двоичная;
u 8 — 8-ричная;
u 10 — десятичная;
u 16 — 16-ричная.
Указанное в директиве .RADIXвыражение всегда трактуется как десятичное число независимо от текущего умалчиваемого основания. По умолчанию при отсутствии директивы .RADIX используется десятичная система счисления.
Директива .RADIX не влияет на числа, указанные в директивах DD, DQ иDT. Числа выражений этих директив всегда трактуются как десятичные.
Директива.RADIX не влияет на спецификаторы основания B и D, используемые при задании целых чисел. Если последним символом целого числа оказывается B или D, он трактуется как спецификатор системы счисления, а не как 16-ричная цифра, даже если умалчиваемое основание — 16. Например, число 11B будет восприниматься как двоичное 11, а не как 16-ричное 11B. Для того, чтобы оно трактовалось как 16-ричное, следует задавать 11Bh.
Примеры:
.RADIX 16
.RADIX 2
Директива COMMENT позволяет указывать Ассемблеру, что выделенный участок исходного файла следует рассматривать как комментарий.
Формат:
COMMENT ограничитель
...
текст
...
ограничитель [[текст]]
Текст, заключенный между ограничителями (которые должны совпадать), считается комментарием и ассемблированию не подлежит. В качестве ограничителя берется первый отличный от пробела символ после ключевого слова COMMENT. Ассемблер пропускает весь последующий текст до следующего вхождения такого же ограничителя. Текст комментария не должен содержать такого символа. Комментарием считается также весь текст, расположенный на той же строке, что и последний ограничитель.
Директива COMMENT обычно используется при задании комментария, занимающего много строк.
Пример:
COMMENT
* Весь текст между звездочками считается комментарием *
Управление листингом
Директивы управления листингом позволяют управлять содержимым и форматом формируемого MASM листинга ассемблерной программы.
Директива TITLE задает заголовок листинга программы, который будет печататься в начале каждой страницы листинга. Текст заголовка может включать в себя до 60 любых символов. Каждый модуль может содержать не более одной директивы TITLE. Если не использовалась директива NAME, первые 6 отличных от пробела символов заданного в TITLE заголовка рассматриваются как имя модуля.
Директива SUBTTL определяет подзаголовок листинга, который печатается в начале каждой страницы листинга на следующей строке после заголовка. Задаваемый текст представляет собой любую комбинацию символов, из которой в качестве подзаголовка используются первые 60 символов. Если текст опущен, строка подзаголовка в листинге содержит левый пробел. Программа может содержать любое количество директив SUBTTL. Каждая последующая директива замещает предыдущую.
Директивы управления листингом
Формат Функция
TITLE текст задание заголовка листинга
SUBTTL [[текст]] задание подзаголовка листинга
PAGE длина,ширина задание параметров страницы листинга
.LIST печатать листинг
.XLIST не печатать листинг
.LALL печатать все исходные предложения
.SALL подавить печать макрорасширений
.XALL печатать только код и данные
.SFCOND подавить печать условных блоков с
ложными условиями
.LFCOND печатать условные блоки с ложными
условиями
.TFCOND установить умалчиваемый режим печати
условных блоков
.CREF печатать листинг перекрестных ссылок
.XCREF [[имя,...]] подавить печать листинга перекрестных
ссылок
Директива PAGE позволяет управлять форматом страницы листинга.
В первой форме директивы предусмотрены 2 позиционных параметра, которые устанавливают максимальное число строк страницы листинга (длина) и максимальное число символов в строке листинга (ширина). Задаваемая длина должна находиться в пределах от 10 до 255 (значение по умолчанию — 50). Ширина может варьироваться от 60 до 132 (значение по умолчанию — 80). Если длина не указана, ширине, если она задана, должна предшествовать запятая.
Вторая форма директивы PAGE (со знаком +) означает, что номер секции программы должен быть увеличен, а номер страницы устанавливается равным 1. Номер страницы листинга состоит их 2-х компонент: номера секции и номера страницы внутри секции и имеет следующий вид:
секция-страница
По умолчанию нумерация страниц листинга начинается со значения 1-1.
Третья форма директивы PAGE (без аргументов) предписывает MASM перейти на новую страницу листинга.
Директива .XLIST подавляет копирование в листинг последующих строк исходной программы. Следует помнить, что обработка MASM директивы .XLIST перекрывает все предшествующие ей директивы управления листингом.
Директива .LIST восстанавливает копирование в листинг последующих строк исходной программы.
Директива .LALLсообщает MASM, что листинг должен содержать все предложения макрорасширений, если они есть, включая обычные комментарии (с предшествующей ;), но исключая макрокомментарии (с предшествующей ;;).
По директиве .XALL распечатываются только предложения макрорасширений, по которым генерируется программный код или данные. Комментарии игнорируются. Этот режим действует по умолчанию при отсутствии в исходной программе директив .LALL и .SALL.
Директива .SALL подавляет распечатку макрорасширений.
Директива .SFCOND подавляет распечатку тел всех последующих условных блоков, условия ассемблирования которых окажутся ложными.
Директива .LFCOND восстанавливает распечатку таких блоков.
Директива .TFCOND устанавливает умалчиваемый режим распечатки условных блоков. Эта директива работает в сочетании с опцией /X MASM. Если опция /X при запуске MASM не была задана, .TFCOND разрешает печать условных блоков с ложными условиями. Если же опция /X была задана, .TFCOND подавляет печать таких блоков. Каждая обработка Ассемблером директивы .TFCOND меняет режим распечатки условных блоков с ложными условиями на противоположный.
Директива.XCREF подавляет генерацию листинга перекрестных ссылок для меток, переменных и имен. Если в директиве задан список имен, из листинга перекрестных ссылок исключаются только указанные объекты, а все остальные в листинг попадают. Если список содержит более, чем одно имя, его элементы должны отделяться друг от друга запятыми.
Директива .CREF восстанавливает генерацию листинга перекрестных ссылок.
Другие директивы
В языке Ассемблере имеются еще 2 директивы, имеющие некоторое отношение к вводу/выводу. Это директивы%OUT и NAME.
Директива%OUT имеет следующий формат:
%OUT текст
При обработке Ассемблером этой директивы указанный текст выдается на системный экран. Эта директива полезна при отслеживании прохождения процесса ассемблирования через специфичные участки очень большой исходной программы.
Директива %OUT срабатывает на обоих проходах MASM. Для того, чтобы сообщение выдавалось на каком-либо одном проходе, можно использовать директивыIF1 и IF2.
Пример:
IF1
%OUT First pass
ENDIF
Сообщение будет выдано только на 1-м проходе.
Директива NAME позволяет присваивать имя текущему модулю и имеет формат:
NAME имя-модуля
Имя модуля используется программой LINK при выдаче диагностических сообщений. Имя-модуля может быть любой комбинацией букв и цифр, из которой используются только первые 6 символов. Имя должно быть уникальным и не может совпадать с ключевым словом.
При отсутствии в исходной программе директивы NAME Ассемблер создает умалчиваемое имя модуля, в качестве которого используются первые 6 символов текста, задаваемого директивой TITLE. Если же и директива TITLE опущена, модулю присваивается имя A.
Глобальные объявления
Директивы глобального объявления позволяют определять метки, переменные и абсолютные имена, доступ к которым возможен из всех сегментов программы независимо от того, как они ассемблировались.
В языке Ассемблера имеются 2 директивы глобального объявления: PUBLIC и EXTRN, которые дополняют друг друга.
Директива PUBLIC имеет следующий формат:
PUBLIC имя,...
Директива PUBLIC делает указанные в списке переменные, метки или абсолютные имена, общими, то есть, доступными всем модулям программы. Каждый элемент списка должен быть определен в текущем исходном файле. Абсолютные имена, если они указаны, должны представлять одно- или двухбайтные целые числа или строковые значения.
Обычно до копирования в объектный файл строчные буквы в общих именах преобразуются в заглавные. Для сохранения первоначального написания имен с учетом регистра могут быть использованы опции /ML и /MX MASM.
Директивой PUBLIC должны быть описаны имена, используемые при работе с SYMDEBв режиме символьной отладки.
Директива EXTRN имеет следующий формат:
EXTRN имя:тип,...
Директива EXTRN определяет внешние по отношению к текущему сегменту объекты с указанием их типа. Внешним объектом может быть переменная, метка или имя, объявленные в другом модуле программы директивой PUBLIC. Тип, указанный в директиве EXTRN, должен соответствовать действительному типу объекта и может кодироваться одним из следующих ключевых слов:
u BYTE
u WORD
u DWORD
u QWORD
u TBYTE
u NEAR
u FAR
u ABS.
Тип ABS используется при описании имен, представляющих абсолютные значения. Остальные описатели типа имеют обычный смысл.
Несмотря на то, что действительные адреса объектов до обработки объектного файла программой LINK неизвестны, Ассемблер, основываясь на местонахождении директивы EXTRN, может делать предположения о том, какой сегмент следует использовать для адресации внешнего объекта. Если директива EXTRN находится внутри какого-либо сегмента, считается, что указанные внешние объекты связаны с этим сегментом, и описывающие их директивы PUBLIC должны содержаться в сегменте с тем же именем и теми же атрибутами.
Если директива EXTRN не входит ни в один сегмент, предположений о содержащем внешний объект сегменте не делается, и соответствующая директива PUBLIC может располагаться в любом сегменте. В обоих случаях для подавления адресации внешнего объекта относительно умалчиваемого сегмента может использоваться оператор переключения сегмента (:).
Инструкции процессоров
Набор инструкций процессора представляет собой самый нижний (машинный) уровень программного обеспечения компьютера. Программирование на этом уровне представляет из себя весьма непростую задачу по той причине, что выполняемые каждой инструкцией функции довольно просты, и поэтому любая сколько-нибудь сложная программа включает в себя большое количество инструкций и обычно теряет наглядность. Кроме того, программист обязан знать многие архитектурные и функциональные особенности компьютера, о которых он может не думать при программировании на языках высокого уровня. С другой стороны, только набор машинных инструкций предоставляет программисту все возможности компьютера.
Инструкции процессора доступны пользователю через программу MASM.
Инструкции процессора в унифицированной форме обрабатывают различные типы операндов. Почти каждая инструкция может оперировать с байтом или словом на выбор. Регистры, переменные памяти (поля памяти, представленные адресами) и непосредственные операнды могут кодироваться в большинстве инструкций без ограничений, за исключением, разумеется, того, что непосредственный операнд может быть только источником, но не приемником. В частности, переменные памяти могут участвовать в операциях сложения, вычитания, сдвига, сравнения и других без предварительного помещения их в регистры, что экономит инструкции, регистры и время выполнения ассемблерной программы. Для языков высокого уровня, где большинство переменных размещено в памяти, компиляторы могут генерировать более быстродействующий и меньший по объему объектный код.
Набор инструкций процессоров можно рассматривать как состоящий из 2-х уровней:
u ассемблерный уровень;
u машинный уровень.
Ассемблерный уровень включает в себя около 100 инструкций. Например, только инструкция MOV способна пересылать содержимое регистра или ячейки памяти или непосредственное значение в регистр или ячейку памяти. Процессор распознает 28 различных инструкций для MOV (пересылка байта из регистра в память, пересылка непосредственно представленного слова в регистр).
Ассемблер транслирует написанные программистом инструкции ассемблерного уровня в инструкции машинного уровня, которые непосредственно выполняются процессором. Компиляторы языков высокого уровня транслируют предложения своего языка также в инструкции машинного уровня.
Наличие 2-х уровней инструкций направлено на удовлетворение 2-х различных требований: эффективности программы и относительной простоты программирования. Набор инструкций машинного уровня (их около 300) позволяет эффективно использовать память. Например, машинная инструкция, предназначенная для увеличения на 1 операнда памяти, занимает 3-4 байта, так как она должна содержать адрес операнда. Для наращивания регистра эта информация не нужна, и инструкция может быть короче. Если программист будет использовать одну инструкцию для наращивания регистра, другую — для операнда памяти, выгода от компактных инструкций будет сведена на нет сложностью программирования. Инструкции ассемблерного уровня с точки зрения программиста проще. Программист кодирует одну форму инструкции INC, а Ассемблер проверяет ее операнд и решает, какую генерировать машинную инструкцию.
Инструкции пересылки данных
14 инструкций этого типа обеспечивают пересылку одиночных байтов и слов между памятью и регистрами, а также между портами ввода/вывода и регистрами AL или AX. В эту группу включены также инструкции манипуляции со стеком и инструкции пересылки флагов процессора и загрузки регистров сегмента.
Все инструкции пересылки данных можно условно разделить на 4 группы:
Общего назначения
u MOV — пересылка байта или слова;
u PUSH — сохранение слова в стеке;
u POP — восстановление слова из стека;
u XCLHG — обмен байтами или словами;
u XLAT — трансляция байта.
Ввода/вывода
u IN — ввод байта или слова из порта;
u OUT — вывод байта или слова в порт.
Адресные операции
u LEA — загрузка исполнительного адреса;
u LDS — загрузка указателя с использованием DS;
u LES — загрузка указателя с использованием ES.
Пересылка флагов
u LAHF — загрузка флагов в AH;
u SAHF — установка флагов из AH;
u PUSHF — сохранение флагов в стеке;
u POPF — восстановление флагов из стека.
Все инструкции пересылки данных, кроме POPF и SAHF, значений флагов процессора не изменяют.