В регистрах EAX,ECX,EBX,EDX находятся неотрицательные числа от 0 до 2^32-1, которые задают два множества A=[EAX..ECX) и B=[EBX..EDX). Левая(меньшая) граница принадлежит множеству, а правая(большая) нет. Например, множество [4..7) состоит из 3х чисел: 4,5 и 6. Необходимо написать три функции, которые в регистр EAX поместят количество чисел в объединениии(OR), пересечении(AND) и симметричной разности(XOR) множеств A и B соответственно. Пример: A=[5..15) B=[10..20) Объединение=[5..20) и содержит 15 чисел. Пересечение=[10..15) и содержит 5 чисел. Сим.Разность=[5..10)+[15..20) и содержит 10 чисел. Забыл одно важное условие: код конечно же должен быть без переходов
Объеденение - 47 байт Пересечение - 43 байта Сим.Разность - 51 байт Начало общее для всех функций (34 байта) mov esi, eax mov edi, ecx cmp eax, ebx cmovnc esi, ebx cmovnc edi, edx cmovnc ebx, eax cmovnc edx, ecx mov eax, esi mov ecx, edi mov esi, ecx cmp ecx, edx cmovnc esi, edx cmovnc edx, ecx mov ecx, esi Далее отделное окончание для каждой функции ~~~~~or~~~~~ - 13+22= 47 байтов sub edx, eax xor esi, esi sub ebx, ecx cmovnc esi, ebx sub edx, esi mov eax, edx ~~~~~and~~~~~ - 9+22= 43 байта xor esi, esi sub ecx, ebx cmovc ecx, esi mov eax, ecx ~~~~~xor~~~~ - 17+22= 51 байт sub edx, eax xor esi, esi sub ebx, ecx cmovc esi, ebx sub edx, ebx add edx, esi add edx, esi mov eax, edx
Я о таких командах не слышал даже. Код (Text): or 57 байт xor esi,esi cmp ebx,ecx rcl esi,1 cmp ebx,eax rcl esi,1 cmp edx,ecx rcl esi,1 cmp edx,eax rcl esi,1 push eax movzx eax,byte ptr [command_table+esi] shl eax,2 shr al,2 or word ptr[command],ax jmp get_result command_table: @0 db 0dbh ;11 01 1 011 ebx,ebx,ebx get_result: @1 db 58h ;pop eax @2 db 2bh ;sub command db 0c0h ;mod r/m (sub) push_ db 50h ;push @5 db 58h ;pop eax @6 db 0ebh ;jmp @7 db 8 ;jmp range прыжок на end_ @8 db 4bh ;01 00 1 011 ecx,ecx,ebx @9 db ? @a db 93h ;10 01 0 011 edx,edx,ebx @b_ db ? @c db 48h ;01 00 1 000 ecx,ecx,eax @d db ? @e db 90h ;10 01 0 000 edx,edx,eax @f_ db 0dbh ;11 01 1 011 ebx,ebx,ebx end_: ----------------------------------- and: or+ то,что ниже Код (Text): mov ebp,edx sub ebp,ebx add ebp,ecx sub ebp,eax здесь or sub eax,ebp neg eax xor: or+ то,что ниже Код (Text): mov ebp,edx sub ebp,ebx add ebp,ecx sub ebp,eax здесь or shl eax,1 sub eax,ebp neg eax
В лоб у меня получается: AND - 24 байта OR - 34 байта XOR - 37 байт Но решения пока публиковать не буду, сделаю только пару подсказок. Вот как можно вычислить максимум и минимум двух чисел: D=A-B M=SBB M,M D=D AND M A=A-D ;MAX(A,B) B=B+D ;MIN(A,B) Чтобы вычислить сколько чисел в пересечении множеств можно из MIN(ECX,EDX) вычесть MAX(EAX,EBX) и если возникло переполнение - обнулить результат.
Вычисление OR, 33 байта, немного оптимизированный "в лоб" Код (Text): ;eax..ecx == [A..C) ;ebx..edx == [B..D) lea edi, [ecx+edx] ;C + D sub ecx, edx ;C == C - D sbb esi, esi ;M == SBB M - M and ecx, esi ;C == C & M add ecx, edx ;C == C + D ;C == min(C,D) sub edi, eax sub edi, ebx ;X == (C + D) - A - B == (D - B) + (C - A) == сумма длин отрезков ;D (edx) больше не нужна, используем как временную переменную mov edx, ebx ;D == B sub edx, eax ;D == B - A sbb esi, esi ;M == SBB M - M and edx, esi ;D == D & M sub ebx, edx ;B == B - D ;B == max(A,B) sub ebx, ecx ;max(A,B) - min(C,D) sbb esi, esi and ebx, esi ; == -ANDlength add edi, ebx ;{сумма длин отрезков} + (-ANDlength) ; == {сумма длин отрезков} - ANDlength == ORlength
модификация варианта B_108 - 32 байта lea edi, [ecx+edx] xor esi, esi sub ecx, edx cmovnc ecx, esi add ecx, edx sub edi, eax sub edi, ebx mov edx, ebx sub edx, eax cmovnc edx, esi sub ebx, edx sub ebx, ecx cmovnc ebx, esi add edi, esi
для вычисление XOR если не ошибаюсь нужно из результата OR (ORlength) еще раз вычесть длину пересечения (ANDlength). То бишь в конце еще раз Код (Text): add edi, ebx