Препроцессор команд ХММ-расширения
Центральное место в макроопределении ХММ1 d_st_f3 занимают команда целочисленного устройства (в данном случае – CMPXCHG) и директива ORG. Первое действие данной макрокоманды – выяснить тип операнда приемника (dst) в макрокоманде MOVSS, так как он может быть и регистром, и ячейкой памяти. Это необходимо для правильного определения кода операции, которая будет управлять направлением потока данных. После того как определен приемник данных, с помощью условного перехода осуществляется переход на ветвь программы, где будет выполняться собственно формирование соответствующего ХММ-команде MOVSS кода операции.
Формирование кода операции ХММ-команды MOVSS производится с помощью директивы org, которая предназначена для изменения значения счетчика адреса. В строках 6 или 11 директива org устанавливает значение счетчика адреса равным адресу метки х. Адрес метки х является адресом первого байта машинного кода команды CMPXCHG. Директива db в следующих строках размещает по этому адресу байтовые значения 0F3H,0Fh, ор&_ld или 0F3H,0Fh, op&st, в зависимости от того, какое действие производится – загрузка (_ld) или сохранение (_st). Значение opc_Movss, с помощью которого формируются значения op&_st и ор&_ld, определены в начале файла iaxmm.inc:
opcjtovssjd – 010Н opc_Movss_st – 011H
Для дотошных читателей заметим еще один характерный момент. Для его полного понимания необходимо хорошо представлять себе формат машинной команды и назначение его полей. Достаточно полная информация об этом приведена в литературе. Обратите внимание на порядок следования операндов в заголовке макрокоманды, который построен по обычной для команд ассемблера схеме: коп назначение, источник.
В команде CMPXCHG порядок обратный. Этого требует синтаксис команды. Это хорошо поясняет назначение бита d во втором байте кода операции, который характеризует направление передачи данных в микропроцессор (то есть в регистр) или в память (из микропроцессора (регистра)). Вы можете провести эксперимент. Проанализируйте машинные коды команды MOV:
- Команды с непосредственным операндом: MPPS RXMM1. RXMM2/ml28, 18 CMPSS RXMM1, RXMM2/m32 .i8
- Однооперандные команды: FXRSTOR m512 FXSAVE m512 LDMXCSR m32 STMXCSR m32
Из перечисленных выше групп команд можно вывести следующую обобщенную структуру команды:
метка: код_операции операнд1. операнд2, операнд3; текст комментария
Данная структура почти совпадает со структурой обычных команд ассемблера. В соответствии с общими принципами трансляции препроцессор будет работать с исходной программой в несколько этапов.
- Лексический анализ (сканирование) исходного текста.
- Синтаксический анализ.
- Генерация кода.
Необходимо отметить, что по принципу действия разрабатываемый нами препроцессор относится к интерпретаторам. Читатель наверняка понимает, в чем состоит разница между интерпретатором и компилятором. Объект для работы компилятора – исходный текст программы в полном объеме. Выход компилятора – объектный модуль, то есть машинное представление исходной программы, пригодное для компоновки с другими модулями или получения исполняемого модуля.
Интерпретатор работает с отдельными строками исходной программы. Распознав синтаксическую правильность строки, интерпретатор исполняет ее. В частности, интерпретация характерна для обработки входных строк командного процессора. Поэтому на примере данной задачи читатель может научиться достаточно профессионально организовывать языковое взаимодействие с пользователями своих программ.
В главе 2 описаны основные шаги разработки компилятора. Для интерпретатора разница невелика, в чем мы убедимся ниже.
Для распознавания лексем входной программы разработаем сканер, следуя для этого следующему алгоритму.
- Выделить классы лексем.
- Определить классы литер.
- Определить условия выхода из сканера для каждого класса лексем.
- Каждому классу лексем поставить в соответствие грамматику класса 3.
- Для каждой грамматики, построенной на шаге 4, построить конечный автомат, который будет распознавать лексему данного класса.
- Выполнить объединение ("склеивание") конечных автоматов для всех классов лексем.
- Составить матрицу переходов для "склеенного" конечного автомата.
- "Навесить" семантику на дуги "склеенного" конечного автомата.
- Выбрать коды лексической свертки для терминалов грамматики и формат таблицы идентификаторов.
- Разработать программу сканера.