Сборник по задачам и примерам Assembler

     

Поддержка ХММ-команд в файле iaxmm.inc



Поддержка ХММ-команд в файле iaxmm.inc

С точки зрения структуры включаемый файл iaxmm.inc представляет собой набор макрокоманд двух типов — основных и вспомогательньях. Названия основных макрокоманд полностью совпадают с названиями ХММ-команд, и эти макрокоманды обеспечивают моделирование определенных XlMM-команд. Вспомогательные макрокоманды расположены в начале файла и предназначены для обеспечения работы основных макрокоманд. В частности, :эти макрокоманды устанавливают тип операндов, указанных при обращении к (основной макрокоманде, причем делают это исходя из режима функционировашия транслятора — 16-или 32-разрядного. Другое важное действие — установление соответствия между названиями ХММ-регистров и регистров общего назначения. Дело в том, что для моделирования ХММ-команд в 16- или 32-разрядном режиме работы ассемблера используются разные регистры общего назначения — 1 6-разрядные регистры в 16-разрядном режиме, и 32-разрядные в 32-разрядном режиме.

Рассмотрим процесс моделирования ХММ-команд. В! качестве основы для моделирования выступает команда основного процессора!. Эта команда должнаудовлетворять определенным требованиям. Каковы они? В поисках ответа посмотрим на машинные коды ХММ-команд в литературе [40, 41]. Видно, что общими у них являются два момента:

  • поле кода операции ХММ-команд состоит из двух или трех байтов, один

    из которых равен Ofh;

  • большинство ХММ-команд использует форматы адресации с байтами modR/M и sib и соответственно допускает сочетание операндов как обычных двух-операндных команд целочисленного устройства — регистр-регистр или память-регистр.
  • Для моделирования ХММ-команд нужно подобрать такую команду основного процессора, которая удовлетворяет этим двум условиям. Во включаемом файле iaxmm.inc в качестве таких команды присутствуют две — CMPXCHG и ADD. В процессе моделирования на место нужного байта кода операции этих команд помещаются байты со значениями кода операции соответствующей ХММ-команды. Когда микропроцессор «видит», что очередная команда является ХММ-командой, то он начинает трактовать коды регистров в машинной команде как коды ХММ-регистров и ссылки на память, размерностью соответствующей данной команде. В машинном формате команды нет символических названий регистров, которыми мы пользуемся при написании исходного текста программы, например АХ или ВХ. В этом формате они определенным образом кодируются. Например, регистр АХ кодируется в поле REG машинной команды как 000. Если заменить код операции команды, в которой одним из операндов является регистр АХ, на код операции некоторой ХММ-команды, то это же значение в поле reg микропроцессор будет трактовать как регистр RXMMO. Таким образом, в ХММ-командах коды регистров воспринимаются соответственно коду операции. В табл. 10.1 приведены коды регистров общего назначения и соответствующих им ХММ-регистров. В правом столбце этой таблицы содержится условное обозначение ХММ-регистров, принятое в файле iaxmm.inc. Это же соответствие закреплено рядом определений в этом файле, которые иллюстрирует следующая программа.


    DefineXMMxRegs Macro IFDEF APPJ.6BIT

    rxmmO TEXTEQU<AX>

    rxmml TEXTEQU<CX>

    rxmm2 TEXTEQU<DX>

    rxmm3 TEXTEQU<BX>



    rxmm4 TEXTEQU<SP>

    rxmm5 TEXTEQU<BP>

    гхттб TEXTEQU<SI>

    rxmm7 TEXTEQU<DI>

    RXMMO TEXTEQU<AX>

    RXMM1 TEXTEQU<CX>

    RXMM2 TEXTEQU<DX>

    RXMM3 TEXTEQU<BX>

    RXMM4 TEXTEQU<SP>

    RXMM5 TEXTEQU<BP>

    P.XMM6 TEXTEQU<SI>

    RXMM7 TEXTEQU<DI>

    rxmml TEXTEQU<ECX>

    rxmm2 TEXTEQU<EDX>

    rxmm3 TEXTEQU<EBX>

    rxmm4 TEXTEQU<ESP>

    rxmm5 TEXTEQU<EBP>

    гхттб TEXTEQU<ESI>

    ГХШП7 TEXTEQU<EDI>

    RXMMO TEXTEQU<EAX>

    RXMM1 TEXTEQU<ECX>

    NRXMM2 TEXTEQU<EDX>

    RXMM3 TEXTEQU<EBX>

    RXMM4 TEXTEQU<ESP>

    RXMM5 TEXTEQU<EBP>

    RXMM6 TEXTEQU<ESI>

    RXMM7 TEXTEQU<EDI> ENDIF endm

    Таблица 10.1. Кодировка регистров в машинном коде команды

    Код в поле reg Регистр целочисленного

    устройства
    ХММ-регистр
    000 АХ/ЕАХ RXMM0
    001 СХ/ЕСХ RXMM1
    010 DX/EDX RXMM2
    Oil ВХ/ЕВХ RXMM3
    100 SP/ESP RXMM4
    101 ВР/ЕВР RXMM5
    110 SI/ESI RXMM6
    111 DI/EDI RXMM7
    Теперь в исходном тексте программы можно использовать символические имена ХММ-регистров в качестве аргументов макрокоманд, моделирующих ХММ-команды.

    Рассмотрим, как в файле iammx.inc описано макроопределение для моделирования ХММ-команды скалярной пересылки MOVSS.

    :F3 OF 10 /г movss xrrnil. xmm2/m32 :F3 OF 11 /r movss xmm2/m32. xnrnl movss macro dst:req. src:req

    XMMld_st_f3 opc_Mo«s. dst, src endm

    Понимание структуры приведенного макроопределения не должно вызвать у читателя трудностей. Начать следует с того, что данная команда содержит вложенный вызов макрокоманды XMMld_st_f3, у которой две задачи — определить вариант сочетания операндов, после чего сформировать правильный код операции и подставить его на место соответствующих байтов в команде CMPXCHG. В результате этих действий команда CMPXCHG «превращается» в ХММ-команду MOVSS.



    1. XMMld_St f3 macro op:req.dst:req, src:req

    2. local x. у

    3. Defin'eXMMxRegs

    4. IF (OPATTR(dst)) AND OOOlOOOOy -.register

    5. x: lock cmpxchg src. dst

    6. у: org x

    7. byte OF3H.0Fh. op& Id

    8. org у

    9. ELSE

    10. x: lock cmpxchgdst. src

    11. y: orgx

    12. byte 0F3H.0Fh. op&_st

    13. orgy

    14. ENDIF

    15. UnDefineXMMxRegs

    16. endm

    Центральное место в макроопределении ХММ1 d_st_f3 занимают команда целочисленного устройства (в данном случае — CMPXCHG) и директива ORG. Первое действие данной макрокоманды — выяснить тип операнда приемника (dst) в макрокоманде MOVSS, так как он может быть и регистром, и ячейкой памяти. Это необходимо для правильного определения кода операции, которая будет управлять направлением потока данных. После того как определен приемник данных, с помощью условного перехода осуществляется переход на ветвь программы, где будет выполняться собственно формирование соответствующего ХММ-команде

    MOVSS кода операции.

    Формирование кода операции ХММ-команды MOVSS производится с помощью директивы org, которая предназначена для изменения значения счетчика адреса. В строках 6 или 11 директива org устанавливает значение счетчика адреса равным адресу метки х. Адрес метки х является адресом первого байта машинного кода команды CMPXCHG. Директива db в следующих строках размещает по этому адресу байтовые значения 0F3H,0Fh, ор&_1 d или 0F3H,0Fh, op&st, в зависимости от того, какое действие производится — загрузка (_ld) или сохранение (_st). Значение opc_Movss, с помощью которого формируются значения op&_st и ор&_1 d, определены в начале файла iaxmm.inc:

    opcjtovssjd - 010Н

    opc_Movss_st - 011H

    Для дотошных читателей заметим еще один характерный момент. Для его полного понимания необходимо хорошо представлять себе формат машинной команды и назначение его полей. Достаточно полная информация об этом приведена в литературе [39, 40]. Обратите внимание на порядок следования операндов в заголовке макрокоманды, который построен по обычной для команд ассемблера схеме: коп назначение, источник. В команде CMPXCHG порядок обратный. Этого требует синтаксис команды. Это хорошо поясняет назначение бита d во втором байте кода операции, который характеризует направление передачи данных в микропроцессор (то есть в регистр) или в память (из микропроцессора (регистра)). Вы можете провести эксперимент. Проанализируйте машинные коды команды MOV:



  • Команды с непосредственным операндом:

    CMPPS RXMM1. RXMM2/ml28, 18 CMPSS RXMM1, RXMM2/m32. i8


  • Однооперандные команды: FXRSTOR m512 FXSAVE m512 LDMXCSR m32 STMXCSR m32


  • Из перечисленных выше групп команд можно вывести следующую обобщенную структуру команды:

    метка: код_операции операнд1. операнд2, операндЗ] ;текст комментария

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

  • 1. Лексический анализ (сканирование) исходного текста.

    2. Синтаксический анализ.

    3. Генерация кода.


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

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

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

  • 1. Выделить классы лексем.

    2. Определить классы литер.

    3. Определить условия выхода из сканера для каждого класса лексем.

    4. Каждому классу лексем поставить в соответствие грамматику класса 3.

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

    6. Выполнить объединение («склеивание») конечных автоматов для всех классов лексем.

    7. Составить матрицу переходов для «склеенного» конечного автомата.

    8. «Навесить» семантику на дуги «склеенного» конечного автомата.

    9. Выбрать коды лексической свертки для терминалов грамматики и формат таблицы идентификаторов.

    10. Разработать программу сканера.



  • Содержание раздела