Подтвердить что ты не робот

Где можно найти алгоритмы с многократным умножением и делением?

Я работаю над микроконтроллером без размножения и разделения оборудования. Мне нужно подготовить алгоритмы программного обеспечения для этих основных операций, которые являются хорошим балансом компактных размеров и эффективности. Мой порт компилятора C будет использовать эти альгоны, а не сами разработчики C.

Мой google-fu пока что вызывает шум в этой теме.

Может ли кто-нибудь указать мне что-то информативное? Я могу использовать команды add/sub и shift. Алгоритмы поиска на основе таблицы также могут работать для меня, но я немного переживаю за то, что так много перерабатываю в компилятор back-end... um, так сказать.

4b9b3361

Ответ 1

Здесь простой алгоритм умножения:

  • Начните с самого правого бита множителя.

  • Если бит в множителе равен 1, добавьте multipicand

  • Сдвиг мультипликатора на 1

  • Переместитесь к следующему бит в мультипликаторе и вернитесь к шагу 2.

И вот алгоритм деления:

  • Если делитель больше дивиденда, остановитесь.

  • В то время как регистр делителей меньше регистра дивидендов, сдвиг влево.

  • Регистр сдвига сдвига на 1.

  • Вычтите регистр делителей из регистра дивидендов и измените бит на 1 в реестре результатов на бит, который соответствует общему числу сдвигов, выполненных в регистре делителей.

  • Начните с шага 1 с регистром делителя в исходном состоянии.

Конечно, вам нужно поставить чек для деления на 0, но он должен работать.

Эти алгоритмы, конечно, предназначены только для целых чисел.

Ответ 2

Здесь алгоритм деления: http://www.prasannatech.net/2009/01/division-without-division-operator_24.html

Я предполагаю, что мы говорим о ints?

Если нет поддержки аппаратного обеспечения, вам придется реализовать свое собственное исключение по отдельности.

(Мне не повезло быстро найти алгоритм умножения, но я буду продолжать искать, если кто-то еще его не найдет).

Ответ 5

Оказывается, у меня все еще есть старый код ассемблера 68000 для длительного умножения и длинного деления. Код 68000 довольно чистый и простой, поэтому его легко перевести на ваш чип.

68000 умножил и разделил инструкции IIRC - я думаю, что они были написаны как учебное упражнение.

Решил просто поместить код здесь. Добавлены комментарии и при этом исправлена ​​проблема.

;
; Purpose  : division of longword by longword to give longword
;          : all values signed.
; Requires : d0.L == Value to divide
;          : d1.L == Value to divide by
; Changes  : d0.L == Remainder
;          : d2.L == Result
;          : corrupts d1, d3, d4
;

        section text

ldiv:   move    #0,d3     ; Convert d0 -ve to +ve - d3 records original sign
        tst.l   d0
        bpl.s   lib5a
        neg.l   d0
        not     d3
lib5a:  tst.l   d1        ; Convert d1 -ve to +ve - d3 records result sign
        bpl.s   lib5b
        neg.l   d1
        not     d3
lib5b:  tst.l   d1        ; Detect division by zero (not really handled well)
        bne.s   lib3a
        rts
lib3a:  moveq.l #0,d2     ; Init working result d2
        moveq.l #1,d4     ; Init d4
lib3b:  cmp.l   d0,d1     ; while d0 < d1 {
        bhi.s   lib3c
        asl.l   #1,d1     ; double d1 and d4
        asl.l   #1,d4
        bra.s   lib3b     ; }
lib3c:  asr.l   #1,d1     ; halve d1 and d4
        asr.l   #1,d4
        bcs.s   lib3d     ; stop when d4 reaches zero
        cmp.l   d0,d1     ; do subtraction if appropriate
        bhi.s   lib3c
        or.l    d4,d2     ; update result
        sub.l   d1,d0
        bne.s   lib3c
lib3d:                    ; fix the result and remainder signs
;       and.l   #$7fffffff,d2  ; don't know why this is here
        tst     d3
        beq.s   lib3e
        neg.l   d2
        neg.l   d0
lib3e:  rts

;
; Purpose  : Multiply long by long to give long
; Requires : D0.L == Input 1
;          : D1.L == Input 2
; Changes  : D2.L == Result
;          : D3.L is corrupted
;

lmul:   move    #0,d3       ; d0 -ve to +ve, original sign in d3
        tst.l   d0
        bpl.s   lib4c
        neg.l   d0
        not     d3
lib4c:  tst.l   d1          ; d1 -ve to +ve, result sign in d3
        bpl.s   lib4d
        neg.l   d1
        not     d3
lib4d:  moveq.l #0,d2       ; init d2 as working result
lib4a:  asr.l   #1,d0       ; shift d0 right
        bcs.s   lib4b       ; if a bit fell off, update result
        asl.l   #1,d1       ; either way, shift left d1
        tst.l   d0
        bne.s   lib4a       ; if d0 non-zero, continue
        tst.l   d3          ; basically done - apply sign?
        beq.s   lib4e       ; was broken! now fixed
        neg.l   d2
lib4e:  rts
lib4b:  add.l   d1,d2      ; main loop body - update result
        asl.l   #1,d1
        bra.s   lib4a
Кстати, я никогда не выяснял, нужно ли было сначала конвертировать все в позитивное. Если вы осторожны со сменными операциями, это может быть предотвращено издержки.

Ответ 6

Чтобы умножить, добавьте частичные продукты из сдвинутого множителя в аккумулятор, если соответствующий бит в множителе установлен. Множитель Shift и множитель в конце цикла, тестовый множитель и 1, чтобы увидеть, нужно ли делать добавление.

Ответ 7

Микрочипы серии Microchip PICmicro 16Fxxx не имеют инструкции умножения или деления. Возможно, некоторые из программ мягкого размножения и мягкого разделения для него могут быть перенесены в ваш MCU.

PIC Микроконтроллер Основные методы умножения математики

PIC Микроконтроллер Основные методы математического отдела

Также проверьте "Метод Ньютона" для деления. Я думаю, что этот метод дает наименьший исполняемый размер любого алгоритма деления, который я когда-либо видел, хотя объяснение делает его более сложным, чем оно есть на самом деле. Я слышал, что некоторые ранние суперкомпьютеры Cray использовали метод Ньютона для деления.