Black_mirror, На выходе не восстанавливает mm0..mm2. Последним flags пишет, \not eax\ - используйте jcc. Код (Text): proc p1; v1,v2 mov eax,[esp+4] movd mm0,eax shr eax,4 movd mm1,eax punpcklbw mm0,mm1 mov eax,[esp+8] movd mm1,eax shr eax,4 movd mm2,eax punpcklbw mm1,mm2 pcmpeqb mm0,mm1 movq [esp+4],mm0 movd eax,mm0 or eax,[esp+8] jz @f or eax,-1 @@: not eax ret 8 endp
KeSqueer XOR EDX,EDX BTS EDX,EAX <- здесь устанавливает бит соответствующий первой тетраде MOV CL,4 ROL EAX,CL BTS EDX,EAX SBB EBX,EBX <- а здесь счётчик совпавших тетрад устанавливаем в -1, если совпали две первых проверенных тетрады ROL EAX,CL BTS EDX,EAX ADC EBX,EBX <- ну а тут сдвигаем счётчик и добавляем к нему очередной флаг, таких блоков 6 штук ... На самом деле BTS берёт не 4 бита, а 5, из-за этого лишнего бита, флаг может установиться как в младшей половине edx, так и в старшей, это проверяется следующим кодом: SHLD EBX,EDX,10 AND BX,DX Данный код требует 7 байт, но bts edx,eax на 1 байт короче bts dx,ax, а поскольку команд bts у нас 8 штук, то в итоге мы экономим один байт.
Black_mirror Почему бы не использовать xor ebx, ebx и 8 раз adc ebx, ebx? Далее если ebx не 0, то есть одинаковые тетрады.
KeSqueer Потому что код оптимизируем по размеру, первый раз adc можно не использовать потому что перенос невозможен в принципе, а второй adc и xor можно заменить на sbb с таким же успехом.
Serg50 Немного почистил ваш код, 70 байт, всего на 1 байт длинее варианта с битовой таблицей(вернее на 2, потому что в варианте с таблицей not можно заменить на cmc), на правильность пока не тестировал: Код (Text): mov ebx,11111111h mov cl,4 mov ebp,eax rol eax,cl mov edx,eax rol eax,cl mov esi,eax rol eax,cl mov edi,eax rol eax,cl xor eax,ebp xor edx,ebp xor esi,ebp xor edi,ebp push edi push esi push edx push eax sub eax,ebx sbb edx,ebx sbb esi,ebx sbb edi,ebx sbb al,0 pop ebp xor eax,ebp pop ebp xor edx,ebp pop ebp xor esi,ebp pop ebp xor edi,ebp and eax,edx and eax,esi and eax,edi and eax,ebx cmp eax,ebx cmc sbb eax,eax edemko Ваш код я пока совсем не понял, вообще для mmx я предлагал решать задачку с 8 байтами, а не тетрадами.
Код (Text): ; v1 = первый dword, к примеру $1234abcd ; v2 = второй dword, к примеру $1234abcd proc p1; v1,v2 mov eax,[esp+4] ; $1234abcd movd mm0,eax shr eax,4 movd mm1,eax ; $01234abc>>d punpcklbw mm0,mm1 ; $01122334'4aabbccd mov eax,[esp+8] ; то же проделываем со вторым набором тетрад v2 movd mm1,eax shr eax,4 movd mm2,eax punpcklbw mm1,mm2 push $0f0f0f0f $0f0f0f0f ; не обязательно, но более понятно pand mm0,[esp] ; $01020304'0a0b0c0d pand mm1,[esp] ; $01020304'0a0b0c0d pcmpeqb mm0,mm1 ; сравнить побайтно, если равно, - mm0.x = $ff, иначе $00 movq mm1,mm0 ; нам нужна только старшая часть результата сравнения... psrlq mm1,32 ; ...получили por mm0,mm1 ; старшая часть нас уже не волнует movd eax,mm0 ; сохраняем, если eax=0, совпадений нет вовсе ret 8 endp Black_mirror, таким способом для байт нужно брать xmm. Процедуру переписывал без OllyDbg(я не дома), должно работать. Часто сам не понимаю, чего перо выкинет...
edemko Задачка у нас не в сравнении тетрад двух слов, задачка у нас в сравнении между собой всех тетрад одного слова. Если хотя бы две из них равны, то устанавливаем eax=0, а если все различны, то eax=-1. Ту же самую задачку только уже не с тетрадами, а с байтами предлагается решить для rax или mm0, результат нужно оставить в них же.
edemko Надо примерно так Код (Text): eax:=0; for i:=0 to 6 do for j:=i+1 to 7 do if mm0[i]=mm0[j] then goto 1; dec(eax); 1:
Без цикла, 62 байта Код (Text): xor edx,edx mov cl,4 bts dx,ax rcr eax,cl bts dx,ax rcr eax,cl bts dx,ax rcr eax,cl bts dx,ax rcr eax,cl bts dx,ax rcr eax,cl bts dx,ax rcr eax,cl bts dx,ax rcr eax,cl bts dx,ax rcr eax,cl and eax,11111111h neg eax cmc sbb eax,eax ЗЫ. Используя инструкцию POPCNT, вполне выиграть как с циклом так и без. Однако проверить не на чем.