Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции / Лекция 2 / Лекция 2.doc
Скачиваний:
40
Добавлен:
10.06.2015
Размер:
240.64 Кб
Скачать

Глава 5

Синтаксис ассемблера

Структура программы на ассемблере

Типы и структура предложений ассемблера

Понятие о метасинтаксических языках

Классификация лексем ассемблера

Описание простых операндов и операндов-выражений

Варианты расположения операндов команд ассемблера

Виды адресации операндов в памяти

Операторы ассемблера

Стандартные директивы сегментации

Упрощенные директивы сегментации

Простые типы данных ассемблера (диапазоны значений)

Директивы описания простых типов данных

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

Синтаксис ассемблера

Программа на ассемблере представляет собой совокупность блоков памяти, называемых сегментами. Программа может состоять из одного или нескольких таких блоков-сегментов. Сегменты программы имеют определенное назначение, соответствующее типу сегментов: кода, данных и стека. Названия типов сегментов отражают их назначение. Деление программы на сегменты отражает сегментную организацию памяти процессоров Intel (архитектура IA-32). Каждый сегмент состоит из совокупности отдельных строк, в терминах теории компиляции называемых предложениями языка. Для языка ассемблера предложения, составляющие программу, могут представлять собой синтаксические конструкции четырех типов.

Команды (инструкции) представляют собой символические аналоги машинных команд. В процессе трансляции инструкции ассемблера преобразуются в соответствующие команды системы команд процессора.

Макрокоманды — это оформляемые определенным образом предложения текста программы, замещаемые во время трансляции другими предложениями.

Директивы являются указанием транслятору ассемблера на выполнение некоторых действий. У директив нет аналогов в машинном представлении.

Комментарии содержат любые символы, в том числе и буквы русского алфавита. Комментарии игнорируются транслятором.

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

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

Как использовать синтаксические диаграммы? Очень просто: для этого нужно всего лишь найти и затем пройти путь от входа диаграммы (слева) к ее выходу (направо). Если такой путь существует, то предложение или конструкция являются синтаксически правильными. Если такого пути нет, значит, эту конструкцию компилятор не примет. Иногда на линиях в синтаксических диаграммах присутствуют стрелки. Они говорят о том, что необходимо обратить внимание на направление обхода, указываемое этими стрелками, так как среди путей могут быть и такие, по которым можно идти справа налево. По сути, синтаксические диаграммы отражают логику работы транслятора при разборе входных предложений программы. Далее перечислены термины, представленные на рисунках.

Имя метки — символьный идентификатор. Значением данного идентификатора является адрес первого байта предложения программы, которому он предшествует.

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

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

Код операции (КОП) и директива — это мнемонические обозначения соответствующей машинной команды, макрокоманды или директивы транслятора.

Операнды — части команды, макрокоманды или директивы ассемблера, обозначающие объекты, над которыми производятся действия. Операнды ассемблера описываются выражениями с числовыми и текстовыми константами, метками и идентификаторами переменных с использованием знаков операций и некоторых зарезервированных слов.

Другой способ описания синтаксиса языка - нормальные (расширенные) формы Бэкуса-Наура. С помощью форм Бэкуса-Наура целевой язык представляется в виде объектов трех типов.

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

Имена конструкций языка, в теории называемые нетерминальными символами, обычно заключаются в угловые скобки <> или пишутся строчными буквами.

Правила (формы) описывают порядок формирования конструкций, в том числе предложений, целевого языка.

Каждая форма состоит из трех частей — левой, правой и связки:

-левая часть — всегда нетерминальный символ, который обозначает одну из конструкций языка;

-связка — символ стрелки =>, который можно трактовать как словосочетание «определяется как»;

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

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

Для примера рассмотрим описание и использование форм Бэкуса-Наура для построения десятичных чисел со знаком. Вначале опишем эти формы (правила):

<десятичное_знаковое_целое>=><число_без_знака>|+<число_6ез_знака>|<число_без_ знака>

<число_без_знака>=><дес_цифра> | <число_6ез_знака_цифра>

<дес_цифра>=>0|1|2|3|4|5|6|7|8|9

Здесь:

<десятичное_знаковое_целое>,<число_без_знака>,<дес_цифра> — нетерминальные символы (в исходной программе на ассемблере таких объектов нет);

+|-|0|1|2|3|4|5|б|7|8|9 — терминальные символы (их можно найти в исходном тексте программы), из терминальные символов по приведенным ранее трем правилам строится любое десятичное число;

символ вертикальной черты (|) означает альтернативу при выборе варианта некоторого правила.

Для примера выведем число -501, используя формы Бэкуса-Наура:

<десятичное_знаковое_целое> => <число_без_знака> =>

<число_без_знака><дес_цифра> => <число_без_знака>1 =>

<число_без_знака><дес_цифра>1 => <число_без_знака>01 => <дес_цифра>01 => 501

Предложения ассемблера (см. рис. 5.1-5.3) формируются из лексем, представляющих собой синтаксически неразделимые последовательности допустимых символов языка, имеющие смысл для транслятора.

Вначале определим алфавит ассемблера, то есть допустимые для написания текста программ символы:

