Для выполнения арифметических действий над числами с плавающей точкой расширения SSE предоставляет ряд инструкций:
addss и addsd: сложение
subss и subsd: вычитание
mulss и mulsd: умножение
divss и divsd: деление
minss и minsd: вычисляют минимальное значение двух операндов, сохраняя минимальное значение в первом операнде.
maxss и maxsd: вычисляют максимальное значение двух операндов, сохраняя минимальное значение в первом операнде.
sqrtss и sqrtsd: вычисляют квадратный корень второго операнда и сохраняют результат в первый операнд
rcpss и rcpsd: вычисляют обратное значение второго операнда, сохраняя результат в первый операнд
rsqrtss и rsqrtsd: вычисляют обратное значение квадратного корня второго операнда, сохраняя результат в первый операнд
Инструкции, которые оканчиваются на ss, предназначены для 32-разрядных чисел с плавающей точкой (ss - сокращение от "scalar single"). Инструкции, которые оканчиваются на sd, предназначены для 64-разрядных чисел с плавающей точкой (sd - сокращение от "scalar double"). Общий синтаксис инструкций:
addss xmmn, xmmn addss xmmn, mem32 addsd xmmn, xmmn addsd xmmn, mem64 subss xmmn, xmmn subss xmmn, mem32 subsd xmmn, xmmn subsd xmmn, mem64 mulss xmmn, xmmn mulss xmmn, mem32 mulsd xmmn, xmmn mulsd xmmn, mem64 divss xmmn, xmmn divss xmmn, mem32 divsd xmmn, xmmn divsd xmmn, mem64 minss xmmn, xmmn minss xmmn, mem32 minsd xmmn, xmmn minsd xmmn, mem64 maxss xmmn, xmmn maxss xmmn, mem32 maxsd xmmn, xmmn maxsd xmmn, mem64 sqrtss xmmn, xmmn sqrtss xmmn, mem32 sqrtsd xmmn, xmmn sqrtsd xmmn, mem64 rcpss xmmn, xmmn rcpss xmmn, mem32 rsqrtss xmmn, xmmn rsqrtss xmmn, mem32
Первый операнд (куда помещается результат операции) всегда должен быть регистром XMM. Например, сложим два числа в программе на Linux:
global _start section .data num0 dq 3.4 num1 dq 6.6 section .text _start: movsd xmm0, [num0] ; помещаем в xmm0 число num0 movsd xmm1, [num1] ; помещаем в xmm1 число num1 addsd xmm0, xmm1 ; xmm0 = xmm0 + xmm1 cvtsd2si rdi, xmm0 ; из xmm0 преобразуем в целое число и помещаем в rdi mov rax, 60 syscall
В данном случае складываем два числа типа qword - num1 и num2, которые предварительно загружаются в регистры xmm0 и xmm1. После сложения результат помещается в регистр xmm0, а затем конвертируется в целое число и помещается в регистр rdi. Таким образом, в регистре rdi в итоге окажется число 10.
Аналогичная программа для Windows:
global _start section .data num0 dq 3.4 num1 dq 6.6 section .text _start: movsd xmm0, [rel num0] ; помещаем в xmm0 число num0 movsd xmm1, [rel num1] ; помещаем в xmm1 число num1 addsd xmm0, xmm1 ; xmm0 = xmm0 + xmm1 cvtsd2si rax, xmm0 ; из xmm0 преобразуем в целое число и помещаем в rax ret