FPU предоставляет ряд инструкций для выполнения арифметических операций. Для сложения применяются инструкции fadd, faddp и fiadd
Если инструкциям fadd и faddp не передается параметр, то они извлекает два значения из вершины стека, складывает их и помещает их сумму обратно в стек.
fadd faddp
Если инструкции fadd передаются два регистра FPU, то она добавляет значение второго операнда к значению первого операнда. Один из операндов должен быть регистром ST(0).
fadd st(i), st(0) fadd st(0), st(i)
Инструкция faddp с двумя операндами добавляет ST(0) (который всегда должен быть вторым операндом) к первому операнду, а затем извлекает ST(0). Первый операнд должен быть одним из других регистров FPU.
faddp st(i), st(0)
Еще две формы fadd добавляют 32- или 64-битную переменную с плавающей точкой к значению в ST(0). Эти формы инструкции преобразует 32- или 64-битные операнды в 80-битное значение повышенной точности перед выполнением сложения. Но использовать 80-битные переменные нельзя операнд
fadd mem32 fadd mem64
Инструкция fiadd добавляет к ST(0) значение 16- и 32-битных переменных, которые представляют целые числа.
fiadd mem16 fiadd mem32
В зависимости от ситуации Эти инструкции могут генерировать исключения стека, точности, потери значимости (undeflow), переполнения, денормализации и недопустимой операции.
Применение fadd без параметров:
.data n1 real8 3.4 n2 real8 4.6 result dword ? .code main proc fld n1 ; загружаем число n1 в стек FPU fld n2 ; загружаем число n2 в стек FPU fadd ; складываем ST(0) и ST(1) fistp result ; Преобразуем число из ST(0) в dword mov eax, result ; EAX = 8 ret main endp end
Здесь в стек FPU последовательно загружаются переменные n1 и n2. Поскольку больше ничего не загружается в стек, то эти переменные будут располагаться в регистрах ST(0) (n2) и ST(1)(n1).
И инструкция fadd
сложит их и поместит результат в ST(0).
Другой пример - сложим значения из двух регистров:
.data st0 real8 3.4 st1 real8 4.6 st2 real8 1.6 result dword ? .code main proc fld st2 fld st1 fld st0 fadd st(0), st(2) ; складываем значения из регистров ST(0) и ST(2) fistp result mov eax, result ; EAX = 5 ret main endp end
Здесь складываем значения из регистров ST(0) и ST(2). Результатом будет число 5.0, которое помещается в первый регистр - ST(0).
Третий пример - сложение с переменной:
.data st0 real8 3.4 n real4 10.6 result dword ? .code main proc fld st0 fadd n ; прибавляем к ST(0) значение переменной n fistp result mov eax, result ; EAX = 14 ret main endp end