diff --git a/.gitignore b/.gitignore index a8fd5d7..f3c7c31 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ main.exe sha-256.obj .vscode/tasks.json.etalon sha-256.dll +sha-256.lib +sha-256.exp + diff --git a/.vscode/tasks copy.json b/.vscode/tasks copy.json new file mode 100644 index 0000000..8046ec8 --- /dev/null +++ b/.vscode/tasks copy.json @@ -0,0 +1,100 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Assemble", + "type": "shell", + "args": [ + "/c", + "/Cp", + "${fileBasenameNoExtension}.asm" + ], + "command": "C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.28.29333/bin/Hostx64/x64/ml64.exe", + "problemMatcher": { + "owner": "masm", + "fileLocation": [ + "relative", + "${workspaceFolder}" + ], + "pattern": { + "regexp": "^(.*)\\((\\d*)\\)\\s+:?\\s+(error|warning)\\s+([A-z]+\\d+):\\s+(.*)$", + "file": 1, + "line": 2, + "severity": 3, + "code": 4, + "message": 5, + "loop": true + } + }, + "group": "build" + }, + { + "label": "link", + "type": "shell", + "args": [ + "/LIBPATH:/includes", + "/SUBSYSTEM:WINDOWS", + "/entry:WinMain", + "/LARGEADDRESSAWARE:NO", + "${fileBasenameNoExtension}.obj" + ], + "command": "C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.28.29333/bin/Hostx64/x64/link.exe", + "dependsOn": "Assemble" + }, + { + "label": "execute", + "type": "shell", + "command": "${workspaceFolder}/${fileBasenameNoExtension}.exe", + "group": { + "kind": "build", + "isDefault": true + }, + "dependsOn": "link", + "problemMatcher":[] + }, + { + "label": "AssembleLib", + "type": "shell", + "args": [ + "/c", // Только ассемблирование, без сборки + "/Cp", // Сохраняет регистр пользовательских символов (делает разницу между строчными и заглавными символами) + ///Zi", // Отладочная информация + "${fileBasenameNoExtension}.asm" + ], + "command": "C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.28.29333/bin/Hostx64/x64/ml64.exe", + "problemMatcher": { + "owner": "masm", + "fileLocation": [ + "relative", + "${workspaceFolder}" + ], + "pattern": { + "regexp": "^(.*)\\((\\d*)\\)\\s+:?\\s+(error|warning)\\s+([A-z]+\\d+):\\s+(.*)$", + "file": 1, + "line": 2, + "severity": 3, + "code": 4, + "message": 5, + "loop": true + } + }, + "group": "build" + }, + { + "label": "linkDLL", + "type": "shell", + "args": [ + "/DLL", + "/SUBSYSTEM:WINDOWS", + "/DEF:sha-256.def", + "/LIBPATH:C:/repo/SHA-256/includes/", + "/entry:DllMain", + "${fileBasenameNoExtension}.obj" + ], + "command": "C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.28.29333/bin/Hostx64/x64/link.exe", + "dependsOn": "AssembleLib" + } + ] +} diff --git a/sha-256.asm b/sha-256.asm index 1c43282..8fe1233 100644 --- a/sha-256.asm +++ b/sha-256.asm @@ -6,34 +6,91 @@ includelib includes\user32.lib OPTION PROLOGUE:none OPTION EPILOGUE:none .data -AppName dw 0044h,004ch,004ch,0020h,0053h,006bh,0065h,006ch,0065h,0074h,006fh,006eh,0000h -HelloMsg 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 dw 0044h,004ch,004ch,0020h,0417h,0430h,0433h,0440h,0443h,0436h,0435h,043dh,0430h,0000h -UnloadMsg dw 0044h,004ch,004ch,0020h,0432h,044bh,0433h,0440h,0443h,0436h,0435h,043dh,0430h,0000h -SHAMsg dw 0053h,0048h,0041h,0032h,0035h,0036h,0020h,0417h,0430h,043fh,0443h,0449h,0435h,043dh,0430h,0021h,0000h ;"SHA256 Запущена!" -DllAtata 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 -DllDetata 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 + 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 - lea rdx,LoadMsg - .elseif edx==DLL_PROCESS_DETACH - lea rdx,UnloadMsg - .elseif edx==DLL_THREAD_ATTACH - ;lea rdx,DllAtata - add rsp,28h - xor rax,rax - ret - .elseif edx==DLL_THREAD_DETACH - ;lea rdx,DllDetata - add rsp,28h - xor rax,rax - ret + .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 + mov r9d,MB_OK ; jmp exit DllMain Endp TestHello proc @@ -49,16 +106,119 @@ exit:: lea r8,AppName mov rax,TRUE ret TestHello endp -Sha256 proc h_line:QWORD, h_size:QWORD -sub rsp,28h -;Основа - lea rdx,SHAMsg - mov r9d,MB_OK + MB_ICONERROR - lea r8,SHAMsg - xor ecx,ecx - call MessageBoxW - add rsp,28h +;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 \ No newline at end of file diff --git a/sha-256.def b/sha-256.def index cb62bea..78a7c06 100644 --- a/sha-256.def +++ b/sha-256.def @@ -1,4 +1,5 @@ LIBRARY sha-256 EXPORTS DllMain EXPORTS TestHello -EXPORTS Sha256 \ No newline at end of file +EXPORTS Sha256 +EXPORTS Sha256Init \ No newline at end of file diff --git a/sha-256.dll b/sha-256.dll index ffaffed..5e83cce 100644 Binary files a/sha-256.dll and b/sha-256.dll differ diff --git a/sha-256.exp b/sha-256.exp index bcbc6b2..58339b1 100644 Binary files a/sha-256.exp and b/sha-256.exp differ diff --git a/sha-256.lib b/sha-256.lib index 1da7228..bc54a5d 100644 Binary files a/sha-256.lib and b/sha-256.lib differ diff --git a/Алгоритм.png b/Алгоритм.png new file mode 100644 index 0000000..add1d5d Binary files /dev/null and b/Алгоритм.png differ diff --git a/Алгоритм.vsdx b/Алгоритм.vsdx new file mode 100644 index 0000000..32a1517 Binary files /dev/null and b/Алгоритм.vsdx differ diff --git a/Книга1.xlsm b/Книга1.xlsm new file mode 100644 index 0000000..6188d7e Binary files /dev/null and b/Книга1.xlsm differ diff --git a/Книга1.xlsx b/Книга1.xlsx index 28371b6..8b87515 100644 Binary files a/Книга1.xlsx and b/Книга1.xlsx differ diff --git a/На чём остановился.txt b/На чём остановился.txt index 074d25c..5e7bdb6 100644 --- a/На чём остановился.txt +++ b/На чём остановился.txt @@ -1 +1,2 @@ После подключения DLL вызывающая прогамма ловит исключение через 20-30 секунд (в дебагере - сразу). Похоже, глюк в адресации. Проверить возвращаемые значения. +Проблема оказалась в том, что в wndproc переменные я хранил локально, что давало исключене после вызова DLL diff --git a/Регистры.txt b/Регистры.txt new file mode 100644 index 0000000..cc65020 --- /dev/null +++ b/Регистры.txt @@ -0,0 +1,27 @@ +RAX 64(double) 00000000 00000000 8 байт +RCX 64(double) 00000000 00000000 8 байт +RDX 64(double) 00000000 00000000 8 байт +R8 64(double) 00000000 00000000 8 байт - A,B (Занят только во время цикла) +R9 64(double) 00000000 00000000 8 байт - C,D (Занят только во время цикла) +R10 64(double) 00000000 00000000 8 байт - E,F (Занят только во время цикла) +R11 64(double) 00000000 00000000 8 байт - G,H (Занят только во время цикла) +R12 64(double) 00000000 00000000 8 байт - H1,H2 +R13 64(double) 00000000 00000000 8 байт - H3,H4 +R14 64(double) 00000000 00000000 8 байт - H5,H6 +R15 64(double) 00000000 00000000 8 байт - H7,H8 +XMM0 128 00000000 00000000 00000000 00000000 16 байт - W1,W2,W3,W4 +XMM1 128 00000000 00000000 00000000 00000000 16 байт - W5,W6,W7,W8 +XMM2 128 00000000 00000000 00000000 00000000 16 байт - W9,W10,W11,W12 +XMM3 128 00000000 00000000 00000000 00000000 16 байт - W13,W14,W15,W16 +XMM4 128 00000000 00000000 00000000 00000000 16 байт - W17,W18,W19,W20 +XMM5 128 00000000 00000000 00000000 00000000 16 байт - W21,W22,W23,W24 +XMM6 128 00000000 00000000 00000000 00000000 16 байт - W25,W26,W27,W28 +XMM7 128 00000000 00000000 00000000 00000000 16 байт - W29,W30,W31,W32 +XMM8 128 00000000 00000000 00000000 00000000 16 байт - W33,W34,W35,W36 +XMM9 128 00000000 00000000 00000000 00000000 16 байт - W37,W38,W39,W40 +XMM10 128 00000000 00000000 00000000 00000000 16 байт- W41,W24,W43,W44 +XMM11 128 00000000 00000000 00000000 00000000 16 байт- W45,W46,W47,W48 +XMM12 128 00000000 00000000 00000000 00000000 16 байт- W49,W50,W51,W52 +XMM13 128 00000000 00000000 00000000 00000000 16 байт- W53,W54,W55,W56 +XMM14 128 00000000 00000000 00000000 00000000 16 байт- W57,W58,W59,W60 +XMM15 128 00000000 00000000 00000000 00000000 16 байт- W61,W62,W63,W64 \ No newline at end of file