
- •Программирование
- •Синтаксис языка Ассемблера
- •Xchg Приемник, Источник
- •Inc Операнд
- •Imul eax, b ; возможна потеря !!!
- •Idiv Источник
- •Стек. Команды работы со стеком
- •Подпрограммы
- •Структура приложения Win32 api
- •Функции Windows api Функции Windows api сохраняют значения регистров ebp, ebx, esi, edi и могут модифицировать регистры eax, ecx, edx
- •Int MessageBox (hwnd hWnd, char * сообщение, char * заголовок, int стиль) вывод диалогового окна с текстовым сообщением и одной-двумя-тремя кнопками (см. Тему«Стандартные диалоги»)
- •Int wsprintf (char * строка, char * образец, …) формирование текстовой строки по образцу
- •Int ReleaseDc(hwnd hWnd,hdc hDc) освободить заданный дескриптор контекста устройства, связанный с заданным окном
- •Арифметический сопроцессор
- •Void FloatToStr(double число, char * строка)
Арифметический сопроцессор
Изначально процессоры семейства Intel 80x86 были ориентированы на обработку только целочисленных данных.
Для работы с вещественными числами требовалось использовать сложные алгоритмы.
Возможности процессора по обработке вещественных чисел были расширены арифметическим (числовым, математическим) сопроцессором.
Арифметический сопроцессор устройство, предназначенное для выполнения операций над вещественными числами.
В первых поколениях IBM-совместимых компьютеров арифметический сопроцессор (Intel 8087, Intel 80287, Intel 80387) являлся независимым устройством.
Для установки сопроцессора использовался отдельный разъем материнской платы. Отсутствие сопроцессора не влияло на работоспособность компьютера.
Начиная с Intel 80486 арифметический сопроцессор является составной частью центрального процессора.
Форматы данных сопроцессора
Сопроцессор поддерживает данные нескольких форматов:
– двоичные целые числа (16, 32 и 64 бита);
– двоично-десятичные числа (80 бит, 18 цифр);
– вещественные числа (32, 64 и 80 бит)
Кроме того, допускаются специальные значения:
– положительная и отрицательная бесконечности;
– нечисла, неопределенности и т.п.
Архитектура сопроцессора
С точки зрения программиста, сопроцессор содержит в себе 13 регистров
Стек сопроцессора образуют восемь 80-разрядных регистров, предназначенных для хранения вещественных чисел
Для доступа к стеку сопроцессора используются логические имена регистров:
ST или ST(0) – вершина стека
ST(1) – предыдущий элемент
. . .
ST(7) – дно стека
Регистры сопроцессора образуют кольцо, что позволяет не беспокоится о фактическом размещении данных:
Регистр тегов описывает содержимое каждого из восьми регистров стека сопроцессора
Возможны 4 состояния для каждого регистра:
– регистр не занят;
– регистр занят, содержит ненулевое число;
– регистр занят, содержит ноль;
– регистр занят, содержит специальное значение
Регистр состояния описывает текущее состояние сопроцессора после выполнения последней операции
Содержит:
– указатель на вершину стека сопроцессора;
– биты флагов (аналогично SF, ZF, …);
– биты исключительных ситуаций
При выполнении команд возможны исключительные ситуации:
– недействительная операция (запись в занятый регистр, чтение из свободного регистра, плохой операнд);
– деление на ноль;
– переполнение (результат операции выходит за допустимый диапазон);
– потеря значимости (результат слишком мал и был заменен на 0);
– потеря точности (было выполнено округление результата, например, 1/3)
Регистр управления описывает особенности обработки численных данных
Содержит:
– поле управления точностью (одинарная, двойная или расширенная);
– поле управления округлением (к ближайшему представимому значению, с избытком, с недостатком, отсечением);
– поле управления бесконечностью (аффинная или проективная);
– маски исключительных ситуаций (генерировать ошибку или возвращать специальное значение)
Указатель команды и Указатель данных содержат адрес команды, вызывавшей исключение, и адрес соответствующего операнда
Система команд сопроцессора
– команды пересылки данных;
– арифметические команды;
– трансцендентные команды;
– команды сравнения данных;
– команды управления
Мнемоники всех команд сопроцессора начинаются на букву F.
Вторая буква обычно указывает на тип данных:
I – команда работает с двоичными целыми числами
B – команда работает с двоично-десятичными целыми числами
Команды пересылки данных предназначены для организации обмена между регистрами стека, вершиной стека сопроцессора и ячейками оперативной памяти
Сопроцессор не имеет возможности обратиться к регистрам центрального процессора, а может обращаться только к ячейкам оперативной памяти.
Перед выполнением любой операции данные должны быть загружены из памяти в стек сопроцессора.
После выполнения операций результат выгружается в ячейки оперативной памяти.
При загрузке данных в стек сопроцессора автоматически выполняется преобразование значения в 80-битовое вещественное число.
При выгрузке данных в память происходит обратное преобразование.
Команда F?LD загружает значение из памяти в стек сопроцессора (работает аналогично команде PUSH)
FLD источник загружает вещественное число (32-, 64- или 80-битовое)
FILD источник загружает целое число (16-, 32- или 64-битовое)
FBLD источник загружает двоично-десятичное целое число (80-битовое)
Пример.
.data
integer dd 2
float dd 3.0
double dq 4.0
.code
fild integer
fld float
fld double
Команда F?ST сохраняет значение из вершины стека сопроцессора в память
FST приемник сохраняет вещественное число (32-, 64- или 80-битовое)
FIST приемник сохраняет целое число (16-, 32- или 64-битовое)
Команда F?STP извлекает значение из вершины стека сопроцессора и сохраняет его в памяти (работает аналогично команде POP)
FSTP приемник сохраняет вещественное число (32-, 64- или 80-битовое)
FISTP приемник сохраняет целое число (16-, 32- или 64-битовое)
FBSTP приемник сохраняет двоично-десятичное целое число (80-битовое)
Пример. Преобразование типа данных double ® float
.data
doublePI dq 3.14159265358979323846
.data?
floatPI dd ?
.code
fld doublePI
fstp floatPI
Команда FLD? загрузка часто используемых констант в стек сопроцессора
FLDZ загрузить ноль
FLD1 загрузить единицу
FLDPI загрузить число PI
. . .
Арифметические команды арифметические команды реализуют основные арифметические операции (сложение, вычитание, умножение, деление и др.)
Для каждого действия используется несколько команд, отличающихся набором и типом операндов.
Команда F?ADD
FADD источник – прибавление вещественного числа
FIADD источник – прибавление целого числа
Действие команды:
ST = ST + Источник
FADD ST(i),ST(j) – сложение регистров сопроцессора
Действие команды:
ST(i) = ST(i) + ST(j)
Пример. Реализация команды z=x+y
.data
x dq 2.3
y dq 4.1
.data?
z dq ?
.code
fld x ; ST = x
fadd y ; ST += y
fstp z ; z = ST
Команда F?MUL
FMUL источник – умножение на вещественное число
FIMUL источник – умножение на целое число
Действие команды:
ST = ST * Источник
FMUL ST(i),ST(j) – умножение регистров сопроцессора
Действие команды:
ST(i) = ST(i) * ST(j)
Команда F?SUB
FSUB источник – вычитание вещественного числа
FISUB источник – вычитание целого числа
Действие команды:
ST = ST – Источник
FSUB ST(i),ST(j) – вычитание регистров сопроцессора
Действие команды:
ST(i) = ST(i) – ST(j)
Команда F?DIV
FDIV источник – деление на вещественное число
FIDIV источник – деление на целое число
Действие команды:
ST = ST / Источник
FDIV ST(i),ST(j) – деление регистров сопроцессора
Действие команды:
ST(i) = ST(i) / ST(j)
Для команд FSUB, FDIV имеются реверсивные (обратные) аналоги, например:
FSUBR источник
Действие команды:
ST = источник – ST
FDIVR источник
Действие команды:
ST = источник / ST
Команда FABS – вычисление модуля числа
Действие команды:
ST = | ST |
Команда FCHS – изменение знака числа
Действие команды:
ST = – ST
Команда FSQRT – вычисление квадратного корня
Действие команды:
ST = sqrt( ST )
Трансцендентные команды используются для вычисления значений логарифмических, показательных, тригонометрических и обратных тригонометрических функций
Например: FSIN – вычисление синуса FCOS – вычисление косинуса
Команды сравнения данных используются для сравнения значения, находящегося в вершине стека сопроцессора с различными операндами.
В результате сравнения устанавливаются биты в регистре состояния сопроцессора.
Их значения можно переписать в регистр флагов центрального процессора и проанализировать с помощью команд условного перехода.
Команды управления сопроцессором предназначены для управления работой сопроцессора.
Большинство из этих команд работают с регистрами состояния и управления сопроцессором: задают, изменяют, сохраняют их значение.
Например:
FINIT – инициализация сопроцессора
Вывод вещественных чисел
Для вывода вещественных чисел можно воспользоваться функцией из библиотеки masm32: