Расширения SSE/AVX не поддерживают загрузку в регистры XMM/YMM константных значений, например, числовых литералов. В качестве решения мы, конечно, можно определить переменную с нужным
значением и затем использовать одну из инструкций, например, movdqa
для загрузки переменной в регистр XMM/YMM.
.data num word 11 .code main proc movdqu xmm0, oword ptr num ; загружаем данные ret main endp end
Но это не самый быстрый путь. В качестве альтернативы можно применять различные комбинации логических, арифметических операций и операций сравнения. Посмотрим возможные варианты.
Вначала загружаем в один регистр число 0. Для этого используем операцию XOR с помощью инструкции pxor
:
pxor xmm0, xmm0 ; XMM0 = 0
Чтобы установить все биты в регистре XMM или YMM в 1, можно использовать инструкцию pcmpeqb
pcmpeqb xmm1, xmm1 ; XMM1 = -1
Так как любой регистр XMM или YMM равен самому себе, эта инструкция сохраняет 0FFh во всех байтах XMM1.
Например, чтобы получить 1, мы можем вычесть из 0 число -1:
pxor xmm0, xmm0 pcmpeqb xmm1, xmm1 psubb xmm0, xmm1 ; 0 - (-1) = 1
Здесь применяется вычитание байтов с помощью инструкции psubb
, но аналогично можно применять инструкции psubw
или psubd
для получения 16- или 32-битного результата
Если необходимо получить другое число, то можно использовать, например, инструкцию pslld
. Например, если вы хотите загрузить в регистр XMM0 значение
8080808080808080h, вы можете использовать следующую последовательность инструкций:
pxor xmm0, xmm0 pcmpeqb xmm1, xmm1 psubb xmm0, xmm1 pslld xmm0, 7 ; сдвигаем 01h на 4 разряда влево, получаем 80h в каждом байте
Сдвигая число в регистре на разное количество бит, можно получать различные значения.
Для загрузки 2n – 1 (когда все биты вплоть до n-го бита в числе равны 1) можно применять следующий способ:
; для 16-битных дорожек pcmpeqd xmm0, xmm0 psrlw xmm0, 16 - n ; Очищаем правые 16 - n бит в xmm0 ; для 32-битных дорожек pcmpeqd xmm0, xmm0 psrld xmm0, 32 - n ; Очищаем правые 32 - n бит в xmm0 ; для 64-битных дорожек pcmpeqd xmm0, xmm0 psrlq xmm0, 64 - n ; Очищаем правые 64 - n бит в xmm0
Подобным образом можно сдвигать влево:
; для 16-битных дорожек pcmpeqd xmm0, xmm0 psllw xmm0, n ; сбрасываем левые n бит в xmm0 ; для 32-битных дорожек pcmpeqd xmm0, xmm0 pslld xmm0, n ; сбрасываем левые n бит в xmm0 ; для 64-битных дорожек pcmpeqd xmm0, xmm0 psllq xmm0, n ; сбрасываем левые n бит в xmm0
Например, загрузим в XMM1 число 7:
pcmpeqd xmm1, xmm1 psrld xmm1, 32 - 3 ; XMM1 = 7
Здесь сдвигаем двойное слово (32-битное число) на 29 разрядов влево, то есть остается 3 разряда, которые равны 111 или 7 в десятичной.