Морфинг на функции Пирса

Admin

Administrator
Сообщения
863
Оценка реакций
527
Основа на macro'сах fasm'а
Код:
macro _nor r, a, b
{
    push a
    pop r
    or r, b
    not r
}

macro _not r, a
{
    _nor r, a, a
}

macro _and r, a, b, ar, br
{
    push ar br
    _not ar, a
    _not br, b
    _nor r, ar, br
    pop br ar
}

macro _or r, a, b, ar, br
{
    push ar br
    _nor ar, a, b
    _nor br, a, b
    _nor r, ar, br
    pop br ar
}

macro _xor r, a, b, ar, br, cr, dr
{
    push ar br
    _not ar, a
    _and ar, ar, b, cr, dr

    _not br, b
    _and br, br, a, cr, dr

    _or r, ar, br, cr, dr
    pop br ar
}

macro _mov r, a, ar, br
{
    _or r, a, a, ar, br
}
Для примера закодим сумматор

Код:
macro _add r, a, b, ar, br, cr, dr
{
    push cr dr

@@: test b, b
    je @f

    _mov cr, a, b, dr
    _xor r, a, b, ar, br, cr, dr
    _and cr, cr, b, a, dr
    shl cr, 1
    _mov b, cr, a, dr

    jmp @b
@@: pop dr cr
}
Это
Код:
    mov eax, 0x584d540
    mov ecx, 0x84877
    _add eax, eax, ecx, esi, edi, edx, ebx ; eax = 058D1DB7h
сгенерирует нам следующее
Код:
    mov eax, 0x0584D540
    mov ecx, 0x00084877
    push edx
    push ebx
L_0x00402021:
    test ecx, ecx
    je  L_0x004020C4
    push ecx
    push ebx
    push eax
    pop ecx
    or ecx, eax
    not ecx
    push eax
    pop ebx
    or ebx, eax
    not ebx
    push ecx
    pop edx
    or edx, ebx
    not edx
    pop ebx
    pop ecx
    push esi
    push edi
    push eax
    pop esi
    or esi, eax
    not esi
    push edx
    push ebx
    push esi
    pop edx
    or edx, esi
    not edx
    push ecx
    pop ebx
    or ebx, ecx
    not ebx
    push edx
    pop esi
    or esi, ebx
    not esi
    pop ebx
    pop edx
    push ecx
    pop edi
    or edi, ecx
    not edi
    push edx
    push ebx
    push edi
    pop edx
    or edx, edi
    not edx
    push eax
    pop ebx
    or ebx, eax
    not ebx
    push edx
    pop edi
    or edi, ebx
    not edi
    pop ebx
    pop edx
    push edx
    push ebx
    push esi
    pop edx
    or edx, edi
    not edx
    push esi
    pop ebx
    or ebx, edi
    not ebx
    push edx
    pop eax
    or eax, ebx
    not eax
    pop ebx
    pop edx
    pop edi
    pop esi
    push eax
    push ebx
    push edx
    pop eax
    or eax, edx
    not eax
    push ecx
    pop ebx
    or ebx, ecx
    not ebx
    push eax
    pop edx
    or edx, ebx
    not edx
    pop ebx
    pop eax
    shl edx, 1
    push eax
    push ebx
    push edx
    pop eax
    or eax, edx
    not eax
    push edx
    pop ebx
    or ebx, edx
    not ebx
    push eax
    pop ecx
    or ecx, ebx
    not ecx
    pop ebx
    pop eax
    jmp  L_0x00402021
L_0x004020C4:
    pop ebx
    pop edx
попробуй разберись) Для большего хардкора можно заюзать rept (но если бит не занят, то будет работа вхолостую).

Ну или на C'шке

Код:
#define nor(a, b)  (~(a | b))

#define not(a   )  nor(a, a)
#define and(a, b)  nor(not(a), not(b))
#define  or(a, b)  nor(nor(a, b), nor(a, b))
#define xor(a, b)  or(and(not(a), b), and(not(b), a))

uint32_t add(uint32_t a, uint32_t b)
{
    return b ? add(xor(a, b), and(a, b) << 1) : a;
}

uint32_t neg(uint32_t a)
{
    return add(not(a), 1);
}

uint32_t sub(uint32_t a, uint32_t b)
{
    return add(a, neg(b));
}
..что компилятор всячески оптимизирует, и не есть избыточно как на макросах, но тоже неплохо с отключенной оптимизацией.

Стрелки Пирса хороши для построения логики (как пример) какого-то АЛУ для ВМ при минимальном наборе команд. Аналогичным образом можно использовать штрих Шеффера.