OPTION DOTNAME include includes\temphls.inc include includes\win64.inc include includes\user32.inc includelib includes\user32.lib OPTION PROLOGUE:none OPTION EPILOGUE:none .data AppName: ;DLL Skeleton dw 0044h,004ch,004ch,0020h,0053h,006bh,0065h,006ch,0065h,0074h,006fh,006eh,0000h HelloMsg: ;Вызвана функция TestHello dw 0412h,044bh,0437h,0432h,0430h,043dh,0430h,0020h,0444h,0443h,043dh,043ah,0446h,0438h,044fh,0020h,0054h,0065h,0073h,0074h,0048h,0065h,006ch,006ch,006fh,0000h LoadMsg: ;DLL Загружена dw 0044h,004ch,004ch,0020h,0417h,0430h,0433h,0440h,0443h,0436h,0435h,043dh,0430h,0000h UnloadMsg: ;DLL выгружена dw 0044h,004ch,004ch,0020h,0432h,044bh,0433h,0440h,0443h,0436h,0435h,043dh,0430h,0000h SHAMsg: ;"SHA256 Запущена!" dw 0053h,0048h,0041h,0032h,0035h,0036h,0020h,0417h,0430h,043fh,0443h,0449h,0435h,043dh,0430h,0021h,0000h DllAtata: ;Неожиданно прилетел DLL_THREAD_ATTACH dw 041dh,0435h,043eh,0436h,0438h,0434h,0430h,043dh,043dh,043eh,0020h,043fh,0440h,0438h,043bh,0435h,0442h,0435h,043bh,0020h,0044h,004ch,004ch,005fh,0054h,0048h,0052h,0045h,0041h,0044h,005fh,0041h,0054h,0054h,0041h,0043h,0048h,0000h prime2nums: ;Простые числа от 2 до 311 dw 02h,03h,05h,07h,0Bh,0Dh,11h,13h,17h,1Dh,1Fh,25h,29h,2Bh,2Fh,35h,3Bh,3Dh,43h,47h,49h,4Fh,53h,59h dw 61h,65h,67h,6Bh,6Dh,71h,7Fh,83h,89h,8Bh,95h,97h,9Dh,0A3h,0A7h,0ADh,0B3h,0B5h,0BFh,0C1h,0C5h,0C7h,0D3h,0DFh dw 0E3h,0E5h,0E9h,0EFh,0F1h,0FBh,101h,107h,10Dh,10Fh,115h,119h,11Bh,125h,133h,137h DllDetata: ;Неожиданно прилетел DLL_PROCESS_DETACH dw 041dh,0435h,043eh,0436h,0438h,0434h,0430h,043dh,043dh,043eh,0020h,043fh,0440h,0438h,043bh,0435h,0442h,0435h,\ 043bh,0020h,0044h,004ch,004ch,005fh,0050h,0052h,004fh,0043h,0045h,0053h,0053h,005fh,0044h,0045h,0054h,0041h,0043h,0048h,0000h prime_nums: ; 8 байт с простыми числами от 2 до 19 db 0 dup (8) align 16 my3sqrt REAL8 0.3333333333333333333333333333 ;xmminst dq 12232434,13342342342 xmmhash xmmword 0 dup (4); 4 Байта в которых хранится хэш k_konst dd 0 dup (64) ;64 32-битных значения инициированных первыми 32 битами дробной части кубических корней от 2 о 311 myXMMSAVE xmmword 0 dup (10) ;глобальная переменная для сохранения/восстановления регистров XMM6-XMM15 (неизменяемые) myRnSAVE dq 0 dup (4) ;глобальная переменная для сохранения/восстановления регистров R12-R15 (неизменяемые) .code DllMain proc hInstDLL:QWORD, reason:QWORD, unused:QWORD ;push rbp ;mov rbp,rsp sub rsp,28h .if edx==DLL_PROCESS_ATTACH ;Обрабатываю событие вызова DLL call _isAvxSupported pshufd xmm0,xmm0,10010011b ;Перераспределяет 32-битные qword'ы в xmm согласно битовой маске: 2 бита, числа от 0-3 сообщают pshufd xmm0,xmm0,10010011b ;слева направо новое расположение qword'ов в регистре XMM. Например: 3-2-1-0 -> 2-1-0-3(10010011b) pshufd xmm0,xmm0,10010011b pshufd xmm0,xmm0,10010011b mov eax,001020304h ;вычисляю Σ0 xor rcx,rcx ror eax,2 xor ecx,eax ror eax,11 xor ecx,eax ror eax,9 xor ecx,eax ;вычисляю ключ mov eax,001020304h xor eax,ecx mov edx,eax ; в EDX - ключ mov eax,001020304h xor eax,edx ;смотрю, подходит ли он для других чисел mov eax,005040304h ;вычисляю Σ0 xor rcx,rcx ror eax,2 xor ecx,eax ror eax,11 xor ecx,eax ror eax,9 xor ecx,eax ;Подставляю ключ из первого примера mov eax,005040304h xor eax,edx lea rdx,LoadMsg ;Указатель на сообщение "DLL загружена" .elseif edx==DLL_PROCESS_DETACH ;Обрабатываю событие закрытия DLL lea rdx,UnloadMsg ;Указатель на сообщение "DLL выгружена" .elseif edx==DLL_THREAD_ATTACH ;Обрабатываю событие создания треда в вызывающем процессе ;(ох и попило крови это событие: не обрабатывал, а по-умолчанию падало на другой обработчик) ;lea rdx,DllAtata ;Указатель на сообщение "неожиданно прилетел DLL_THREAD_ATTACH" add rsp,28h ;восстанавливаю вершину стека xor rax,rax ;возвращаю ноль ret ;Выхожу .elseif edx==DLL_THREAD_DETACH ;Обрабатываю событие закрытия треда в вызывающем процессе ;lea rdx,DllDetata ;Указатель на сообщение "Неожиданно прилетел DLL_PROCESS_DETACH" add rsp,28h ;восстанавливаю вершину стека xor rax,rax ;возвращаю ноль ret ;Выхожу .endif mov r9d,MB_OK ; jmp exit DllMain Endp TestHello proc sub rsp,28h lea rdx,HelloMsg mov r9d,MB_OK + MB_ICONERROR exit:: lea r8,AppName xor rcx,rcx call MessageBoxW ;mov rsp,rbp ;pop rbp add rsp,28h mov rax,TRUE ret TestHello endp ;Sha256 - Функция, принимающая в качестве параметра 1-Адрес хешируемого объекта;2-его полный размер; 3-Размер отрезка; 4-последний ли он?. Возвращаемое значение: NULL в случае успеха Sha256 proc __fastcall enter 128,0 leave xor rax,rax ret Sha256 Endp ;Инициализация хэш функции, ввод исходных значений Sha256Init proc __fastcall LOCAL myInt64:QWORD ;Число для преобразования LOCAL squareRoot:QWORD ;Корень LOCAL delitel:QWORD ;делитель (равен 1 для извлечения дробной части числа) LOCAL mnoz:QWORD;множитель для выведение целого числа LOCAL myxmmword:XMMWORD enter 8*8,0 lea rdx,prime_nums ;в RDX массив простых чисел lea r8,xmmhash ;в R8 - адрес инициализированного хэша (его начальных значений) mov rcx,8 ;в RCX количество повторений цикла. Для процессора нет разницы, обращаться к DL или к RDX, поэтому снижаю расходы приводя всё к единому размеру mov rax,1373893702338282242 mov QWORD PTR [rdx],rax ; инициализирую простые числа от 2 до 19 loop1: finit mov al, BYTE PTR [rdx] ;беру текущее простое число and rax,255 mov myInt64,rax mov delitel,1 ;делитель 1 нужен для отсечения целой части, при делениии на 1 по модулю mov rax,4294967296 ;множитель 2^32, нужен...\ mov QWORD PTR mnoz,rax ;...для сдвига дробной части на 32 бита fild QWORD PTR mnoz ; сохраняю всё в стек FPU fild QWORD PTR delitel fild QWORD PTR myInt64 fsqrt ;извлекаю корень fprem ;делю на 1 по модулю fmul ST,ST(2) ;сдвигаю на 32 fisttp qword ptr squareRoot ;сохраняю для проверки mov eax,dword ptr squareRoot ;сохраняю результат в хеше mov dword ptr [r8],eax add r8,4;сдвигаю указатель на хэш inc rdx ;сдвигаю указатель на простое число dec rcx jnz loop1 ;цикл ; Далее, инициализирую константы (k) кубическим корнем ряда первых 64 простых числел от 2 до 311 lea rdx,prime2nums ;в RDX адресс массива простых числел forxmm0: ;Заполняю регистр XMM0 значениями 4-х корней mov r8,64 ;счётчик цикла lea r9,k_konst ;указатель на буфер k_konst loopxmm0: mov cx, word ptr [rdx]; беру текущее простое число and rcx,65535 ;обнуляю остальные биты call z3sqrt ;вызываю процедуру рассчёта дробной части от кубического корня от числа в rcx mov dword ptr [r9],eax ;сохраняю результат в буфер add rdx,2 ;сдвигаю указатель на простое число add r9,4 ;сдвигаю указатель на буфер k_konst dec r8 ;уменьшаю счётчик jnz loopxmm0 ;цикл leave ret Sha256Init Endp _isAvxSupported: ; extern "C" int isAvxSupported() xor eax, eax cpuid cmp eax, 1 ; Поддерживает ли CPUID параметр eax = 1? jb not_supported mov eax, 1 cpuid and ecx, 018000000h ; Проверяем, что установлены биты 27 (ОС использует XSAVE/XRSTOR) cmp ecx, 018000000h ; и 28 (поддержка AVX процессором) jne not_supported xor ecx, ecx ; Номер регистра XFEATURE_ENABLED_MASK/XCR0 есть 0 xgetbv ; Регистр XFEATURE_ENABLED_MASK теперь в edx:eax and eax, 110b cmp eax, 110b ; Убеждаемся, что ОС сохраняет AVX регистры при переключении контекста jne not_supported mov eax, 1 ret not_supported: xor eax, eax ret z3sqrt proc __fastcall ;вынес вычисление кубического корня в процедуру. На входе, в rcx - простое число, на выходе, в rax 32 бита остатка. LOCAL myInt64:QWORD ;локальная переменная для хранения простого числа LOCAL delitel:QWORD ;делитель (равен 1 для извлечения дробной части числа) LOCAL mnoz:QWORD;множитель для выведение целого числа LOCAL result:QWORD ;результат LOCAL regCR:word ;ячейка для сохренения регистра CR (FPU) enter 5*8,0 mov myInt64,rcx ;сохраняю в переменную mov delitel,1 ;единица для деления по модулю mov rax,4294967296 ;множитель 2^32, нужен...\ mov QWORD PTR mnoz,rax ;...для сдвига дробной части на 32 бита finit fstcw regCR ;сохраняю регистр CR (FPU), для изменения значения бита округления or word ptr regCR,3072 ;включаю 10 и 11 биты, сообщающие, что нужно округлять до нуля (в сторону нуля) fldcw regCR ;записываю изменённые значения в регистра CR fild QWORD PTR mnoz ; сохраняю всё в стек FPU fild QWORD PTR delitel fld QWORD PTR my3sqrt ;загружаю 1/3 fild QWORD PTR myInt64 ;текущее простое число FYL2X ;получаю LN(x) fld ST(0) ;Создаем еще одну копию LN(x) frndint ;Округляем fsubr st(0),st(1) ;ST(1)=z, ST(0)=z-trunc(z) f2xm1 ;ST(1)=z, ST(0)=2**(z-trunc(z))-1 fld1 faddp ;ST(1)=z, ST(0)=2**(z-trunc(z)) fscale ;ST(1)=z, ST(0)=(2**trunc(z))*(2**(z-trunc(z)))=2**t fxch st(1) fstp st ;Результат остается на вершине стека ST(0) fprem ;делю на 1 по модулю fmul ST,ST(2) ;сдвигаю на 32 fisttp qword ptr result ;сохраняю результат mov rax,result leave ret z3sqrt endp end