Реклама:

В этом подразделе мы подробно обсудим ассемблер/компоновщик as88, который вместе с трассером поставляется на сопроводительном компакт-диске и имеется также на веб-сайте, посвященном книге. Этот ассемблер, входящий в набор АСК (Amsterdam Compiler Kit), больше похож на ассемблеры UNIX, чем на аналогичные продукты для MS-DOS и Windows. Символом комментария в нем является знак восклицания (!). Все символы, следующие за знаком восклицания вплоть до конца строки, считаются комментарием и не влияют на объектный файл. Пустые строки допустимы, но при формировании объектного файла не учитываются.

В ассемблере имеются три секции, в которых хранятся транслируемый код и данные. Разделение на секции соответствует сегментации памяти. Первая секция, секция текста, предназначена для хранения команд процессора. Следующая секция, секция данных, служит для инициализации памяти в сегменте данных, который к началу процесса становится известен. Последняя секция, секция BSS (Block Started by Symbol - блок с начальным символом), нужна для резервирования памяти в неинициализированном (точнее говоря, в инициализированном нулем) сегменте данных. В каждой из трех секций есть собственный счетчик адресов. Секции задумывались для того, чтобы ассемблер мог сгенерировать несколько команд, затем перейти к данным, затем вернуться к командам, потом снова к данным, и т. д., а компоновщик, в свою очередь, мог скомпоновать все эти блоки так, чтобы все команды оказались вместе в текстовом сегменте, а все слова данных - в сегменте данных. Результат обработки любой отдельно взятой строки на языке ассемблера попадает только в одну из секций, хотя строки кода и строки данных могут чередоваться. В период выполнения секция текста хранится в текстовом сегменте, а секции данных и BSS - последовательно в сегменте данных.

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

CMP АХ,ABC JE L

MOV AX.XYZ

L:

Здесь L - метка, связанная со следующей командой или словом. Метки бывают двух видов. Во-первых, существуют глобальные метки, представляющие собой буквенно-цифровые идентификаторы, после которых ставится двоеточие (:). Такие метки должны быть уникальными; они не могут совпадать с ключевыми словами и мнемоническими кодами команд. Во-вторых, в секции текста встречаются локальные метки, каждая из которых состоит из одной цифры с последующим двоеточием (:). Локальная метка может устанавливаться многократно. Например:

JE 2f

Эта команда означает операцию перехода JUMP EQUAL вперед до следующей локальной метки 2. Аналогично:

jne 4Ь

Эта команда означает операцию перехода JUMP NOT EQUAL назад к ближайшей локальной метке 4.

Ассемблер допускает присвоение константам символических имен в рамках синтаксической конструкции идентификатор = выражение

Здесь идентификатор является буквенно-цифровой строкой, как в следующем примере:

BLOCKSIZE = 1024

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

Численные значения могут быть восьмеричными (в таком случае они начинаются с нуля), десятеричными или шестнадцатеричными (начинаются с символов ОХ или Ох). В шестнадцатеричном представлении буквы а-£ и А-Б обозначают значения от 10 до 15. Целочисленные операторы +,-,*,/ и % выражают сложение, вычитание, умножение, деление и остаток о деления, соответственно. Логические операторы &, * и ~ обозначают поразрядное И, поразрядное ИЛИ и логическое отрицание (НЕ), соответственно. Для группировки в выражениях могут устанавливаться квадратные скобки. Во избежание путаницы круглые скобки в выражениях не используются (оставлены для задания режимов адресации).

К меткам в составе выражений следует относиться с осторожностью. Вычитание меток команд из меток данных недопустимо. Разность между однородными метками выражается в численных значениях, однако ни сами метки, ни их разности не могут выступать в качестве констант в мультипликативных и логических выражениях. Выражения, разрешенные к применению в определениях констант, могут быть задействованы в виде констант в командах процессора. В некоторых процессорах предусмотрены макросредства, позволяющие группировать множества команд и присваивать таким группам имена, но в аэ88 этой возможности нет.

В каждом языке ассемблера есть директивы, которые влияют на процесс ассемблирования, но не транслируются в двоичный код. Они называются псевдокомандами. Псевдокоманды ассемблера аэ88 перечислены в табл. В.5.

Таблица В.5. Псевдокоманды ассемблера ав88

Псевдокоманда Описание

