О MMX и SSE - некоторые команды, регистры
-
В этой теме показаны примеры использования регистров и команд:
Список некоторых команд (не всех, их очень много):
Регистры xmm0 xmm1 xmm... xmm15 Выполняют те же функции что и обычные регистры, но могут хранить в разы больше. Могут быть приёмником и источником для команд MMX. Команды записи movd *,* - записывает 4 байта из переменной в приёмник. movq *,* - записывает 8 байт. movss *,* - записываем float (4 байта) из переменной в приёмник movsd *,* - записывает doble (8 байт) их переменной в приёмник Массивные movups *,* - записывает 4 элемента массива в том порядке в котором они идут в приёмник movaps *,* - записывает выравненные 4 элемента массива movhlps *,* - записываем 2 левых элемента из источника в 2 правых приёмника movlhps *,* - записываем 2 правых элемента из источника в 2 левых приёмника movhps *,* - записывает 2 левых элемента из источника в 2 левых приёмника. movlps *,* - то же что и выше но 2 правых элемента. Арифметические команды. Любые действия выполняются в следующем порядке - приёмник на источник, запись в приёмник. (приёмник это первая *, источник - вторая *) addsd *,* - сложение двух чисел с плавающей запятой, типа doble (8 байт). subsd *,* - то же что выше но вычитание. mulsd *,* - Умножение. divsd *,* - Деление. sqrtsd *,* - Корень из doble addss *,* - Сложение двух float (4 байта) subss *,* - Вычитание float mulss *,* - Умножение float divss *,* - Деление float sqrtss *,* - Корень из float Массивные addps *,* - складывает 2 массива subps *,* - вычитает массив из массива divps *,* - делит массив на массив. mulps *,* - умножает массив на массив. sqrtps *,* - корни из массива Команды сравнения comiss - сравнение двух float comisd - сравнение doble Команды преобразования cvtsi2ss - преобразовать целое в float cvtsi2sd - преобразовать целое в doble cvttss2si - преобразовать вещественное в целое с округлением.Регистры в этих дополнениях сопроцессора очень похожи на основные, но в отличии от них могут содержать целых четыре элемента, и даже работать сразу со всеми четырьмя!
Все функции сложения, вычитания, и другие могут быть совершены только с регистрами.
Такая инструкция
addss xmm0,[MyLabel]сработает:
А такаяaddss [MyLabel],xmm0- нет.Потому следует все операции производить с регистрами.
Например, если необходимо прибавить что нибудь к переменной можно использовать такой код:movss xmm0,[MyLabel] //Записываем в xmm0 число из label addss xmm0,[MyAddValue] //Добавляем к нему другое movss [MyLabel],xmm0 //Записываем из xmm0 назад в label.Помните что регистры это не стек, и потому значения свои сохраняют после записи.
Эти регистры могут содержать целых 4 элемента, позволяя обрабатывать списки из четырёх значений:
Список должен состоять из четырёх элементов, например такой:MyList: dd (float)2 dd (float)7 dd (float)29324.126 dd (float)8261.3Что бы записать этот список в xmm мы можем использовать инструкцию
movups xmm0,[MyList].После чего получим в
xmm0все четыре числа по порядку.
Теперь мы можем сделать что нибудь с этим массивом, например умножить его на другой массив"MyListMul: dd (float)1 dd (float)2 dd (float)0.5 dd (float)2Умножение:
movups xmm0,[MyList] //Загружаем умножаемый список movups xmm1,[MyListMul] //Загружаем умножающий список mulps xmm0,xmm1 //Умножаем movups [MyList],xmm0 //Возвращаем в умножаемый список.После выполнения этого кода, список примет такой вид:
2 14 14662,063 16522,6Так же можно вычитать, делить, находить корень, складывать, и многое другое.
Не используйте
movapsесли не знаете выравнен ли адрес, проверить это можно разделив адрес на 16, он должен делиться без остатка. Используйтеmovupsразница по скорости минимальная для простых одиночных операций.Imaginary