Upload
others
View
4
Download
0
Embed Size (px)
Citation preview
1111
Презентация не содержит весь
материал лекции. И, поэтому,
не может заменить посещение
лекции студентом
Лекция № 07
Параллельная обработка вещественных чисел на ассемблере.
SSE команды
1. Общие сведения о параллельной обработке вещественных чисел на
ассемблере.
2. Использование команд SSE.
Литература: (вся информация на сайте http://blogs.kpi.kharkov.ua/v2/asm/knigi)1. Рысованый АН. Системное программирование, Ч.1. Программирование в среде masm64 : учеб.-метод. пособие /
А.Н. Рысованый. – Харьков : «Слово», 2017. – 108 с.– На рус. яз.
2. Рысованый А.Н. Системное программирование, Ч.2. Расширенные возможности программирования в среде masm64
: учеб.-метод. пособие / А.Н. Рысованый. – Харьков : «Слово», 2017. – 140 с. – На рус. яз.
3. http://blogs.kpi.kharkov.ua/v2/asm/knigi/
4. masm32.com – сайт Steve Hutchesson
5. wasm.in - сайт Mikl___
Лектор: к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич
[email protected], http://blogs.kpi.kharkov.ua/v2/asm/
«Системное программирование»
НАЦИОНАЛЬНЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
“Харьковский политехнический институт”
Кафедра “Вычислительная техника и программирование”Специальность 123 – «Компьютерная инженерия»;
специализации:
123-01 «Компьютерные системы и сети»;
123-02 «Системное программирование»;
123-03 «Программирование компьютерных игр и мобильных приложений»;
Специальность 125 – «Кибербезопасность»
2
SSE Pentium® III (начало 1999 г.)
SSE может выполнять 70 новых инструкций, которые используют 128-разрядные регистры ХММ0-
ХММ7, MMX и даже обычные 32-битные регистры, если SIMD простаивает без дела.
SSE 2 Intel® Pentium® 4 (июнь 2000 г.)
SSE 2 инструкции, появились с выходом первых Pentium 4 и значительно усовершенствовали SSE первого
поколения. Включает в себя возможность использовать операции со скалярными и упакованными типами
данных. Присутствуют инструкции для потоковой обработки целочисленных MMX данных в 128-битных
XMM регистрах SSE. Новый набор инструкций значительно упростил работу программистов и даже
родилась поговорка – «SSE должен был родиться таким, как SSE 2».
SSE 3 Pentium® 4 на базе 90-нм (февраль 2004 г.)
Также имели название PNI (Prescott New Instructions). Добавлены дополнительные 13 инструкций, которые
расширяют математические возможности DSP и поток управления инструкциями. Больше походит на
косметическое улучшение, чем на практическое, которым было предыдущее обновление.
SSSE 3
Дополнительное обновление для SSE3, которое включает 16 новых инструкций. Позволяет умножать 16-ти
разрядные числа с фиксированной точкой и правильным округлением, вносить слова в инструкции и
переставлять байты в них.
SSE 4 Core 2 Duo E6700 (2007-2008 г.)
Добавлены 54 инструкции, но с оговорками. В SSE 4.1 (появилась в Intel Penryn) содержится урезанный
набор из 47 инструкций, а в SSE 4.2 – полный, из 54 (+7, добавлены в архитектуре Nehalem).
Инструкции работают только с 128-битными XMM0-XMM15. Добавлены POPCNT и дополнительные
целочисленные инструкции. SSE 4 привнесла практически столько нововведений, как в своё время привнесла
первая SSE. Основным направлением при разработке было расширение мультимедийных возможностей —
декодирование игр, ускорение физических и векторных расчётов для игр, ускорение обработки фото, музыки.
Количество регистров ХММ0:
-ХММ0-ХММ7, если используется 32-разрядный режим
-XMM0-XMM15, если используется 64-разрядный режим
Вступление
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
1. Общие сведения о параллельной обработке
вещественных чисел на ассемблереSSE-РАСШИРЕНИЕ
SSE-расширение реализовано как аппаратно-программный модуль, который
включает дополнительные восемь для 32 ОС (16 для х64) регистров
разрядностью в 128 битов, которые имеют обозначение ХММ0 – ХММ7 и
32-разрядный регистр управления/состояния MXCSR.
127 96 95 64 63 32 31 0
Рис. 17.1. Формат данных расширения SSE1
Порядок Мантисса
31 30 23 22 0
Знак
SSE-расширение появилось в процессорах Intel Pentium III и дополняет
MMX-расширение средствами обработки данные с плавающей точкой.
Для SSE1 cодержимым ХММ-регистра является четыре 32-разрядных операнда с
плавающей точкой в коротком формате. Каждое 32-разрядное число с плавающей
запятой имеет 1 знаковый бит, 8 битов порядка и 23 биты мантиссы.
В связи с тем, что форматы команд сопроцессора и SSE-команд не одинаковы, то в
некоторых случаях при разных пределах выравнивания результаты вычислений с
использованием форматов FPU и SSE могут различаться.
3
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
4
Форматы данных SSE1-4 бывают двух типов:
– форматы с плавающей точкой (floating-Point). В 128 разрядах могут
размещаться 4 32-разрядных числа (4 DWORD – Single-Precision), или 2 64-
розрядних числа (2 QWORD – Double-Precision);
– форматы с фиксированной точкой (Integer). В 128 разрядах могут
размещаться один из типов:
16 BYTE;
8 WORD;
4 DWORD;
2 QWORD
1 xmmword.
Тестовая программа для определения поддержки SSE-команд:
.data
testSSE DB 1
.code
…
mov EAX, 1
cpuid ; идентификация микропроцессора
test EDX, 2000000h ; edx:= edx 200 0000h (25 разряд)
jnz exit ; перейти на exit, если не ноль
mov testSSE, 0
exit:
xor EAX, EAX
mov AL, testSSE
ret
end st
Тип команд, которые использует микропроцессор определяется
соответствующими разрядами:
SSE: CPUID.01H:EDX[bit25]=1; Streaming SIMD Extension
SSE2: CPUID.01H:EDX[bit26]=1
SSE3: CPUID.01H:ECX[bit0]=1
SSSE3: CPUID.01H:ECX[bit9]=1
SSE4.1: CPUID.01H:ECX[bit19]=1
SSE4.2: CPUID.01H:ECX[bit20]=1
AVX: CPUID.01H:ECX[bit28]=1; Advanced Vector Extension
FMA: CPUID.01H:ECX[bit12]=1; Fused Multiply Add
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
5
Значительная часть команд SSE может выполняться в двух
вариантах: скалярном и параллельном. Это касается
арифметических команд и команд сравнения.
Команды скалярных операций обрабатывают только
младшие 32-разрядные двойные слова упакованных
операндов, не задевая при этом три старших двойных слова
(суффикс ss (SSE1), суффикс sd (SSE2) ).
Команды параллельных арифметических операций
обрабатывают одновременно 4 двойных слова и имеют в своей
мнемонике суффикс ps (SSE1), суффикс pd (SSE2).
Все команды SSE, кроме специально оговоренных, при работе с памятью требуют
выравнивания операнда на границу 16 байт. В противном случае возникает ошибка
исполнения. Для выравнивания данных компиляторы предоставляют специальные
ключевые слова
ALIGN 16
a dword ?
…
SSE1:суффикс ss скаляр.суффикс ps парал.
SSE2:суффикс sd скаляр.суффикс pd парал.
6
Команды SSE-расширения можно разделить на несколько групп:
- команды для чисел с плавающей точкой;
- команды для целых чисел;
- другие команды.
Команды для чисел с плавающей точкой:
– команды пересылки:
скалярные типы : MOVSS;
упакованные типы : MOVAPS, MOVUPS, MOVLPS, MOVHPS, MOVLHPS, MOVHLPS;
– арифметические команды:
скалярные типы : ADDSS, SUBSS, MULSS, DIVSS, RCPSS, SQRTSS, MAXSS, MINSS, RSQRTSS;
упакованные типы : ADDPS, SUBPS, MULPS, DIVPS, RCPPS, SQRTPS, MAXPS, MINPS, RSQRTPS;
– команды сравнения:
скалярные типы : CMPSS, COMISS, UCOMISS;
упакованные типы : CMPPS;
– перемешивание и распаковка:
упакованы типы : SHUFPS, UNPCKHPS, UNPCKLPS;
– команды для превращения типов:
скалярные типы : CVTSI2SS, CVTSS2SI, CVTTSS2SI;
упакованы типы : CVTPI2PS, CVTPS2PI, CVTTPS2PI;
– битовые логические операции:
упакованные типы : ANDPS, ORPS, XORPS, ANDNPS.
Команды для целых чисел:
– арифметические команды: PMULHUW, PSADBW, PAVGB, PAVGW, PMAXUB, PMINUB, PMAXSW,
PMINSW;
– команды пересылки: PEXTRW, PINSRW;
– другие: PMOVMSKB, PSHUFW.
Другие команды :
– работа с регистром MXCSR: LDMXCSR, STMXCSR;
– управление кэшем и памятью: MOVNTQ, MOVNTPS, MASKMOVQ, PREFETCH0, PREFETCH1,
PREFETCH2, PREFETCHNTA, SFENCE.к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
7
ADDPD xmm, xmm/m128 dest = dest+src - сложение двух пар вещественных чисел удвоенной точности
SUBPD xmm, xmm/m128 dest = dest-src - вычитание двух пар вещественных чисел удвоенной точности
MULPD xmm, xmm/m128 dest = dest*src - умножение двух пар вещественных чисел удвоенной точности
DIVPD xmm, xmm/m128 dest = dest/src - деление двух пар вещественных чисел удвоенной точности
SQRTPD xmm, xmm/m128 dest = sqrt(src) - извлечение квадрат. корня из двух веществ. чисел источника с записью результата в прм.
MAXPD xmm, xmm/m128 dest = max(dest,src) - нахождение в каждой паре большего вещественного числа удвоенной точности
MINPD xmm, xmm/m128dest = min(dest,src) - нахождение в каждой паре меньшего вещественного числа удвоенной точности
ADDSD xmm, xmm/m64 dest = dest+src - сложение двух вещественных чисел удвоенной точности
SUBSD xmm, xmm/m64 dest = dest-src - вычитание двух вещественных чисел удвоенной точности
MULSD xmm, xmm/m64 dest = dest*src - умножение двух вещественных чисел удвоенной точности
DIVSD xmm, xmm/m64 dest = dest/src - деление двух вещественных чисел удвоенной точности
SQRTSD xmm, xmm/m64 dest = sqrt(src) - извлечение квадратного корня из вещественного числа источника с записью результата в прм.
MAXSD xmm, xmm/m64 dest = max(dest,src) - нахождение большего из двух вещественных чисел удвоенной точности
MINSD xmm, xmm/m64 dest = min(dest,src) - нахождение меньшего из двух вещественных чисел удвоенной точности
CVTPD2PS xmm, xmm/m128 dest(0-63) = conv(src) - два вещественных числа преобразуются из формата с двойной точностью в формат с обычной точностью. dest(64-127)=0
CVTPS2PD xmm, xmm/m64dest = conv(src) - два вещественных числа преобразуются из формата с обычной точностью в формат с двойной точностью. Если источником является xmm, то преобразуются два младших числа.
CVTPS2DQ xmm, xmm/m128 dest = conv(src) - 4 вещественных числа представленные с обычной точностью преобразуются в 4 целых 32-х разрядных числа.
CVTTPS2DQ xmm, xmm/m128
dest = conv(src) - 4 вещественных числа представленные с обычной точностью преобразуются в 4 целых 32-х разрядных числа с отсечением остатка.
CVTDQ2PS xmm, xmm/m128 dest = conv(src) - 4 целых 32-х разрядных числа преобразуются в 4 вещественных числа, представленных с обычной точностью.
CVTPD2DQ xmm, xmm/m128 dest(0-63) = conv(src) - два вещественных числа двойной точности преобразуются в два целых 32-х разрядных числа. dest(64-127)=0
CVTTPD2DQ xmm, xmm/m128
dest(0-63) = conv(src) - два вещественных числа двойной точности преобразуются в два целых 32-х разрядных числа с отсечением остатка. dest(64-127)=0
CVTDQ2PD xmm, xmm/m64dest = conv(src) - два целых 32-х разрядных числа преобразуются в два вещественных числа, представленных с двойной точностью. Если источником является xmm, то преобразуются два младших числа.
CVTPD2PI mmx, xmm/m128 dest = conv(src) - два вещественных числа двойной точности преобразуются в два целых 32-х разрядных числа и записываются в регистр mmx
CVTTPD2PI mmx, xmm/m128 dest = conv(src) - два вещественных числа двойной точности преобразуются в два целых 32-х разрядных числа с отсечением остатка и записываются в регистр mmx
CVTPI2PD xmmx, mmx/m64 dest = conv(src) - два целых 32-х разрядных числа, находящихся в регистре mmx, преобразуются в два вещественных числа, представленных с двойной точностью.
(SSE2)
8
CVTSD2SS xmm, xmm/m64 dest(0-31) = conv(src) - вещественное число преобразуется из формата с двойной точностью в формат с обычной точностью. У dest не изменяется содержимое разрядов 32-127.
CVTSS2SD xmm, xmm/m32 dest(0-63) = conv(src) - вещественное число преобразуется из формата с обычной точностью в формат с двойной точностью. Содержимое старшей половины dest не изменяется.
CVTSD2SI r32, xmm/m64 dest = conv(src) - вещественное число двойной точности преобразуются в целое 32-х разрядное число.
CVTTSD2SI r32, xmm/m64 dest(0-63) = conv(src) - вещественное число двойной точности преобразуется в целое 32-х разрядное число.
CVTSI2SD xmm, r32/m32 dest(0-63) = conv(src) - целое 32-х разрядное число преобразуется в вещественное число, представленное с двойной точностью. Содержимое старшей половины dest не изменяется.
CMPPD xmm, xmm/m128, imm8 cmp dest,src - независимо друг от друга сравниваются две пары вещественных чисел. Результат помещается в соответствующие половины dest. Проверяемое условие задает третий операнд (см.
ниже).
CMPSD xmm, xmm/m128, imm8 cmp dest[l],src[l] - сравниваются два вещественных числа. Результат помещается в младшую половину dest[l], содержимое старшей половины dest[h] не изменяется. Проверяемое условие
задает третий операнд
MOVSD xmm, xmm/m64MOVSD xmm/m64, xmm
Пересылка из ОЗУ в младшие 64-разряда xmmПересылка в ОЗУ младших 64-х разрядов xmm
Важно: при копировании содержимого одного регистра xmm в другой, содержимое старшей половины dest не изменяется.
MOVHPD xmm, m64MOVHPD m64, xmm
Пересылка из ОЗУ в старшие 64-разряда xmmПересылка в ОЗУ старших 64-х разрядов xmm
MOVLPD xmm, m64MOVLPD m64, xmm
Пересылка из ОЗУ в младшие 64-разряда xmmПересылка в ОЗУ младших 64-х разрядов xmm
MOVNTPD m128, xmm Пересылка 128-ми разрядного кода в ОЗУ без кешированияВажно: пересылаемый код должен иметь адрес кратный 16-ти, в противном случае возникает
аварийная ситуация (нарушение защиты).
MOVAPD xmm, xmm/m128MOVAPD xmm/m128, xmm
Пересылка 128-bit кода из ОЗУ в регистр xmmПересылка 128-bit кода из регистра xmm в ОЗУ
Важно: пересылаемый код должен иметь адрес кратный 16-ти, в противном случае возникает аварийная ситуация (нарушение защиты).
MOVUPD xmm, xmm/m128MOVUPD xmm/m128, xmm
Пересылка 128-bit кода из ОЗУ в регистр xmmПересылка 128-bit кода из регистра xmm в ОЗУ
Замечание: эта инструкция предназначена для применения в тех случаях, когда данные не выровнены или неизвестно выровнены они или нет.
(SSE2)
9
UNPCKHPD xmm, xmm/m128 dest = Yh, Xh - распаковка: в dest копируется содержимое старших половин src и dest.
UNPCKLPD xmm, xmm/m128 dest = Yl, Xl - распаковка: в dest копируется содержимое младших половин src и dest.
SHUFPD xmm, xmm/m128, imm8 dest = Yh/Yl, Xh/Xl - перегруппировка: bit 0 imm8 указывает какая половина dest копируется в его младшие разряды, bit 1 imm8 указывает какая половина src копируется в старшие разряды dest. В обоих случаях 0 соответствует младшей половине, а 1 - старшей. Например, если dest и
src находятся в одном регистре, то imm8=1 вызовет перестановку чисел в dest.
ANDPD xmm, xmm/m128 dest = dest AND src - логическая функция конъюнкция ("И").Аналоги ANDPS xmm, xmm/m128 и PAND xmm, xmm/m128
ANDNPD xmm, xmm/m128 dest = (NOT dest) AND src - логическая функция без определенного названия.Аналоги ANDNPS xmm, xmm/m128 и PANDN xmm, xmm/m128.
ORPD xmm, xmm/m128 dest = dest OR src - логическая функция дизюнкция ("ИЛИ").Аналоги ORPS xmm, xmm/m128 и POR xmm, xmm/m128.
XORPD xmm, xmm/m128 dest = dest XOR src - логическая функция "исключенное ИЛИ".Аналоги XORPS xmm, xmm/m128 и PXOR xmm, xmm/m128.
LFENCE Приостанавливает считывание данных из кеш до окончания ранее запрошенной операции загрузки.
MFENCE Приостанавливает любые обращения к кеш до окончания всех операций обмена между ОЗУ и кеш.
CFLUCH m8 Очистка строки кеш, номер (адрес) которой в кеш задает операнд, имеющий размер байта.
(SSE2)
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
10
include win64a.inc
.data
mas1 DD 167.13
mas2 DD 23.13
titl1 db "Обработка дробных чисел",0
buf1 dq 2 dup(0.),0 ; буфер
res1 dd 0,0
ifmt db "Через FPU = %d ",10, "Через SSE = %d ",10,10,"Применена инструкция FISTTP — преобразование вещественного числа в целое с
сохранением",
" целочисленного значения и округлением к меньшему.",10,10,
"Автор программы: Рысованый А.Н., каф. ВТП, НТУ ХПИ",0
.code
WinMain proc
sub rsp,28h; cтек: 28h=40d =32d+8; 8 - возврат
mov rbp,rsp
finit
fld mas1
fld mas2
fadd
fisttp res1
movss XMM0,mas1
addss XMM0,mas2
cvtss2si eax,XMM0 ; скалярное преобразование одного мл. числа
invoke wsprintf,addr buf1,ADDR ifmt,res1,eax;
invoke MessageBox,0,addr buf1,addr titl1,MB_OK
invoke ExitProcess,0
WinMain endp
end
Пример: скалярное
сложение двух чисел на
FPU и SSE
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
2. Использование команд SSE
11
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
12
include win64a.inc.datamas1 DD 167.13mas2 DD 23.13titl1 db "Обработка дробных чисел",0buf1 dq 2 dup(0.),0 ; буферres1 dq 0,0tFpu dq 0tSse dq 0ifmt db "Через FPU = %d ",10, "Число тиков FPU = %d ",10,10,"Через SSE = %d ",10,"Число тиков SSE = %d ",10,"Применена инструкция FISTTP — преобразование вещественного числа в целое с сохранением"," целочисленного значения и округлением к меньшему.",10,10,"Автор программы: Рысованый А.Н., каф. ВТП, НТУ ХПИ",0.codeWinMain procsub rsp,28h; cтек: 28h=32d+8; 8 - возврат
mov rbp,rsp
rdtscxchg r14,rax finitfld mas1fld mas2faddfisttp res1rdtscsub rax,r14mov tFpu,rax
rdtsc
sub rax,r14
mov tSse,rax
invoke wsprintf,addr buf1,ADDR
ifmt,res1,tFpu,r10,tSse;
invoke MessageBox,0,addr buf1,addr
titl1,MB_ICONINFORMATION
invoke ExitProcess,0
WinMain endp
end
rdtsc
xchg r14,rax
movss XMM0,mas1
addss XMM0,mas2
cvtss2si eax,XMM0 ;
movsxd r10,eax
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
Пример сложения двух чисел на FPU и SSEс выводом числа тактов на эту операцию
13
Пример перемещения массивов через FPU и SSEс выводом числа тактов на эти операцииinclude win64a.inc
.datamas1 DD 20 dup(0,2,4,6) ; резервирование ячеек памяти для mas1
dd 16 dup(1) ; 80+16=96len1 equ ($-mas1)/type mas1mas2 DD len1 dup(0) ; резервирование ячеек памяти для mas2
titl1 db "Пересылка целых чисел",0buf1 dq 0,0 ; буферtFpu dq 0tSse dq 0ifmt db "Число тиков FPU = %d ",10,10,"Число тиков SSE = %d ",10,
"Автор программы: Рысованый А.Н., каф. ВТП, НТУ ХПИ",0
.codeWinMain procsub rsp,28h; cтек: 28h=32d+8; 8 - возвратmov rbp,rsprdtscxchg r14,rax finitmov rcx,len1 ; количество чисел массива mas1
lea rsi,mas1 ; адрес начала массива mas1lea rdi,mas2 ; адрес начала массива mas2@@: fild dword ptr [rsi] ; загрузка целого числа
fistp dword ptr [rdi]add rsi,type mas1; add rdi,type mas1; loop @brdtscsub rax,r14mov tFpu,rax
rdtscxchg r14,rax mov rcx,len1 ; количество чисел массива mas1lea rsi,mas1 ; адрес начала массива mas1lea rdi,mas2 ; адрес начала массива mas2@@: movups XMM0,mas1 ; пересылка 4-x целых чиселmovups mas2,xmm0add rsi,type mas1; add rdi,type mas1;loop @brdtscsub rax,r14mov tSse,raxinvoke wsprintf,addr buf1,ADDR ifmt,tFpu,tSse;invoke MessageBox,0,addr buf1,addr titl1,MB_ICONINFORMATIONinvoke ExitProcess,0WinMain endpend
14
title ; masm64
include \masm32\include64\masm64rt.inc
.data ;
mas1 DD 20 dup(0,2,4,6) ; резервирование ячеек памяти для mas1
dd 16 dup(1) ; 80+16=96
len1 equ ($-mas1)/type mas1
mas2 DD len1 dup(0) ; резервирование ячеек памяти для mas2
titl1 db "Пересылка целых чисел",0
buf1 dq 0,0 ; буфер
tFpu dq 0
tSse dq 0
ifmt db "Число тиков FPU = %d ",10,10,"Число тиков SSE = %d ",10,
"Автор программы: Рысованый А.Н., каф. ВТП, НТУ ХПИ",0
.code
proc1 proc ; процедура
rdtsc
xchg r14,rax
finit
mov rcx,len1 ; количество чисел массива mas1
lea rsi,mas1 ; адрес начала массива mas1
lea rdi,mas2 ; адрес начала массива mas2
@@: fild dword ptr [rsi] ; загрузка целого числа
fistp dword ptr [rdi]
add rsi,type mas1;
add rdi,type mas1;
loop @b
rdtsc
sub rax,r14
mov tFpu,rax
ret
proc1 endp ;
proc2 proc ; процедура
rdtsc
xchg r14,rax
mov rcx,len1 ; количество чисел массива mas1
lea rsi,mas1 ; адрес начала массива mas1
lea rdi,mas2 ; адрес начала массива mas2
@@: movups XMM0,mas1 ; пересылка 4-x целых
чисел
movups mas2,xmm0
add rsi,type mas1;
add rdi,type mas1;
loop @b
rdtsc
sub rax,r14
mov tSse,rax
ret
proc2 endp;
15
entry_point proc
invoke proc1
invoke proc2
invoke wsprintf,addr buf1,ADDR ifmt,tFpu,tSse;
invoke MessageBox,0,addr buf1,addr
titl1,MB_ICONINFORMATION
invoke ExitProcess,0
entry_point endp
endBat-файл:
@echo off
set appname=22
del %appname%.obj
del %appname%.exe
\masm32\bin64\ml64.exe /c /nologo %appname%.asm
\masm32\bin64\link.exe /SUBSYSTEM:WINDOWS
/ENTRY:entry_point /nologo /LARGEADDRESSAWARE
%appname%.obj
dir %appname%.*
pause
Рис. Процесс получения
результата командой movhlps
XMM0 := 6. 4. 2. 0
XMM1 := 7. 5. 3. 1.
XMM0 := 6. 4. 7. 5.
ст. мол. ст. мол.
Для того, чтобы в отладчике OllyDbg v.1.10 увидеть регистры
SSE, необходимо поставить метку в пункте Опции/Опции
отладки/Registers/Decode SSE.
OllyDbg 2.01 - полная поддержка SSE и AVX инструкций.
16
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
Текст. Пример использования команд передачи данных:
include win64a.inc
.data
mas1 DD 0, 2.,4.,6. ; резервирование ячеек памяти для массива mas1
mas2 DD 1.,3.,5.,7. ; резервирование ячеек памяти для массива mas2
res dq 2 dup (0)titl1 db "Обработка дробных чисел",0
buf1 dq 2 dup(0.),0 ; буфер
ifmt db "res[0] = %d, ","res[4] = %d, ","res[8] = %d, ","res[12] = %d ",10,10,
"CVTPS2DQ - преобразование 4-х упакованных чисел одинарной точности в ",
"4-е 32-разрядных числа",10,10,
"Автор программы: Рысованый А.Н., каф. ВТП, НТУ ХПИ",0
.code
WinMain procsub rsp,28h; cтек: 28h=32d+8; 8 - возврат
mov rbp,rsp
movups XMM0,mas1 ; пересылка 4-х 32-разрядных чисел массива mas1
movups XMM1,mas2 ; пересылка 4-х 32-разрядных чисел массива mas2
movhlps XMM0,XMM1 ; пересылка с обменом невыровненными 64 битами
cvtps2dq xmm3,xmm0
movupd res,xmm3
invoke wsprintf,addr buf1,ADDR ifmt,res[0],res[4],res[8],res[12]
invoke MessageBox,0,addr buf1,addr titl1, MB_ICONINFORMATION
invoke ExitProcess,0
WinMain endp17
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
18
; Сложение первого и последнего элементов структуры
include win64a.inc
DATE1 STRUCT ; СТРУКТУРА с именем Date1
a1 dd ? ; имя первого поля структуры
a2 dd ? ; имя второго поля структуры
a3 dd ? ; имя третьего поля структуры
a4 dd ? ; имя четвертого поля структуры
DATE1 ENDS ; окончание структуры
.data
Car1 DATE1 <1.1,2.2,3.3,4.4> ; структура с именем Car1
titl1 db 'Сложение 1-го и 4-го элементов массива <1.1,2.2,3.3,4.4>',0
fmt db "Результат - %d",10,10,
"Применена команда cvtss2si - конвертирует сжатое значение с ПТ одинарной точности",
"в 32-разрядное целое число", 10,10,
"Автор программы: Рысованый А.Н., каф. ВТП, НТУ ХПИ",0
buf1 db 0.code ;
WinMain proc
sub rsp,28h; cтек: 28h=32d+8; 8 - возврат
mov rbp,rsp
movss XMM0,Car1.a1
addss XMM0,Car1.a4
;movss res,XMM0
cvttss2si eax,xmm0;fld res
;fisttp res1
invoke wsprintf,addr buf1,addr fmt,eax;res1
invoke MessageBox,0,addr buf1,addr titl1,MB_ICONINFORMATIONinvoke ExitProcess,0
WinMain endp
end
Сложение первого и
последнего элементов
структуры при помощи
команд SSE
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
19
Пример. Сложение двух массивов вещественных чисел командами SSE
include win64a.inc
.data
mas1 dd 2.4, 7.1, 6.8, 2.6,21.9, 6.12,7.54, 8.1, 9.0, 10.65
mas2 dd -1.34,-5.0,-3.54,1.5,-5.8,-6.53,7.5, -8.34,-9.54,-10.1
len1 equ ($-mas2)/ type mas2 ; количество чисел массива mas2
res dd len1 DUP(0),0 ; резервирование байтов под переменнуюtitl1 db "Результат параллельного сложения. SSE. masm64",0
buf1 dd len1 DUP(0),0 ; буфер вывода сообщения
ifmt db "Результат сложения: %d ,%d ,%d ,%d ,%d ,%d ,%d ,%d ,%d ,%d",10,10,
«Использовались команды округления: cvtps2dq, cvtss2si",10,10,
"Автор программы: Рысованый А.Н., каф. ВТП, НТУ ХПИ",0
.code ;
WinMain procsub rsp,28h; cтек: 28h=32d+8; 8 - возврат
mov rbp,rsp
mov rax,len1 ; количество чисел в массиве
mov rbx,4 ; количество одновременно занесенных чисел в XMM
xor rdx,rdx ; сложение по модулем 2 (обнуление)
div rbx ; eax := 4 – количество циклов, edx := 1
mov rcx,rax ; загрузка счетчика
lea rsi,mas1 ; esi := addr mas1
lea rdi,mas2 ; edi := addr mas2
lea rbx,res ; занесение начала массива
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
20
m1: movups XMM0,[rsi] ;mas1 ;
movups XMM1,[rdi] ;mas2 ;
addps xmm0,xmm1
cvtps2dq xmm2,xmm0
movups xmmword ptr [rbx],xmm2
add rsi,16;type mas2 ; подготовка адреса mas1 к новому считыванию
add rdi,16 ; подготовка адреса mas2 к новому считыванию
add rbx,16 ; подготовка адреса к новому считыванию
loop m1 ; ecx := ecx – 1 и переход, если ecx /= 0
cmp rdx,0 ; определение остатка необработанных элементов массивов
jz exit ; если элементы закончились, то перейти на exit
mov rcx,rdx ; занесение в счетчик количества необработанных чисел
m2: movss xmm3,dword ptr [rsi] ; занесение необработанного элемента из mas1
addss xmm3,dword ptr [rdi] ; сложение элементов двух массивов
cvtss2si eax,xmm3 ; float-число в целое 32-разрядное число
mov dword ptr [rbx],eax ; сохранение результата
add rsi,4 ; подготовка к выборке элемента из mas1
add rdi,4 ; подготовка к выборке элемента из mas2
add rbx,4 ; подготовка к записи результата в память
loop m2 ; ecx := ecx – 1 и переход, если ecx /= 0
exit:
invoke wsprintf,addr buf1,addr ifmt,res[0],res[4],res[8],res[12],res[16],res[20],
res[24],res[28],res[32],res[36]
invoke MessageBox,0,addr buf1,addr titl1,MB_ICONINFORMATION
invoke ExitProcess,0
WinMain endp
endк.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
21
; Скалярное сложение массивов вещественных чисел
include win64a.inc
.data
mas1 DD 12.13,-15.01, -3.1, 77.1 ; резервирование памяти
mas2 DD 25.13, 35.01,-34.5, 23.01 ;
len1 EQU ($-mas2)/ type mas2 ; количество двойных слов mas2
res dd 4 dup(?),0 ;
titl1 db "Параллельная обработка массива чисел командами SSE",0
buf dd 4 dup(?)
fmt db "mas1 12.13,-15.01, -3.1, 77.1",10,
"mas2 25.13, 35.01,-34.5, 23.01",10,10,
"addss: %d,", 9,"%d, %d, %d ",10,
"Автор программы: Рысованый А.Н., каф. ВТП, НТУ ХПИ",0
.code ;
WinMain proc
sub rsp,28h; cтек: 28h=32d+8; 8 - возврат
mov rbp,rsp
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
22
lea rsi,mas1 ; esi := addr mas1
lea rdi,mas2 ; edi := addr mas2
lea rbx,res
mov rcx,len1 ; счетчик
@m1:
movups XMM0,[rsi] ;mas1 ;
movups XMM1,[rdi] ;mas2 ;
addss xmm0,xmm1
cvtss2si eax,XMM0 ; float-число в целое 32-разрядное число со знаком
mov dword ptr [rbx],eax
add rsi,4 ;
add rdi,4 ;
add rbx,4 ;
loop @m1;
invoke wsprintf,ADDR buf,ADDR fmt,res[0],res[4],res[8],res[12]
invoke MessageBox,0,ADDR buf,ADDR titl1, MB_ICONINFORMATION
invoke ExitProcess,0
WinMain endp
end
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
23
masm64. Числа а є{a1,a2,a3} заданы массивом и имеют
размерность Real8. Вычислить уравнение d/b sqrt(a) + a
с использованием команд SSEinclude win64a.inc ; подключаемые библиотекиIDI_ICON EQU 1001 ; идентификатор иконкиMSGBOXPARAMSA STRUCT
cbSize DWORD ?,?hwndOwner QWORD ?hInstance QWORD ?lpszText QWORD ?lpszCaption QWORD ?dwStyle DWORD ?,?lpszIcon QWORD ?dwContextHelpId QWORD ?lpfnMsgBoxCallback QWORD ?dwLanguageId DWORD ?,?
MSGBOXPARAMSA ENDS
.data
params MSGBOXPARAMSA <>
arr1 real8 16.,25.,36.,1244. ; массив чисел А
len1 equ ($-arr1)/type arr1
arr2 real8 2.,4.,16. ; b, c, d
tit1 db "masm64. Результат циклического вычисления уравнения. SSE2. ",0
res dq len1 DUP(0),0 ;
buf1 dd len1 DUP(0),0 ; буфер вывода сообщения
ifmt db "masm64. Массив ai: 16., 25., 36., 1244.",10,
9,"Числа: b, c, d := 2., 4., 16.",10,
"Результаты вычисления: %d ,%d ,%d ,%d ",10,10,
"Автор: Рысованый А.Н., каф. ВТП, фак. КИТ, НТУ ХПИ",10,
9,"Сайт: http://blogs.kpi.kharkov.ua/v2/asm/",0к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
24
code ; уравнение d/b sqrt(a) + a
WinMain proc
sub rsp,28h; cтек: 28h=32d+8; 8 - возврат
mov rbp,rsp
mov rcx,len1
lea rdx,res
lea rbx,arr1
movsd xmm1,arr2[0] ; xmm1 - b
movsd xmm2,arr2[8] ; xmm2 - c
movsd xmm3,arr2[16] ; xmm3 - d
divsd xmm3,xmm1 ; d/b
@@:
movsd xmm0,qword ptr[rbx] ; xmm0 - a
sqrtsd xmm4,xmm0 ;sqrt(a)
mulsd xmm4,xmm3 ; d/b x sqrt(a)
addsd xmm4,xmm0 ; d/b x sqrt(a) + a
cvttsd2si eax,xmm4 ;
;movsxd r15,eax
mov [rdx],eax ; сохранение результата
add rbx,8
add rdx,8
dec rcx
jnz @b
invoke wsprintf,addr buf1,addr ifmt,res,res[8],res[16],res[24]
;invoke MessageBox,0,addr buf1,addr tit1,MB_ICONINFORMATION
mov params.cbSize,SIZEOF MSGBOXPARAMSA ; размер
структуры
mov params.hwndOwner,0 ; дескриптор окна владельца
invoke GetModuleHandle,0 ; получение дескриптора программы
mov params.hInstance,rax ; сохранение дескриптора программы
lea rax, buf1 ; !!! адрес сообщения
mov params.lpszText,rax
lea rax,tit1 ;!!!Caption ; адрес заглавия окна
mov params.lpszCaption,rax
mov params.dwStyle,MB_USERICON ; стиль окна
mov params.lpszIcon,IDI_ICON ; ресурс значка
mov params.dwContextHelpId,0 ; контекст справки
mov params.lpfnMsgBoxCallback,0 ;
mov params.dwLanguageId,LANG_NEUTRAL ; язык сообщения
lea rcx,params
invoke MessageBoxIndirect
invoke ExitProcess,0
WinMain endp
end
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
Пример 17.2. Выполнить параллельное сравнение с помощью SSE-команд 2-х массивов. Если
все элементы первого массива больше, чем одноименные элементы второго массива, то
выполнить операцию (a – c)b – d/b, де а = 3,0; b = 0.2; с = 1,0; d = 2,2; иначе - выполнить
операцию d/b.
.data
mas1 dd -1.3, 2.1, 3.8, 1.0, 5.4, 6.12,7.54, 8.1, 9.0, 10.65
mas2 dd -1., -5.0,-3.54,1.5,-5.8,-6.53,7.5, -8.34,-9.54,-10.1
len equ ($-mas2)/ type mas2 ; количество чисел массива mas2
a1 dd 3.0 ;
b1 dd 0.2 ;
c1 dd 1.0 ;
d1 dd 2.2 ;
fmt db "IF mas1>mas2, то (a – c)b – d/b",10,"иначе d/b, где d = 2.2, b = 0.2",10,
"Результат = %d",10,10,"Автор: Рысованый А.Н., каф. ВТП, НТУ ХПИ",0
titl1 db "masm64. Параллельное сравнение с помощью SSE-команд",0; название окошка
buf1 dq 0,0
.code
WinMain proc
sub rsp,28h; cтек: 28h=32d+8; 8 - возврат
mov rbp,rsp
mov eax,len ;
mov ebx,4 ; количество 32-разрядных чисел в 128-разрядном регистре
xor edx,edx ;
div ebx ; определение количества циклов для параллельного считывания и остатка
mov ecx,eax ; счетчик циклов для параллельного считывания
lea rsi,mas1 ;
lea rdi,mas2 ; 25
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
lea rsi,mas1 ; lea rdi,mas2 ;
next: movups XMM0,xmmword ptr [rsi]; 4- 32 числа из mas1movups XMM1,[rdi] ; 4- 32 числа из mas2cmpltps XMM0,XMM1 ; сравнение на меньше: если меньше, то нулиmovmskps ebx,XMM0 ; перенесение знаковых битовadd rsi,16 ; подготовка адреса для нового считывания mas1add rdi,16 ; подготовка адреса для нового считывания mas2dec ecx ; уменьшение счетчика цикловjnz m1 ; проверка счетчика на ненулевое значениеjmp m2 ;
m1: mov r10,rbx shl r10,4 ; сдвиг налево на 4 битаjmp next ; на новый цикл
m2: cmp edx,0 ; проверка остаткаjz _end ; mov ecx,edx ; если в остатке не нуль, то установка счетчика
m4: movss XMM0,dword ptr[rsi] ; movss XMM1,dword ptr[rdi] ; comiss XMM0,XMM1 ; сравнение младших чисел массивов
jg @f ; если большеshl r10,1 ; сдвиг влево на 1 разрядinc r10 ; встановление 1, поскольку XMM0[0] < XMM1[0]jmp m3
@@:
26
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
@@: ...
jmp @b; ссылка на предыдущую метку @@ (наверх)
jnz @f; ссылка на следующую метку @@ (вниз)
@@: ...
27
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
shl r10,1 ; сдвиг налево на 1 разряд
m3:
add rsi,4 ; адреса для нового числа mas1
add rdi,4 ; адреса для нового числа mas2
loop m4
_end: cmp r10,0 ; проверка знаковых битов
jz mb ; если ebx = 0, то перейти на метку mb
movss xmm2,dword ptr d1
movss xmm3,dword ptr b1
divss xmm2,xmm3 ; d/b
jmp m5
mb: movss xmm2,dword ptr a1
subss xmm4,dword ptr c1 ; a - c
mulss xmm2,b1 ;(a - c)b
movss xmm5,dword ptr d1
movss xmm6,dword ptr b1 ;
divss xmm5,xmm6 ; d/b
subss xmm2,xmm5 ;(a - c)b - d/b
m5: cvttss2si eax,xmm2
movsxd r15,eax
invoke wsprintf,addr buf1,addr fmt,r15
invoke MessageBox,0,addr buf1,ADDR titl1,MB_ICONINFORMATION
invoke ExitProcess,0
WinMain endp
end
28
UNPCKHPD
приемник, источникОперация распаковки: передача
старших половин чисел
Команда unpckhpd выполняет операцию распаковки: прм = прдh, прмh – у прм
копируется содержание старших половин прд и прм:
unpckhpd XММ0, XММ1
Рис. 7.2. Схема дії команди unpckhpd XММ0, XММ1
XММ0 XММ1
unpckhpd XММ0, XММ1
XММ0
128 0 128 0
128 0
Команда unpckhpd
Упакованные числа необходимо распаковать перед их выводом,
например, через MessageBox
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
29
Пример. Выполнить параллельный поиск максимального значения в парах упакованных 64-разрядных
чисел с плавающей точкой двойной точности. Сложить все результаты и выполнить преобразование
вещественного числа двойной точности в целое 32-разрядное число.
; masm64.
include win64a.inc ; подключаемые библиотеки
.data
mas1 dq 1.,2. ; массив 1
mas2 dq 3.,4. ; массив 2
mas3 dq 5.,6. ; массив 3
mas4 dq 7.,8.1 ; массив 4
titl1 db "SSE2-команды. Параллельный поиск max значений в массивах",0 ; название окна
fmt db "Параллельный поиск max значений",0Ah,0Dh,\
"в парах упакованных 64-разрядных чисел с плавающей точ-кой.",0Ah,0Dh,0Dh,
"Массивы:",0Ah,0Dh,"mas1: 1., 2.",0Ah,0Dh,"mas2: 3., 4.",0Ah,0Dh,0Dh,
"mas3: 5., 6.",0Ah,0Dh,"mas4: 7., 8.",0Ah,0Dh,0Dh,\
"Сумма максимальных значений массивов= %d",10,
"Автор: Рысованый А.Н., каф. ВТП, НТУ ХПИ",0
buf1 dq 0 ; буфер
.code
SSE2
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
30
.code
WinMain procsub rsp,28h; cтек: 28h=32d+8; 8 - возврат
mov rbp,rsp
movupd Xmm0,mas1 ; занесение masl к ХММО
movupd Xmm1,mas2 ; занесение mas2 к Хмм1
movupd Xmm2,mas3 ; занесение mas3 к Хмм2
movupd Xmm3,mas4 ; занесение mas4 к ХММЗ
maxpd Xmm0,xmm1 ; нахождение максимумов в mas1 и mas2
maxpd Xmm2,xmm3 ; нахождение максимумов в mas3 и mas4
addpd Xmm0,xmm2 ; сумма максимумов
unpckhpd xmm4,xmm0 ; распаковка ст. ч. xmm0 в ст. ч. xmm4 и сдвиг мл. ч. xmm4
unpckhpd xmm4,xmm5 ; перемещение ст. части xmm4 в мл. ч. xmm4
unpcklpd xmm5,xmm0 ; распаковка мл. ч. xmm0 в ст. ч. xmm5 и сдвиг мл. ч. xmm5
unpckhpd xmm5,xmm6 ; перемещение ст. части xmm5 в мл. часть xmm5
addpd xmm4,xmm5 ; сумма xmm4 и xmm5
cvtpd2pi MM0,xmm4 ; превращение в 32-разрядное число
movd dword ptr ebx,mm0 ; занесение содержимого ММ0 в ebx
invoke wsprintf,addr buf1,addr fmt,ebx ; преобразование
invoke MessageBox,0,addr buf1,ADDR titl1,MB_ICONINFORMATION+90000h
invoke ExitProcess,0
WinMain endp
endСумма максимальных чисел в массиве командой addpd XMM0,XMM2 сохраняется в ХММ0. В связи с тем,
что это число является упакованным с двойной точностью, то для того, чтобы его вывести функцией
MessageBox, это число необходимо распаковать. Старшие и младшие части результата XMM0 необходимо
распаковать и сложить. Для этого сначала старшая часть регистра xmm0 командой unpckhpd xmm4,xmm0
распаковывается и заносится в старшую часть xmm4, а предыдущее значение ст. части xmm4 сдвигается в
младшую часть. А сложение будет осуществляться в младших частях выбранного регистра. Поэтому
старшая часть максимума из регистра xmm4 передается в младшую часть того же регистра xmm4 командой
unpckhpd xmm4,xmm5.
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
31
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
32
; masm64. include win64a.inc ; подключаемые библиотеки.data mas1 dd 1.,2.,3.,4.titl1 db "Сложение чисел массива ",0 ;fmt db "Сложение 32-разрядных дробных чисел одного массива",10,"с использованием команд SSE",10,"mas1: 1., 2., 3., 4.", 10,13, "Сумма: %d",10,"Автор: Рысованый А.Н., каф. ВТП, НТУ ХПИ",0buf1 dq 0,0 ; буфер .codeWinMain proc
sub rsp,28h; cтек: 28h=32d+8; 8 - возврат
mov rbp,rsp
movaps XMM0,mas1 ; XMM0:= 4. 3. 2. 1.movaps XMM1,XMM0 ; XMM1:= 4. 3. 2. 1.shufps XMM1,XMM1,11111001b ; XMM1:= 4. 4. 3. 2.addss XMM0,XMM1 ; XMM0:= 4. 3. 2. 3.shufps XMM1,XMM1,11111001b ; XMM1:= 4. 4. 4. 3.addss XMM0,XMM1 ; XMM0:= 4. 3. 2. 6.shufps XMM1,XMM1,11111001b ; XMM1:= 4. 4. 4. 4.addss XMM0,XMM1 ; XMM0:= 4. 3. 2. 10.cvttss2si eax,xmm0 movsxd r15,eax
invoke wsprintf,addr buf1,addr fmt,r15
invoke MessageBox,0,addr buf1,ADDR titl1,MB_ICONINFORMATION
invoke ExitProcess,0
WinMain endp
end
len1 equ ($-mas1)/type mas1
…
mov ecx,len1-1
movaps XMM0, mas1
movaps XMM1, XMM0
m1:
shufps XMM1,XMM1,11111001b
addss XMM0,XMM1
loop m1
movups _res, XMM0 ;
shufps xmm0,xmm0,00011011
– команда выполняет перестановку
всех четырех 32 битовых частей
регистра XММ0 в обратном порядке
(перемещение 3-го (11) числа на
место расположения нулевого
числа; перемещение 2-го (10) числа
на место первого числа,
перемещения 1-го (01) числа на
место второго числа, перемещение
0-го (00) числа на место четвертого
числа.
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
33
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич, [email protected]
34
; Сумма нечетных элементов двух одинаковых массивов для чисел размерностью DD и DQinclude win64a.inc.data;arr1 dq 4 dup(0.,1.) arr1 dq 1.,2.,3.,6.len1 equ ($-arr1)/type arr1res1 dq 2 dup(0.)titl1 db "Результат сложения. SSE. masm64",0buf1 dq 50 DUP(0),0 ; буфер вывода сообщенияifmt db "Сумма нечетных элементов массива для чисел размерностью dq",10," Сумма: %d, время %d тиков.",10,10,"Сумма нечетных элементов массива для чисел размерностью dd",10," Сумма: %d, время %d тиков.",10,10,"Автор программы: Рысованый А.Н., г.Харьков, НТУ ХПИ",0.code ;WinMain procsub rsp,28h; cтек: 28h=32d+8; 8 - возвратmov rbp,rsprdtsc ; получение числа тактов в регистрe raxmov r10,rax ; обмен значениями регистровmov rcx,len1/2lea rdi,arr1lea rsi,res1movups XMM0,[rsi];@@:movups XMM1,[rdi];addpd XMM0,XMM1add rdi,8*2loop @bshufpd XMM0,XMM0,0101b ;cvttsd2si r12,xmm0rdtsc ; получение числа тактовmov r11,raxsub r11,r10 ; вычитание из последнего числа тактов предыдущего числа
35
.data
res2 dd 4 dup(0.)
arr2 dd 1.,2.,3.,6.
len2 equ ($-arr2)/type arr2
.code
rdtsc ; получение числа тактов в регистрe rax
mov r10,rax ; обмен значениями регистров
mov rcx,len1/4
lea rdi,arr2
lea rsi,res2
movups XMM2,[rsi];
m2:
movups XMM3,[rdi];
addpd XMM2,XMM3
add rdi,8*4
loop m2
movups xmm3,xmm2
shufps XMM3,XMM3,11100101b ;
cvttss2si eax,xmm3
shufps XMM2,XMM2,11100111b ;
cvttss2si eax,xmm2
addss xmm3,xmm2
cvttss2si eax,xmm3
movsxd r15,eax
rdtsc ; получение числа тактов
mov r14,rax
sub r14,r10 ; вычитание из последнего числа тактов предыдущего числа
invoke wsprintf,addr buf1,addr ifmt,r12,r11, r15,r14
invoke MessageBox,0,addr buf1,addr titl1,MB_ICONINFORMATION
invoke ExitProcess,0
WinMain endp
end
262626262626
«Системное программирование»
к.т.н., проф. НТУ ХПИ Рысованый Александр Николаевич,
[email protected], [email protected]
личный сайт: http://blogs.kpi.kharkov.ua/v2/asm/
НАЦИОНАЛЬНЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
“Харьковский политехнический институт”
Кафедра “Вычислительная техника и программирование”
Специальность 123 – «Компьютерная инженерия»;
специализации:
123-01 «Компьютерные системы и сети»;
123-02 «Системное программирование»;
123-03 «Программирование компьютерных игр и мобильных приложений»;
Специальность 125 – «Кибербезопасность»