.SECT .TEXT

Ассемблирование следующих строк в секции текста

.SECT.DATA

Ассемблирование следующих строк в секции данных

.SECT .BSS

Ассемблирование следующих строк в секции BSS

.BYTE

Ассемблирование аргументов в виде последовательности байтов

.WORD

Ассемблирование аргументов в виде последовательности слов

.LONG

Ассемблирование аргументов в виде последовательности длинных слов

.ASCII "str"

Сохранение строки str в виде ASCII-строки без завершающего нулевого

 

байта

.ASCIZ "str"

Сохранение строки str в виде ASCII-строки с завершающим нулевым

 

байтом

.SPACE n

Продвижение счетчика адресов на п позиций

.ALIGN n

Продвижение счетчика адресов до n-байтной границы

.EXTERN

Объявление идентификатора внешним

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

Во втором блоке псевдокоманд содержатся указатели типов данных в сегменте данных. Таких типов всего четыре: .BYTE, .WORD, .LONG и строка. В первых трех типах после необязательной метки и ключевого слова псевдокоманды остаток строки занимает список константных выражений с разделением запятыми. Для строк предусмотрено два ключевых слова: ASCII и ASCIZ. Единственное различие между ними заключается в том, что ключевое слово ASCIZ добавляет к концу строки нулевой байт. Оба ключевых слова в обязательном порядке сопровождаются строкой, заключенной в двойные кавычки. В определениях строк допускается ряд символов-заменителей, которые перечислены в табл. В.6. Вдобавок к ним любой конкретный символ может предваряться обратной косой чертой и выражаться своим восьмеричным представлением, например, \377 (максимальное число символов - три, 0 в данном случае указывать не требуется).

Таблица В.6. Некоторые разрешенные в as88 символы-заменители

Символ-заменитель Описание

\п

Новая строка (перевод строки)

\t

Табуляция

\\

Обратная косая черта

Пробел

V

Подача страницы

V

Возврат каретки

V

Двойная кавычка

Псевдокоманда SPACE увеличивает значение указателя адресов на число байтов, определенное аргументами. Это ключевое слово может быть особенно полезным, если установить его после метки в секции BSS в целях резервирования памяти для переменной. Ключевое слово ALIGN позволяет продвинуть указатель адресов до первой 2-, 4- или 8-байтной границы в памяти, что упрощает ассемблирование слов, двойных слов и т. д. с размещением в подходящих ячейках памяти. Наконец, ключевое слово EXTERN объявляет о доступности указанной программы или ячейки памяти для компоновщика с целью установки внешних ссылок. Определение не обязательно должно находиться в текущем файле; оно может быть в любом месте в пределах досягаемости компоновщика.

Следует сделать ряд замечаний касательно совместного применения ассемблера и трассера. Ассемблер воспринимает ключевые слова как в верхнем, так и в нижнем регистрах; трассер выводит их только в верхнем регистре. Ассемблер воспринимает в качестве символа новой строки символы-заменители \г (возврат каретки) и \п (перевод строки), в то время как трассер использует только последний. Ассемблер способен работать с программами, разбитыми на несколько файлов, в то время как для обработки в трассере всю программу необходимо объединить в файл с расширением .$. Включенные в него файлы запрашиваются командой

#include имя_файла

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

При наличии одного исходного файла (например, pr.s) предполагается, что именем проекта являются символы рг, а объединенный файл должен называться рг.$. Если исходных файлов несколько, основа имени первого из них принимается за имя проекта, и она же применяется для определения $-файла, который генерируется ассемблером путем объединения исходных файлов. Этот механизм можно изменить, поместив в командной строке перед первым исходным файлом флаг -о projname; в таком случае объединенный файл получает имя projname.$.

Имейте в виду, что к применению включаемых файлов и нескольких исходных файлов выдвигается ряд условий. В частности, во всех исходных файлах имена меток, переменных и констант должны быть разными. Более того, в конечном счете, в загрузочный файл ассемблируется файл projname.$, поэтому номера строк, указываемые ассемблером при обнаружении ошибок и выводе предупреждений, отсчитываются именно от этого файла. При работе с небольшими проектами имеет смысл писать программу в одном файле, а не использовать команду ^include.

Введение-a || Оглавление || Некоторые отличия от других ассемблеров 8088