Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проверьте
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
ILYAUL
Всем привет.

Написал вот такой алгоритм деления. И вроде делит всё правильно и разрядность данных ее не пугает и остаток сохраняет , но чувство того , что чего-то упустил осталось.
А вот не пойму , что.
BeginDIV и ENDDIV - макросы для стека. ldwi - раскрывается в LDI. Retneg: - возврат к отрицательному числу , если делимое было отрицательное.

Код
;+ Подпрограмма деления 32/16.Все результаты сохраняются в SRAM
ValueX2:
        cli
        BeginDIV
        clr    Flags
        clr    count
        clr    mean1
        clr    mean0
        clr    minut
        ldwi    Z,(StartRAM085+MulMCH); загружаем адрес значения MC
        ld    temp,Z+
        ld    temp1,Z+
        ld    mean0,Z+
        ld    mean1,Z+        ; загружаем значение MC
        lds    rab,(StartRAM085+AddMCX1H); загружаем значение делителя
        lds    rab1,(StartRAM085+AddMCX1L)
Div:        
        sub    temp1,rab1
        sbc    temp,rab
        sbc    minut,zero
        brmi    TestNEG        ; Если 0 - загружаем среднее (младший) MC
        inc    count        ; Если не 0 - прибавляем счётчик результата
        sts    (StartRAM085+TailH),minut;+              
        sts    (StartRAM085+TailMH),temp;+              
        sts    (StartRAM085+TailML),temp1;+ Здесь  остаток
        sts    (StartRAM085+TailLH),mean0;+              
        sts    (StartRAM085+TailL),mean1;+              
        rjmp    DIV        ; Снова делим
TestNEG:        
        tst    count        ; Ноль после деления?
        brne    SaveX2        ; НЕТ - сохраняем значение старшее
        sbrc    Flags,fl_Shift
        rjmp    InitShift
        ldi    count,4
        clr    minut
        ldwi    Z,(StartRAM085+MulMCH); загружаем адрес MC        
        ld    temp,Z+
        ld    temp1,Z+
        rjmp    ShiftT    
InitShift:
        ldi    count,4
        ldwi    Z,(StartRAM085+MulMCH)
        ld    minut,Z+
        ld    temp,Z+
        ld    temp1,Z+
        ld    mean0,Z+
        ld    mean1,Z+
ShiftT:            
        lsl    mean1
        rol    mean0
        rol    temp1
        rol    temp
        rol    minut
        dec    count
        brne    ShiftT
        ldwi    Z,(StartRAM085+MulMCH)
        st    Z+,minut
        st    Z+,temp
        st    Z+,temp1
        st    Z+,mean0
        st    Z+,mean1
        sbr    Flags,1<<fl_Shift        
        rjmp    Div
;************************************************
SaveX2:
        sbrc    Flags,fl_ResultH
        rjmp    RESX2M    
        sts    (StartRAM085+X2H),count; Сохраняем сотые
        sbr    Flags,1<<fl_ResultH
        rjmp    Forward
RESX2M:
        sbrc    Flags,fl_ResultM
        rjmp    RESX2L    
        sts    (StartRAM085+X2M),count; Сохраняем  десятые
        sbr    Flags,1<<fl_ResultM
        rjmp    Forward
RESX2L:
        sts    (StartRAM085+X2L),count; Сохраняем единицы
        sbr    Flags,1<<fl_ResultL
        rjmp    ValDiv
Forward:
        clr    count
        ldwi    Z,(StartRAM085+TailH)
        ld    minut,Z+
        ld    temp,Z+
        ld    temp1,Z+
        ld    mean0,Z+
        ld    mean1,Z+
        ldi    count,4
        rjmp    ShiftT
ValDiv:
        lds    rab,(StartRAM085+dtMCH)
        sbrc    rab,MsbOne
        rjmp    RetNeg
RetNeg:
        lds    temp,(StartRAM085+X2H)
        lds    temp1,(StartRAM085+X2M)
        lds    rab,(StartRAM085+X2L)
        ldi    count,4
        swap    rab
Cycle:
        lsl    rab
        rol    temp1
        dec    count
        brne    Cycle
        mov    rab1,zero
        mov    rab,zero
        sub    rab1,temp1
        sbc    rab,temp
        sub    rab1,one
        sbc    rab,zero
        sts    (StartRAM085+X2H),rab
        sts    (StartRAM085+X2M),rab1
        EndDIV
        reti
Ink
Никто не отвечаетsmile.gif Код большой слишком, долго ковырять, а пропустить что-то запросто. Я бы вам рекомендовал сделать простой тест: 100500 тыщ раз в цикле вызывать эту функцию с рандомными параметрами, и вызывать эталонную функцию с этими же параметрами. Потом сравниваете результаты, и если ошибка - смотрите что где. Не 100% гарантия, но может быть близко при хорошем генераторе.

Как реализовать - дело ваше: либо нативно в контроллере (используя библиотеки компилятора за эталон) - медленно, либо на компе, переписав этот код на си 1 в 1 - быстро.
kurtis
Интересно, а почему решили писать свою реализацию? Чем не устраивала уже существующая?
ILYAUL
Цитата(kurtis @ Aug 4 2010, 15:38) *
Интересно, а почему решили писать свою реализацию? Чем не устраивала уже существующая?

Какую? От Atmel? Видел. Можно и простое вычитание до упора , тоже видел. Решил просто в "столбик" поделить. Для моей задачи быстро получается. А если вместо буфера в памяти использовать MOV , то ещё можно подсократить
И как я писал делит -то она правильно , но осталось чувство неудовлетворённости. Как будто я что-то всё таки забыл.
Например я не стал вводить запоминание тысяч , т.к. в моей задаче числа с 1xxx по идее не появятся.
но можно и дописать.
При этом я делю и 24/16 и 32/8 и 24/8 и 8/8 (c увеличением разрядности результата и могу использовать и остаток он тоже сохраняется , если нужно .
Ink
Проще и быстрее написать тест под нужные параметры. Если вас интересует безглючная работа именно у вас, при ваших условиях, - проверяйте и все увидите, забыли или нет.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.