АSСП_символ_буква — все латинские буквы А - Z, а - z, причем прописные и строчные буквы считаются эквивалентными;

decdigit — цифры от 0 до 9;

специальные знаки _, ?, @, $, &;

разделители: „ ., [, ], (, ), <, >, {, }, +, /, *, %, !, ", ", ?, \, = #, л.

Лексемами языка ассемблера являются ключевые слова, идентификаторы, цепочки символов и целые числа.

Ключевые слова — это служебные символы языка ассемблера. По умолчанию регистр символов ключевых слов не имеет значения. К ключевым словам относятся:

названия регистров (AL, АН, BL, ВН, CL, СН, DL, ОН, АХ, ЕАХ, ВХ, ЕВХ, СХ, ЕСХ, DX, EDX, ВР, EBP, SP, ESP, DI, EDI, SI, ESI, CS, DS, ES, FS, GS, SS, CRO, CR2, CR3, DRO, DRl, DR2, DR3, DR6,DR7);

операторы (BYTE, SBYTE, WORD, SWORD, DWORD, SDWORD, FWORD, QWORD, TBYTE, REAL4, REALS, REAL10, NEAR16, NEAR32, FAR16, FAR32, AND, NOT, HIGH, LOW, HIGHWORD, LOWWORD, OFFSET, SEG, LROFFSET, TYPE, THIS, PTR, WIDTH, MASK, SIZE, SIZEOF, LENGTH, LENGTHOF, ST, SHORT, TYPE, OPATTR, MOD, NEAR, FAR, OR, XOR, EQ, NE, LT, LE, GT, GE, SHR,

названия команд (КОП) ассемблера, префиксов.

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

<id>=> А5СП_символ_буква | А5СП_символ_буква | <id> А5СП_символ_буква

<id><decdigit> | <znak> <decdigit> <id> | <znak>

<decdigit> => 0| 1 | 2 | 3 |4| 5 | 6| 7| 8| 9

<znak> => _|

Приведенные формы говорят о том, что идентификатор может состоять из одного или нескольких символов. В качестве символов можно использовать буквы латинского алфавита, цифры и некоторые специальные знаки — _, ?, $, @. Идентификатор не может начинаться символом цифры. Длина идентификатора может составлять до 255 символов (247 в MASM), хотя транслятор воспринимает лишь первые 32, а остальные игнорирует. Регулировать длину возможных идентификаторов (в TASM) можно с использованием ключа командной строки /mv. Кроме того, существует возможность указать транслятору на необходимость различать прописные и строчные буквы либо игнорировать их различие (что и делается по умолчанию). Для этого (в TASM) применяются ключи командной строки/mu, /ml,/mx.

Цепочки символов — это последовательности символов, заключенные в одинарные или двойные кавычки. Правила формирования:

<string> => <quote> [[ <stext> ]] <quote>

<stext> =» <StringChar> | <stext> <stringChar>

<stringChar> => <quote> <quote> | любой_символ_кроме_кавычки

<quote> => " | '

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

<шестнадц_число> =» <дес_шестнадц_число>h| 0<сим_шестнадц_число>h

<дес_шестнадц_число> =» <decdigi 1><сим_шестнадц_число> | <decdigi t>

<сим_шестнадц_число> =>

<hexdigi 1><сим_шестнадц_число>| <дес_шестнадц_число> | <decdigi t> | <hexdigi t>

<decdigit> => 0| 1 12 | 3|4|5 |6| 7|8|9

<hexdigit> = > a | b | c | d | e | f | A | B | C | D | E | F

Важно отметить наличие символов после (h) и перед (0) записью шестнадцатеричного числа. Это сделано для того, чтобы транслятор мог отличить в программе одинаковые по форме записи десятичные и шестнадцатеричные числа. К примеру, числа 1578 и 1578h выглядят одинаково, но имеют разные значения. С другой стороны, какое значение в тексте исходной программы может иметь лексема fe023?

Это может быть и некоторый идентификатор, и, судя по набору символов, шестнадцатеричное число. Для того чтобы однозначно описать в тексте программы на ассемблере шестнадцатеричное число, начинающееся с буквы, его дополняют ведущим нулем «0» и в конце ставят символ «h». Для данного примера правильная запись шестнадцатеричного числа - 0fe023h:

<двоичн_число> => <bindigi t>b| <bindigi 1><двоичн_число>b

<bindigit> => 0|1

Для двоичных чисел все просто — после записи нулей и единиц, входящих в их состав, необходимо поставить латинскую букву «b». Пример:

Рассуждениями, приведенными ранее, был показан порядок формирования предложений программы ассемблера и составляющих их элементов (лексем). Также были рассмотрены правила формирования меток, названий команд (префиксов). Осталось обсудить комментарии и операнды. Что касается комментария, то это самый простой элемент предложения ассемблера. Любая комбинация символов ASCII, расположенная в строке за символом точки с запятой (;), транслятором игнорируется, то есть является комментарием. Описанию операндов, ввиду их важности, будет посвящен отдельный подраздел.

Соседние файлы в папке Лекция 2