Tooprogram.ru

Компьютерный справочник
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Команды сопроцессора ассемблер

Команды сопроцессора ассемблер

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

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

Рис. 10.15. Формат команд с обращением к памяти

Первые пять бит соответствуют команде центрального процессора ESC. Поля КОП1 и КОП2 определяют выполняемую команду, то есть содержат код операции. Поля MOD и R/M вместе с полями «Смещение1» и «Смещение2» задают адрес операнда в памяти аналогично тому, как это происходит в процессорах. Однако есть и отличия, связанные с возможностью адресации численных регистров сопроцессора.

Ниже мы покажем зависимость способа адресации от содержимого полей MOD и R/M:

Если в таблице указаны значения смещения disp8 или disp16, это означает, что в команде присуствует один или два байта смещения, соответственно.

Если поле MOD содержит значение 11, возможна адресация численных регистров ST0. ST1. При этом команда не содержит байтов смещения.

Формат команды с обращением к численному регистру приведен на рис. 10.16.

Рис. 10.16. Формат команд с обращением к численному регистру

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

Самый простой формат имеют команды без явного обращения к операндам (рис. 10.17).

Рис. 10.17. Формат команд без явного обращения к операндам

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

Все команды сопроцессора можно разделить на несколько групп:

· команды пересылки данных;

· команды сравнений чисел;

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

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

Команды сравнения сравнивают вещественные и целые числа, выполняют анализ чисел.

Трансцендентные команды предназначены для вычисления различных тригонометрических, логорифмических, показательных и гиперболических функций — sin, cos, tg и тому подобных.

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

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

Команды пересылки данных

Приведем описание команд, предназначенных для пересылки данных.

Запись в стек

Команды FLD, FILD, FBLD загружают в вершину стека вещественное, целое и десятичное числа, соответственно.

При выполнении этих команд операнд считывается из оперативной памяти, преобразуется в формат с расширенной точностью. Затем поле ST регистра состояния уменьшается на единицу и выполняется запись операнда в численный регистр, определяемый новым значением поля ST. То есть операнд записывается в стек численных регистров, а указатель стека (поле ST) уменьшается на единицу. По своему действию эти команды напоминают команду PUSH центрального процессора.

Непосредственно перед загрузкой численного регистра проверяется содержимое поля TAG0. Если это содержимое не равно 11 (пустой регистр), в регистре состояния устанавливается флаг IE (недействительная операция) и вырабатывается прерывание (если в регистре управления не установлена маска IM — маска недействительной операции).

Извлечение из стека

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

После записи содержимое поля ST увеличивается на единицу. Эти действия аналогичны выполняемым командой POP центрального процессора.

В зависимости от команды (FSTP, FISTP или FBSTP) производится преобразование формата (из расширенного в вещественный, целый или десятичный, соответственно). В процессе преобразования для команд FSTP и FISTP выполняется округление в соответствии с содержимым поля RC регистра управления. Для команды FBSTP округление всегда выполняется следующим образом — прибавляется число 0.5, затем дробная часть результата отбрасывается.

Копирование данных

Эти команды пересылают данные из верхушки стека в область памяти, указанную операндом команды. При этом содержимое указателя стека (поля ST) не изменяется.

Команда FST в качестве операнда может использовать ссылку на численный регистр ST(i), поэтому вы можете использовать эту команду для копирования верхушки стека в любой другой численный регистр.

