Команды управления математическим сопроцессором 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Команды управления математическим сопроцессором



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

· мнемокод, не содержащий второго символа n, обозначает команду, которая перед началом своего выполнения проверяет наличие незамаскированных исключений;

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

Эти команды имеют одинаковый машинный код. Отличие лишь в том, что перед командами, не содержащими символа n, транслятор ассемблера вставляет команду wait. Команда wait является полноценной командой основного процессора и ее, при необходимости, можно указывать явно. Команда wait имеет аналог среди команд сопроцессора — fwait. Обеим этим командам соответствует код операции 9bh.

Команда FWAIT — команда ожидания. Предназначена для синхронизации работы процессора и сопроцессора. Так как основной процессор и сопроцессор работают параллельно, то может создаться ситуация, когда за командой сопроцессора, изменяющей данные в памяти, следует команда основного процессора, которой эти данные требуются. Чтобы синхронизировать работу этих команд, необходимо включить между ними команду wait/fwait. Встретив данную команду в потоке команд, основной процессор приостановит свою работу до тех пор, пока не поступит аппаратный сигнал о завершении очередной команды в сопроцессоре.

Команда FINIT / FNINIT — инициализация сопроцессора. Данная команда инициализирует управляющие регистры сопроцессора определенными значениями:

CWR = 037Fh

· RC=00b; округление к ближайшему целому;

· PM,UM,OM,ZM,DM,IM=1; все исключения замаскированы;

· PC=11b; максимальная точность 64 бита.

SWR = 0h – отсутствие исключений и указание на то, что физический регистр стека сопроцессора r0 является вершиной стека и соответствует логическому регистру ST(0);

TWR = FFFFh – все регистры стека сопроцессора пусты;

DPR=0; IPR=0.

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

Команда FSTSW / FNSTSW — сохранение содержимого регистра состояния swr в регистре ах или в ячейке памяти размером 2 байта. Эту команду целесообразно использовать для подготовки к условным переходам по описанной при рассмотрении команд сравнения схеме.

Команда FSTCW / FNSTCW — сохранение содержимого регистра управления cwr в ячейке памяти размером 2 байта. Эту команду целесообразно использовать для анализа полей маскирования исключений, управления точностью и округления. Следует заметить, что в качестве операнда назначения не используется регистр ах, в отличие от команды FSTSW/FNSTSW.

Команда FLDCW — загрузки значения ячейки памяти размером 16 бит в регистр управления cwr. Эта команда выполняет действие, противоположное командам FSTCW/FNSTCW. Команду целесообразно использовать для задания или изменения режима работы сопроцессора. Если в регистре состояния swr установлен любой бит исключения, то попытка загрузки нового содержимого в регистр управления cwr приведет к возбуждению исключения. По этой причине необходимо перед загрузкой регистра cwr сбросить все флаги исключений в регистре swr.

Команда FCLEX / FNCLEX — позволяет сбросить флаги исключений, которые, в частности, необходимы для корректного выполнения команды FLDCW. Ее также применяют и в случаях, когда необходимо сбрасывать флаги исключений в регистре swr, например, в конце подпрограмм обработки исключений. Если этого не делать, то при исполнении первой же команды сопроцессора прерванной программы (кроме тех команд, которые имеют в названии своего мнемокода второй символ n) будет опять возбуждено исключение.

PE, UE, OE, ZE, DE, IE, ES, SF и B биты регистра SWR равны 0.

Команда FINCSTP — увеличение указателя стека на единицу (поле top) в регистре swr. Команда не имеет операндов. Действие команды fincstp подобно команде FST, но она извлекает значение операнда из стека «в никуда». Таким образом, эту команду можно использовать для выталкивания, ставшего ненужным операнда, из вершины стека. Команда работает только с полем top и не изменяет соответствующее данному регистру поле в регистре тегов twr, то есть регистр остается занятым и его содержимое из стека не извлекается.

