Есть вот такой код. Что из него еще можно выжать? Код (Text): #define GOST_SYNCHRO_SIZE 8 #define OFFSET_GOST_SBOX1 0 #define OFFSET_GOST_SBOX2 256 #define OFFSET_GOST_SBOX3 512 #define OFFSET_GOST_SBOX4 768 #define MACRO_CHANGE_LINK(aa, bb) \ { \ _asm{mov eax, [ecx][aa]} \ _asm{add eax, edi} \ _asm{mov dl, al} \ _asm{mov al, [ebx][edx+OFFSET_GOST_SBOX1]} \ _asm{mov dl, ah} \ _asm{mov ah, [ebx][edx+OFFSET_GOST_SBOX2]} \ _asm{ror eax, 16} \ _asm{mov dl, al} \ _asm{mov al, [ebx][edx+OFFSET_GOST_SBOX3]} \ _asm{mov dl, ah} \ _asm{mov ah, [ebx][edx+OFFSET_GOST_SBOX4]} \ _asm{ror eax, 5} \ _asm{xor esi, eax} \ _asm{mov eax, [ecx][bb]} \ _asm{add eax, esi} \ _asm{mov dl, al} \ _asm{mov al, [ebx][edx+OFFSET_GOST_SBOX1]} \ _asm{mov dl, ah} \ _asm{mov ah, [ebx][edx+OFFSET_GOST_SBOX2]} \ _asm{ror eax, 16} \ _asm{mov dl, al} \ _asm{mov al, [ebx][edx+OFFSET_GOST_SBOX3]} \ _asm{mov dl, ah} \ _asm{mov ah, [ebx][edx+OFFSET_GOST_SBOX4]} \ _asm{ror eax, 5} \ _asm{xor edi, eax} \ } int EncipherGOSTLinkEx( IN CONST PVOID pKey, IN CONST PVOID pSBox, OUT PVOID pDst, IN CONST PVOID pSrc, IN OUT PVOID pContext, IN unsigned long uLength) { unsigned long uCount; if(uLength % GOST_SYNCHRO_SIZE) { return(0); } _asm { pushad mov eax, uLength // eax == uLength mov uCount, eax mov ebx, pContext // ebx == Synchro mov eax, pDst // eax == pDst mov esi, [ebx] // esi == Synchro[0] mov edi, [ebx+4] // edi == Synchro[1] mov ebx, pSrc // ebx == pSrc mov ecx, pKey // ecx == pKey xor esi, [ebx] xor edi, [ebx+4] xor edx, edx up: push ebx push eax xchg esi, edi mov ebx, pSBox // ebx == SBox } MACRO_CHANGE_LINK(0, 4) MACRO_CHANGE_LINK(8, 12) MACRO_CHANGE_LINK(16, 20) MACRO_CHANGE_LINK(24, 28) MACRO_CHANGE_LINK(0, 4) MACRO_CHANGE_LINK(8, 12) MACRO_CHANGE_LINK(16, 20) MACRO_CHANGE_LINK(24, 28) MACRO_CHANGE_LINK(0, 4) MACRO_CHANGE_LINK(8, 12) MACRO_CHANGE_LINK(16, 20) MACRO_CHANGE_LINK(24, 28) MACRO_CHANGE_LINK(28, 24) MACRO_CHANGE_LINK(20, 16) MACRO_CHANGE_LINK(12, 8) MACRO_CHANGE_LINK(4, 0) _asm { pop eax // eax == pDst mov [eax], esi mov [eax+4], edi // Сохранение контекста: mov ebx, pContext mov [ebx], esi mov [ebx+4], edi pop ebx // ebx == pSrc sub uCount, 8 jz down1 add ebx, 8 add eax, 8 xor esi, DWORD PTR [ebx] xor edi, DWORD PTR [ebx+4] jmp up down1: popad } return(1); }
Тут особо не выжмешь, в макросе ror eax,5 мешает, без него можно было бы распараллелить xor (~ на 30% увеличит производительность) путем перевода кода и таблицы SBOX на 32 бита
2bogrus: можно подробнее, что-то я не совсем понял. Это ror не спаривается чтоли или как? И что такое "путем перевода кода и таблицы SBOX на 32 бита"?
В MACRO_CHANGE_LINK 26 простых(одномопных) команд, которые PIII может выполнять по 3шт. за такт, т.е. теоретически в идеальном варианте код выполнялся бы за ~10 тактов, практически же выполняется ~50 из-за зависимостей и чтения eax после записей в al\ah (~ по 5 тактов пенальти) Часть макроса выглядела бы так Код (Text): #define MACRO_CHANGE_LINK(aa, bb) \ { \ _asm{mov eax, [ecx][aa]} \ _asm{add eax, edi} \ _asm{mov edx, eax} \ _asm{and edx, 0xff} \ _asm{shr eax, 8} \ _asm{xor esi, [ebx][edx*4+OFFSET_GOST_SBOX1]}\ _asm{rol esi, 8} \ _asm{mov edx, eax} \ _asm{and edx, 0xff} \ _asm{shr eax, 8} \ _asm{xor esi, [ebx][edx*4+OFFSET_GOST_SBOX2]}\ _asm{rol esi, 8} \ _asm{mov edx, eax} \ _asm{and edx, 0xff} \ _asm{shr eax, 8} \ _asm{xor esi, [ebx][edx*4+OFFSET_GOST_SBOX3]}\ _asm{rol esi, 8} \ _asm{mov edx, eax} \ _asm{and edx, 0xff} \ _asm{shr eax, 8} \ _asm{xor esi, [ebx][edx*4+OFFSET_GOST_SBOX4]}\ _asm{rol esi, 8} \ Это "32-х битный код" он выполняется быстрее, но ror eax, 5 не позволяет такое(надо ещё подумать над этим), таблицу для такого кода надо увеличить в 4 раза, один элемент будет выглядеть не 1-м байтом 0х55, а 4-мя 0х00000055
Имхо, SSE ничего не даст, так как преобразование по S-блокам требует косвенного обращения к памяти, а регистр SSE нельзя использовать в качестве индекса для операций с памятью. Нужно переводить число в GPR, а это долго. Тем более, алгоритм ГОСТ изначально оптимизирован под 32-битные регистры. Советую поиграть с кэш-памятью. Возможно, будет выгодным добавить prefetch. Также попробуй mov dl, al поменять на movzx edx, al. Выложи, пожалуйста, полный код в аттаче, чтобы любой желающий мог проверить свои (без)умные идеи, всего лишь заменив пару инструкций в коде и перекомпилировав твой проект. Еще лучше сделать и выложить тестилку, замеряющую время выполнения программы, и набор тестов, как это делали раньше на этом форуме. bogrus Можно, конечно, реализовать как в каноническом алгоритме ГОСТ, т.е. выделять по маске байты перед тем, как отправить их на вход S-блока, а в конце сделать rol T, 11, но тогда сдвигов (инструкций rol/ror/shr) будет больше. Ты считаешь, что стОит увеличивать число сдвигов для того, чтобы убрать обращения к 8-битным регистрам?
Все дело в камне, для PIII это может повысить производительность в 2 раза, на каждом сдвиге eax после записи в al\ah мы теряем 6 тактов (это равноценно 6-ти сдвигам, на нем кстати и лучше пойдет shrd), можно и не ксорить сразу, а сперва собирать в отдельном регистре результат
Потестируй такой макрос: Код (Text): #define MACRO_CHANGE_LINK(aa, bb) \ { \ _asm{mov eax, [ecx][aa]} \ _asm{add eax, edi} \ _asm{ror esi, 5} \ _asm{mov edx, eax} \ _asm{shr eax, 8} \ _asm{and edx, 0xff} \ _asm{xor esi, [ebx][edx*4+OFFSET_GOST_SBOX1]}\ _asm{ror esi, 8} \ _asm{mov edx, eax} \ _asm{shr eax, 8} \ _asm{and edx, 0xff} \ _asm{xor esi, [ebx][edx*4+OFFSET_GOST_SBOX2]}\ _asm{ror esi, 8} \ _asm{mov edx, eax} \ _asm{shr eax, 8} \ _asm{and edx, 0xff} \ _asm{xor esi, [ebx][edx*4+OFFSET_GOST_SBOX3]}\ _asm{ror esi, 8} \ _asm{mov edx, eax} \ _asm{shr eax, 8} \ _asm{and edx, 0xff} \ _asm{xor esi, [ebx][edx*4+OFFSET_GOST_SBOX4]}\ _asm{rol esi, 3} \ _asm{mov eax, [ecx][bb]} \ _asm{add eax, esi} \ _asm{ror edi, 5} \ _asm{mov edx, eax} \ _asm{shr eax, 8} \ _asm{and edx, 0xff} \ _asm{xor edi, [ebx][edx*4+OFFSET_GOST_SBOX1]}\ _asm{ror edi, 8} \ _asm{mov edx, eax} \ _asm{shr eax, 8} \ _asm{and edx, 0xff} \ _asm{xor edi, [ebx][edx*4+OFFSET_GOST_SBOX2]}\ _asm{ror edi, 8} \ _asm{mov edx, eax} \ _asm{shr eax, 8} \ _asm{and edx, 0xff} \ _asm{xor edi, [ebx][edx*4+OFFSET_GOST_SBOX3]}\ _asm{ror edi, 8} \ _asm{mov edx, eax} \ _asm{shr eax, 8} \ _asm{and edx, 0xff} \ _asm{xor edi, [ebx][edx*4+OFFSET_GOST_SBOX4]}\ _asm{rol edi, 3} \ } Но учти, таблицу BYTE SBox[GOST_SBOX_SIZE] надо переделать на DWORD или xor заменить на две команды: Код (Text): _asm{movzx edx, byte[ebx][edx+OFFSET_GOST_SBOX1]}\ _asm{xor esi, edx} \
Я не очень смотрел алго, но если S-box'ы статичны (те не пересчитываются в процессе шифрования блокофф), и если не жалко памяти, то можно заюзать две таблички 0x100 * 0x100 для SBOX1_SBOX2 и SBOX3_SBOX4, и доставать сразу WORD (а не два раза по байту). ps Вообще надо стремицца к избежанию AGI, те команд, использующих результаты предидущих типа: _asm{mov dl, al} _asm{mov al, [ebx][edx+OFFSET_GOST_SBOX1]} ; USE EDX - AGI но это тупая рекомендация о которой все и так знают
Андрей Винокуров 4 года потратил на работу с данным алгоритмом, лучше сходить на его страничку и глянуть чего там. А там: 1. Ключ шифрования\дешифрования готовится сразу, то бишь есть 1,2,3,4,5,6,7,8 а ты аля 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,8,7,6,5,4,3,2,1 2. Если глянешь таблицу замен сразу увидешь что есть 4 по 2 строки, а лучше глянь в мою статью я там старался разжевать, как можно проще, то что увидел в исходниках А.Винокурова
bogrus После использования такого макроса шифротекст получаецца отличным от того, который показывает исходный вариант.
Если я не туплю, то поправь 2 сдвига и попробуй ещё Код (Text): #define MACRO_CHANGE_LINK(aa, bb) \ { \ _asm{mov eax, [ecx][aa]} \ _asm{add eax, edi} \ _asm{ro[b]l[/b] esi, [b]16+[/b]5} \ ... \ _asm{mov eax, [ecx][bb]} \ _asm{add eax, esi} \ _asm{ro[b]l[/b] edi, [b]16+[/b]5} \ ... \ } \
bogrus Похоже, все-таки тупишь )) Опять каша получаецца. ЗЫ: Если чесна, не совсем твой код понимаю...
В макросе вроде все правильно (вот в аттаче), выдает такой-же результат как и твой, а в коде там смысл поубирать все задержки (т.е. можно сдвигать esi и ксорить побайтно с таблицей, а не собирать байты в частях eax, сдвигать его и ксорить с esi) Код (Text): mov eax,0x01234567 ; 00000001001000110100010101100111b mov esi,0x89abcdef ; 10001001101010111100110111101111b ror eax,5 ; eax = 0x38091a2b = 00111000000010010001101000101011b xor esi,eax ; esi = 0xb1a2d7c4 = 10110001101000101101011111000100b mov eax,0x01234567 ; 00000001001000110100010101100111b mov esi,0x89abcdef ; 10001001101010111100110111101111b rol esi,5 ; esi = 0x3579bdf1 = 00110101011110011011110111110001b xor esi,eax ; esi = 0x345af896 = 00110100010110101111100010010110b ror esi,5 ; esi = 0xb1a2d7c4 = 10110001101000101101011111000100b 957814723__macrotest.zip