23 апреля 2012 г.

Длинная арифметика: Сравнение

Для следующей арифметической операции под названием деление, а именно вычисления модуля числа, нам необходима процедурка - сравнение. В принципе она очень проста, алгоритм заключается в следующем, сначала мы сравниваем длину числа в байтах, то число которое длиннее - всегда будет больше чем короткое. Если длина чисел равна, то сравниваем пару сатрших цифр в числах, если цифра в числе 1 больше, то значит число 1 больше и наоборот, если же они тоже равны то сдвигаемся на одну в право и повторяем сравнение,пока какая то цифра не окажется больше или меньше. Если все цифры закончились, но так и не найдено большее число, тогда считаем что оба числа равны.
А теперь все это на ASM:


long_eq proc uses ecx edx ebx esi edi  cif1:DWORD, cif2:DWORD, lenght1:DWORD, lenght2:DWORD
    mov        eax, lenght1 ; копируем в eax длину цифры 1
    cmp        eax, lenght2 ; сравниваем eax с длиной цифрой 2
    je        eq_main ; длины равны - переходим на основной цикл
    cmp        eax, lenght2 ; сравниваем снова
    jl        eq_big_2 ; длина цифра 1 меньше цифры 2 - уходим на eq_big_2
    jmp        eq_big_1 ; в любом другом случае цифра 1 больше цифры 2 - уходим на eq_big_1
eq_main:
    mov        edx, cif1 ; копируем в edx адрес цифры 1
    mov        ebx, cif2 ; копируем в ebx адрес цифры 1
    mov        esi,lenght2 ; копируем в esi длину цифр
eq_next:
    mov        al, BYTE PTR [edx+esi] ; в al копируем самый старший байт цифры 1
    cmp        al, BYTE PTR [ebx+esi] ; сравниваем со старшим байтом цифры 2
    jl        eq_big_2 ; старший байт цифры 1 меньше цифры 2 уходим на eq_big_2
    jg        eq_big_1 ; старший байт цифры 2 меньше цифры 1 уходим на eq_big_1
    or        esi, 0 ; сравниваем закончились ли у нас цифры которые сравниваем
    jz        eq_cif1_cif2 ; закончились - цифры равны между собой
    dec        esi ; сдвигаем позицию в цифрах на одну в право(в компе в лево)
    jmp        eq_next ; прыгаем на сравнение следующей пары
eq_cif1_cif2:
    mov        eax, 0 ; возвращаем в eax = 0, цифры равны
    jmp        eq_end ; прыгаем на окончание процедурки
eq_big_1:
    mov        eax, 1 ; возвращаем в eax = 1, цифра1 больше
    jmp        eq_end ; прыгаем на окончание процедурки
eq_big_2:
    mov        eax, 2 ; возвращаем в eax = 2, цифра2 больше
    jmp        eq_end ; прыгаем на окончание процедурки
eq_end:
    Ret
long_eq EndP
Прототип процедурки следующий:
long_eq PROTO:DWORD, :DWORD, :DWORD, :DWORD
А Вызывается процедурка вот так:
invoke long_eq,ADDR num1, ADDR num2,  3, 3
В итоге в eax у нас оказывается код 0 = числа равны, 1 - число 1 больше, 2 - число 2 больше.
Из багов, возможно не корректная работа с числами у которых будет стоять флаг минуса. Надо потестить, хотя в расчетах по криптографии редко достаточно возникает минусовые числа.

Комментариев нет:

Отправить комментарий