Команда FDECSTP — уменьшение указателя стека (поле top) в регистре swr. Команда не имеет операндов. Действие команды FDECSTP подобно команде FLD, но она не помещает значения операнда в стек. Таким образом, эту команду можно использовать для проталкивания внутрь стека операндов, ранее включенных в него. Команда работает только с полем top и не изменяет соответствующее данному регистру поле в регистре тегов twr, то есть регистр остается пустым.

Команда FFREE —помечает любой регистр стека сопроцессора как пустой.

Синтаксис:         FFREE ST(i)

Команда записывает в поле регистра тегов, соответствующего регистру ST(i), значение 11b, что соответствует, пустому регистру. При этом указатель стека (поле tор) в регистре swr и содержимое самого регистра не изменяются. Необходимость в этой команде может возникнуть при попытке записи в регистр ST(i), который помечен, как непустой. В этом случае будет возбуждено исключение. Для предотвращения этого применяется команда FFREE.

Команда FNOP — пустая операция. Не производит никаких действий и влияет только на регистр указателя команды IPR.

Команда FSAVE / FNSAVE — сохранения полного состояния среды сопроцессора в память по адресу, указанному операндом приемник. Размер области памяти зависит от размера операнда сегмента кода usel6 или use32:

· use 16 — область памяти должна быть 94 байта: 80 байт для восьми регистров из стека сопроцессора и 14 байт для остальных регистров сопроцессора с дополнительной информацией;

· use32 — область памяти должна быть 108 байт: 80 байт для восьми регистров из стека сопроцессора и 28 байт для остальных регистров сопроцессора с дополнительной информацией.

После выполнения сохранения состояния среды сопроцессора производится инициализация сопроцессора.

     

Команда FRSTOR — используется для восстановления полного состояния среды сопроцессора из области памяти, адрес которой указан операндом источник. Сопроцессор будет работать в новой среде сразу после окончания работы команды frstor.

Команда FSTENV / FNSTENV — сохранение частичного состояния среды сопроцессора в область памяти, адрес которой указан операндом приемник. Размер области памяти зависит от размера операнда сегмента кода usel6 или use32. Формат области частичной среды сопроцессора совпадает с форматом области полной среды, за исключением содержимого стека сопроцессора (80 байт).

Команда FLDENV — восстановление частичного состояния среды сопроцессора содержимым из области памяти, адрес которой указан операндом источник. Информация в данной области памяти была ранее сохранена командой FSTENV/FNSTENV.

 

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

 

Отладка программ, использующих функции сопроцессора

Для просмотра содержимого регистров сопроцессора в среде Microsoft Visual Studio в окне регистров выбрать всплывающее меню Floating Point.

Пример программы с использованием команд сопроцессора

Определить, принадлежит ли точка заштрихованной части плоскости.

Программа запрашивает вещественные координаты точки X и Y, после чего с помощью команды сопроцессора сравнивает координату Y с 2, а X – с (-1). В соответствии с результатом сравнения выдается сообщение о принадлежности или непринадлежности точки.

#include <windows.h>

#include <tchar.h>

void main()

{

float x,y;

int cons=2;

char s[40];

CharToOem(_T("Введите координаты точки X и Y: "),s);

printf(s);

scanf("%f%f",&x,&y);

_asm

{

    fild cons

    fld y

    fcomip ST,ST(1)

    jae m

    fstp cons; освобождение стека

    mov cons, -1

    fild cons

    fld x

    fcomip ST,ST(1)

    jb m

}

CharToOem(_T("Точка принадлежит плоскости."),s);

_asm jmp ext;

m:

CharToOem(_T("Точка не принадлежит плоскости."),s);

ext:

printf(s);

getch();

}

Сложные типы данных

Структуры

Часто в приложениях возникает необходимость рассматривать некоторую совокупность данных разного типа как некоторый единый тип. Это очень актуально, например, для программ баз данных, где необходимо связывать совокупность данных разного типа с одним объектом. Такой объект обычно описывается с помощью специального типа данных — структуры. С целью повысить удобство использования языка ассемблера в него также был введен такой тип данных.

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

