Математический сопроцессор
Floating-point unit, FPU — блок процессора предназначенный для обратки чисел с плавающей точкой. Раньше сопроцессор был отдельной микросхемой. Теперь чаще всего он находится непосредственно на кристале процессора.
Типы данных
Сопроцессор архитектуры х86 способен обрабатывать следующие типы данных:
- single (float)
 - double
 - extended (80 бит)
 - int (16/32/64 бит)
 - bcd80 — двоично-десятичный 10-байтовый формат, каждый полубайт которого хранит одну десятичную цифру
 
Регистры
Регистры общего назначения не подходят для обработки чисел с плавающей точкой. Для этих чисел существуют 8 специальных регистров организованных в кольцевой стек.
Это 80-битовые регистры r0-r7, однако в программе к ним обращаются по именам st(*)(без скобок при компиляции в yasm).
| st(2) | r7 | 
| st(1) | r6 | 
| st(0) | r5 | 
| st(7) | r4 | 
| st(6) | r3 | 
| st(5) | r2 | 
| st(4) | r1 | 
| st(3) | r0 | 
При добавлении в стек еще однго элемента произойдет сдвиг этих имен. st(7) станет st(0) — вершиной стека.
| st(3) | r7 | 
| st(2) | r6 | 
| st(1) | r5 | 
| st(0) | r4 | 
| st(7) | r3 | 
| st(6) | r2 | 
| st(5) | r1 | 
| st(4) | r0 | 
Управляющие регистры
Так же существуют несколько специальных регистров:
- cr \\управляющий регистр. Позволяет контролировать режимы округления и пр.
 - sr \\регистр состония
 - tw \\метки (пустой, число, не число, ...)
 
При обработке исключений так же используются:
- fip \\регистр указателя команд
 - fdp \\регистр указателя данных
 
Команды
- fld/fild/fbl
 
загрузка из памяти или копирование из другого fpu регистра в st(0). Например:
fld st(0)
fild dword [eax]
- fst(p)/fist(p)/fbstp *(p) +выталкивает вершину
 
загрузка в память или st(*) из st(0) регистра
- fxch \\swap(st(0), st(*))
 - fcmov_cc \\условная загрузка
 - fcom st(2)(p(p)) \\сравнение с вершиной
 
- fstsw ax
 
- sahf
 
флаги сопроцессора в флаги процессора
- fucom(p) \\еще одно сравнение
 - ficom(p) \\сравнение с памятью
 
- fcomi(p) \\результат сравнения в flags
 - fucomi(p)
 
Вычисления
- fadd(p)/fiadd \\st(0) = arg + st(0)
 - fsub(p)/fisub \\st(0) = st(0) - arg
 - sfubr(p)/fisubr \\st(0) = arg - st(0)
 - fmul(p)/fimul
 - fdiv(p)/fidiv
 - dfivr(p)/fidivr
 
- frem/frem1 st(0) - n * st(1) \\остаток получаемый вычитаниями (не блолее 64 штук)
 
- fchs
 
изменить знак на противоположный.
Работают с st(0) Не нуждаются в отдельныз пояснениях.
- fabs
 - frndint
 - fsin
 - fcos
 - fsincos
 - fptan
 - fpatanb
 
- fld1/z/pi/...
 
загрузка констант
- fincstp
 - fdecstp
 
двигаем указатель стека, не меняя состояние регистров (пустой/полный)
- ffree
 
освободить регистр
- fnop
 
поделать ничего. Теперь и на fpu.