При записи данных в оперативную память выполняется преобразование формата (в вещественный для FST, в целый для FIST и в десятичный для FBST.

Для сопроцессора 80286 вместо отсутствующей команды FBST можно выполнить следующие две команды, которые приведут к такому же результату:

Читать еще:  Дизассемблер hex файлов

Обмен

Команда выполняет обмен содержимым верхушки стека ST(0) и численного регистра, указанного в качестве операнда команды.

Загрузка констант

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

Арифметические команды

Сопроцессор использует шесть основных типов арифметических команд:

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

Источник берется из памяти, приемником является верхушка стека ST(0). Указатель стека ST не изменяется, команда действительна только для операндов с одинарной и двойной точностью

Аналогично предыдущему типу команды, но операндами могут быть 16- или 32-разрядные целые числа

Для этого типа регистр ST(i) является источником, а ST(0) — верхушка стека – приемником. Указатель стека не изменяется

Для этого типа регитр ST(0) является источником, а ST(i) — приемником. Указатель стека не изменяется

Регистр ST(i) — приемник, регистр ST(0) – источник. После выполнения команды источник ST(0) извлекается из стека

Строка «xxx» может принимать следующие значения:

Команды математического сопроцессора

Математический сопроцессор дает возможность процессорам обрабатывать данные с плавающей запятой, которые широко используются в обработке изображения, а также в научных, инженерных и коммерческих приложениях. Ядро процессора IA-32, доступное программисту, реализует вычисления только над целыми числами, поэтому обработка вещественных чисел на нем, задача достаточно трудоемкая. Поэтому в состав процессора с архитектурой IA-32 входит математический сопроцессор (или блок обработки чисел с плавающей запятой, FPU). Математический сопроцессор, как отдельная микросхема, появился уже в первых ПК (связка процессор и соответствующий ему сопроцессор имели сходную нумерацию, например: процессор I80286, а сопроцессор к нему — I80287), а начиная с процессоров Intel486, математический сопроцессор в виде блока FPU стал размещаться на одном кристалле с процессором.

Архитектура процессоров IA-32 обрабатывает 3 типа данных с плавающей запятой: числа с плавающей запятой одинарной точности, числа с плавающей запятой двойной точности и числа с плавающей запятой расширенной двойной точности.

В таблице 27 приведено описание каждого из типов данных.

Таблица 27 — Типы данных чисел с плавающей запятой

Тип данныхРазрядностьРазрядность мантиссы (бит)Примерный нормализованный диапазон значений
2 с/с10 с/с
Одинарная точностьот 2 -126 до 2 127от 1,18·10 -38 до 3,4·10 38
Двойная точностьот 2 -1022 до 2 1023от 2,23·10 -308 до 1,79·10 38
Расширенная двойная точностьот 2 -16382 до 2 16383от 3,37·10 -4932 до 1,18·10 4932

На рисунке 15 представлена исполнительная среда блока обработки чисел с плавающей запятой.

Рисунок 15 — Исполнительная среда блока FPU

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

Команды блок FPU рассматривают регистры данных как стек (рисунок 16). При этом, адресация регистров данных осуществляется относительно вершины стека (адрес которой хранится в поле TOP регистра состояния). При загрузке данных в стек, адрес вершины стека уменьшается на 1 и загрузка осуществляется в тот регистр, на который указывает вершина стека. При считывании данных из стека, сначала считывается число из вершины стека в память, а затем увеличивается адрес вершина стека. Однако, стоит заметить что имеются операции загрузки и чтения данных из стека, которые не «проталкивают» данные в стеке.

Рисунок 16 — Организация стека данных FPU

Если операция записи данных осуществляется когда указатель на вершину стека равен 0, то записываемые данные окажутся в стековом регистре 7 и будет сформировано исключение «Переполнение стека», при чтении данных из пустого стека формируется исключение «Опустошение стека».

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

Точность вычислений задается двумя битами (8 и 9): 0 — одинарная точность, 2 — двойная точность, 3 — двойная расширенная точность.

Выбор метода округления также осуществляется с помощью двух бит (10 и 11): 0 — округлять к ближайшему, 1 — округлять к ближайшему снизу, 2 — округлять к ближайшему сверху, 3 — отбросить дробную часть.

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

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

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

Читать еще:  Язык си ввод вывод

Регистр тега отображает содержимое каждого из 8 регистров стека (по 2 на каждый регистр): 00 — действительное ненулевое число, 01 — истинный нуль, 10 — специальные числа (неподдерживаемые, ненормализованные или бесконечные числа), 11 — отсутствие данных.

В таблице 28 приведены команды блока FPU.

Таблица 28 — Некоторые команды блока FPU

Команды передачи данных
FLD srcЗагрузить вещественное число в ST(0) (вершину стека) из области памяти. Область памяти может быть 32-, 64-, 80-битная.
FILD srcЗагрузить целое число в ST(0) из памяти. Область памяти может быть 16-, 32-, 64-битной.
FBLD srcЗагрузить двоично-десятичное число в ST(0) из 80-битной области памяти.
FLDZЗагрузить 0 в ST(0).
FLD1Загрузить 0 в ST(0).
FLDPIЗагрузить PI в ST(0).
FLDL2TЗагрузить LOG2(10) в ST(0).
FLDTL2EЗагрузить LOG2(e) в ST(0).
FLDLG2Загрузить LG(2) в ST(0).
FLDLN2Загрузить LN(2) в ST(0).
FST destЗапись вещественного числа из ST(0) в память. Область памяти 32-, 64- или 80-битная.
FSTP destЗапись вещественного числа из ST(0) в память. Область памяти 32-, 64- или 80-битная. При этом происходит выталкивание вершины из стека.
FBST destЗапись двоично-десятичного числа в память. Область памяти 80-битная.
FBSTP destЗапись двоично-десятичного числа в память. Область памяти 80-битная. При этом происходит выталкивание вершины из стека.
FXCH st(i)Обмен значениями вершины стека и стекового регистра i (0≤i≤7)
Команды сравнения данных
FCOMСравнение вещественных чисел ST(0) и ST(1). Флаги устанавливаются, как при операции ST(0)-ST(1).
FCOM srcСравнение ST(0) с операндом в памяти. Операнд может быть 32- или 64-битным.
FCOMP srcСравнение вещественного числа в ST(0) с операндом с выталкиванием ST(0) из стека. Операнд может быть регистром и областью памяти.
FCOMPPСравнение ST(0) и ST(1) с двойным выталкиванием из стека.
FICOM srcСравнение целых чисел в ST(0) с операндом. Операнд может быть 16- или 32-битным.
FICOMP srcСравнение целых чисел в ST(0) с операндом. Операнд может быть 16- или 32-битной областью памяти или регистром. При выполнении операции происходит выталкивание ST(0) из стека.
FTSTПроверка ST(0) на нуль.
FUCOM ST(i)Сравнение ST(0) с ST(i) без учета порядков.
FUCOMP ST(i)Сравнение ST(0) с ST(i) без учета порядков. При выполнении операции происходит выталкивание из стека.
FUCOMPP ST(i)Сравнение ST(0) с ST(i) без учета порядков. При выполнении операции происходит двойное выталкивание из стека.
FXAMАнализ содержимого вершины стека. Результат помещается в биты С3-С0. 000 — неподдерживаемый формат. 001 — не число. 010 — нормализованное число. 011 — бесконечность. 100 — нуль. 101 — пустой операнд. 110 — ненормализованное число.
Арифметические команды
FADD src FADD ST(i),STСложение вещественных чисел. ST(0)

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Да какие ж вы математики, если запаролиться нормально не можете. 8826 — | 7636 — или читать все.

Блог программистов

Работа с дробными числами на ассемблере

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

Сопроцессор имеет восемь 10-байтных регистров, организованных в кольцевой стек. Вершиной стека является регистр ST(0). Если в стек заносится какое-то значение, то регистры FPU «сдвигаются», по сути, меняется значение индекс, который задаёт какой сейчас регистр является вершиной стека (непонятно? Читайте далее). Так что ST(0) — всегда вершина, ST(1) — первое значение ниже вершины и т.д. до ST(7). Если речь идёт о ST(0), то цифру иногда опускают и пишут просто ST. В FASM регистры пишутся так: st0, st1, st2 и т.д. Также надо заботиться о том, чтобы этот стек не переполнился.
Для каждого стекового регистра формируется 2-битный тег (признак), содержание которого соответствует определенному состоянию стекового регистра (00 — допустимое ненулевое число; 01 — нуль; 10 — специальные значения (не число); 11 — пустой регистр). Режим работы FPU и его состояние определяются содержанием регистров слова управления CW (Control Word) и слова состояния SW (Status Word).
Слово состояния SW отражает общее состояние устройства FPU. Регистр слова состояния FPU, по сути, является аналогом регистра флагов центрального процессора.
• IE (бит 0) — наличие недействительной операции: деление на ноль, умножение на бесконечность, корень из отрицательного числа и т.д.;
• DE (бит 1)- фиксируется появление денормализованного операнда ;
• ZE (бит 2)- фиксируется попытка деления на ноль;
• ОЕ (бит 3)- переполнение, при котором результат операции выходит за пределы представления в формате получателя;
• UE (бит 4)- потеря значимости (антипереполнение) — результат не равен нулю, но слишком мал для представления в формате получателя;
• РЕ (бит 5)- неточный результат, результат нельзя точно представить в формате получателя или имеет место округление.
• SF (бит 6) — ошибки в работе стекового регистра: переполнение стека, извлечение из пустого стека. Переполнению стека соответствуют SF=l,Cl=t; изъятию из пустого стека — SF=1,C1=0;
• ES (бит 7) — устанавливается в 1 при возникновении любого особого случая;
• СО — СЗ (биты 8, 9, 10, 14) — являются битами кода условия, отмечают результаты команд сравнения, проверки и анализа. Основное назначение этих бит — определение условий перехода. Они похожи на арифметические флаги в регистре EFLAGS. Командой FSTSW АХ их значения можно занести в регистр АХ, а командой SAMF скопировать их из регистра АХ в биты флагов EFLAGS в следующем порядке: СО ->CF, С2 -> PF, СЗ ZF.
• ТОР (биты 11, 12, 13) — определяют номер регистра стека, который в текущий момент является вершиной стека. При сдвиге регистров сопроцессора изменяется только значение этого поля.
• В (бит 15) — отмечает занятость выполнением операции или наличие не обслуженного запроса (сохранен только для совместимости с сопроцессором 8087).
Например, если предыдущей командой была предпринята попытка деления на ноль, то будет выставлен флаг ZE.
Слово управления CW содержит поля управления точностью и округлением, а также набор флагов (первые шесть бит), каждый из которых является маской отдельных исключений сопроцессора. Маскировка любого исключения проводится занесением в соответствующее поле маски еденицы.
• IM … РМ (биты 0 — 5) — маски исключений (совпадают с соответствующими разрядами слова состояния);
• RC — управление округлением в соответствии со стандартом IEEE -754 (00 — округление до ближайшего или четного; 01 — округление вниз к —

Команда ffree освобождает регистр, не являющийся вершиной стека. Операндом является регистр FPU.
Команды fincstp и fdecstp вращают кольцевой стек FPU на единицу, прибавляя или отнимая единицу от поля STP слова статуса FPU. У этих инструкций нет операндов. fdecstp вращает так: st7->st0->st1->st2…, fincstp – наоборот.
Команда fsqrt вычисляет квадратный корень из значения в регистре ST(0), fsin вычисляет синус этого значения, fcos вычисляет его косинус, fchs дополняет его знаковый бит, fabs очищает знак, чтобы создать абсолютное значение, frndint округляет до ближайшего целого значения, зависящего от текущего режима округления. f2xm1 вычисляет экспоненциальное значение 2 в степени ST(0) и вычитает из результата 1.0 (2^x-1), значение в st0 должно лежать в пределах от -1.0 до +1.0. Все вышеперецисленные инструкции сохраняют значение в ST(0) и не имеют операндов.
Команды fstsw и fnstsw сохраняют текущее значение слова статуса FPU в указанном месте. Операндом-адресатом может быть либо 16 бит в памяти, либо регистр AX. fstsw перед сохранением слова проверяет на подвешенные немаскируемые прерывания, fnstsw этого не делает.
Команды fstcw и fnstcw сохраняют текущее значение управляющего слова FPU в указанном месте в памяти. fstcw перед сохранением слова проверяет на подвешенные немаскируемые прерывания, fnstcw этого не делает. fldcw загружает операнд в управляющее слово FPU. Операндом должно быть 16-битное расположение в памяти.

Итак, с основными командами разобрались. Теперь к радости и счастью студентов напишем две процедуры, которые преобразовывают строку в число с плавающей точкой и наоборот.
Сначала функция, которая преобразовывает строку в число. Общий принцип процедуры такой: начала загружаем в st0 ноль в цикле, смотрим очередной символ в строке, преобразовываем этот символ в число и прибавляем к st0, предварительно умножив его на 10. После всего проделанного смотрим, сколько у нас символов после запятой и делим st0 на 10 столько раз, сколько у нас символов после запятой.

Точность получаемого значения можно изменить, просто изменив директиву qword (на dword или tword) в строке, которую я пометил стрелкой.
Чуть не забыл, процедура GetZSLength

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

Ссылка на основную публикацию
Adblock
detector