· Задать шаблон структуры. По смыслу это означает определение нового типа данных, который впоследствии можно использовать для определения переменных этого типа.

· Определить экземпляр структуры. Этот этап подразумевает инициализацию конкретной переменной с заранее определенной (с помощью шаблона) структурой.

· Организовать обращение к элементам структуры.

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

Описание шаблона структуры

Описание шаблона структуры имеет следующий синтаксис:

имя_структуры STRUC

<описание полей>

имя_структуры ENDS

Здесь <описание полей> представляет собой последовательность директив описания данных db, dw, dd, dq и dt. Их операнды определяют размер полей и при необходимости начальные значения. Этими значениями будут, возможно, инициализироваться соответствующие поля при определении структуры.

Местоположение шаблона в программе может быть произвольным, но, следуя логике работы однопроходного транслятора, он должен быть расположен до того места, где определяется переменная с типом данной структуры. То есть при описании в секции данных переменной с типом некоторой структуры ее шаблон необходимо поместить в начале секции данных либо перед ней.

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

worker struc      ;информация о сотруднике

nam db 30 dup (" ");фамилия, имя, отчество

position db 30 dup (" ");должность

age dd 20    ;возраст

worker ends

Определение данных типа «структура»

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

[имя_переменной] имя_структуры <[список_значений]>

имя_переменной — идентификатор переменной данного структурного типа. Задание имени переменной необязательно. Если его не указать, будет просто выделена область памяти размером в сумму длин всех элементов структуры;

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

Для примера определим несколько переменных с типом структуры worker:

data segment

sotr1 worker<"Гурко Андрей Вячеславович",'художник',33>

sotr2 worker<"Степанова Ольга Валерьевна",'связист'>

sotr3 worker<>;все значения по умолчанию

data ends

Методы работы со структурой

Идея введения структурного типа в любой язык программирования состоит в объединении разнотипных переменных в один объект. В языке должны быть средства доступа к этим переменным внутри конкретного экземпляра структуры. Для того, чтобы сослаться в команде на поле некоторой структуры, используется специальный оператор — символ «.» (точка). Он используется в следующей синтаксической конструкции:

адресное_выражение.имя_поля_структуры

адресное_выражение — идентификатор переменной структурного типа;

имя_поля_структуры — имя поля из шаблона структуры, представляет собой смещение поля от начала структуры. Таким образом оператор «.» вычисляет выражение:

(адресное_выражение) + (имя_поля_структуры)

Продемонстрируем на примере структуры worker некоторые приемы работы со структурами. Пусть требуется извлечь в eaх и ebx значения поля с возрастом.

code segment

start:

mov eax, sotr1.age

mov ebx, sotr2.age

...

ret

code ends

или

code segment

start:

lea ebx, sotr1

mov eax, [ebx + worker.age]

mov edx, [ebx + size(worker) + worker.age]

ret

code ends

 

Язык ассемблера разрешает определять не только отдельную переменную с типом структуры, но и массив структур:

mas_sotr worker 10 dup (<>)

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

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

...

data segment

mas_worker worker 10 dup(<>)

data ends

code segment

start:

lea esi, mas_worker

mov ecx, 10

mov edx, 0

m1:

mov eax, [esi + worker.age]

add eax, edx

mov [esi + worker.age], eax

inc edx

mov eax, [esi + worker.age]

add esi, size(worker)

loop m1

ret

code ends

end start

Объединения

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

Описание объединений в программе напоминает описание структур, то есть сначала описывается шаблон, в котором с помощью директив описания данных перечисляются имена и типы полей:

[имя_объединения] UNION

<описание полей>

[имя_объединения] ENDS

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

MY UNION

mb db?

mw dw?

md dd?

Для описания объекта объединения в тексте программы используется конструкция вида

.data

...

MyData MY <>;определение экземпляра объединения

Для обращения к полям объединения используется оператор «.» (точка)

mov MyData.mw, 1

mov al, MyData.mb; al=1

 



Поделиться:


Последнее изменение этой страницы: 2020-12-09; просмотров: 332; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.191.236.174 (0.086 с.)