Programowanie: Mnożenie 16-bitowe z wynikiem 32-bitowym

From Atariki

(Różnice między wersjami)
Jump to: navigation, search
Wersja z dnia 07:18, 21 gru 2005
KMK (Dyskusja | wkład)

← Previous diff
Wersja z dnia 07:49, 21 gru 2005
KMK (Dyskusja | wkład)
(fmt + procedura dla 816)
Next diff →
Linia 1: Linia 1:
Procedura mnoży dwie 16-bitowe liczby bez znaku umieszczone w rejestrach FR0 ($D4) i FR1 ($E0). 32-bitowy wynik umieszczany jest w FR0. Jeśli po zakończeniu procedury znacznik C jest ustawiony, oznacza to, że nastąpiło przepełnienie i wynik nie jest prawidłowy. Procedura mnoży dwie 16-bitowe liczby bez znaku umieszczone w rejestrach FR0 ($D4) i FR1 ($E0). 32-bitowy wynik umieszczany jest w FR0. Jeśli po zakończeniu procedury znacznik C jest ustawiony, oznacza to, że nastąpiło przepełnienie i wynik nie jest prawidłowy.
 +
 +== 6502 ==
<pre> <pre>
Linia 6: Linia 8:
clc clc
- lda fr0 ;gdy mnoznik albo mnozna jest zerem+ lda fr0 ;gdy mnoznik albo mnozna jest zerem
- ora fr0+1 ;to zerem jest rowniez wynik.+ ora fr0+1 ;to zerem jest rowniez wynik.
- beq ?clr+ beq ?clr
- lda fr1+ lda fr1
- ora fr1+1+ ora fr1+1
- beq ?clr+ beq ?clr
- ldx #$01 ;kopiujemy mnozna do rejestru pomocniczego+ ldx #$01 ;kopiujemy mnozna do rejestru pomocniczego
-?cp lda fr0,x+?cp lda fr0,x
- sta ?frf,x+ sta ?frf,x
dex dex
- bpl ?cp+ bpl ?cp
- jsr ?clr ;zerujemy bajty wyniku+ jsr ?clr ;zerujemy bajty wyniku
- ldx #16+ ldx #16
-?mul lsr fr1+1 ;glowna petla+?mul lsr fr1+1 ;glowna petla
- ror fr1+ ror fr1
- bcc ?noad+ bcc ?noad
clc clc
- lda fr0+2+ lda fr0+2
- adc ?frf+ adc ?frf
- sta fr0+2+ sta fr0+2
- lda fr0+3+ lda fr0+3
- adc ?frf+1+ adc ?frf+1
- sta fr0+3+ sta fr0+3
- bcs ?exit+ bcs ?exit
-?noad lsr fr0+3+?noad lsr fr0+3
- ror fr0+2+ ror fr0+2
- ror fr0+1+ ror fr0+1
- ror fr0+ ror fr0
dex dex
- bne ?mul+ bne ?mul
clc clc
?exit rts ?exit rts
Linia 52: Linia 54:
rts rts
</pre> </pre>
- 
-Procedura nie jest "optymalna", w szczególności można łatwo uniknąć kopiowania mnożnej do rejestru pomocniczego. Chodziło jednak o to, żeby procedura działała zgodnie z konwencją, jaką stosuje umieszczony w pamięci ROM komputera pakiet procedur zmiennoprzecinkowych - dla czterech działań arytmetycznych składniki są zawsze w FR0 i FR1, a wynik umieszczany jest w FR0. Przyjęcie takiej konwencji jest wygodne, gdy mamy w programie wykonać bardziej złożone obliczenie, zwłaszcza dłuższą serię mnożeń i [[Programowanie: Dzielenie 16-bitowe z wynikiem 32-bitowym|dzieleń]] - wtedy wynik jednej procedury przechodzi w naturalny sposób jako składnik dalszych obliczeń do procedury następnej. 
Główna pętla zajmuje - w zależności od wartości mnożnika - od 612 do 944 cykli maszynowych. Główna pętla zajmuje - w zależności od wartości mnożnika - od 612 do 944 cykli maszynowych.
 +
 +== 65C816 ==
 +
 +<pre>
 +int16mul
 +?frf = fr1+2
 +
 + .aw
 + rep #$20 ;CPU musi byc w trybie natywnym
 + clc
 + lda fr0 ;gdy mnoznik albo mnozna jest zerem
 + beq ?clr ;to zerem jest rowniez wynik.
 +
 + lda fr1
 + beq ?clr
 +
 + lda fr0 ;kopiujemy mnozna do rejestru pomocniczego
 + sta ?frf
 +
 + jsr ?clr ;zerujemy bajty wyniku
 +
 + ldx #16
 +?mul lsr fr1 ;glowna petla
 + bcc ?noad
 +
 + clc
 + lda fr0+2
 + adc ?frf
 + sta fr0+2
 + bcs ?exit
 +
 +?noad lsr fr0+2
 + ror fr0
 + dex
 + bne ?mul
 + clc
 +?exit rts
 +
 +?clr stz fr0
 + stz fr0+2
 + rts
 +</pre>
 +
 +== Uwagi ==
 +
 +Procedura nie jest "optymalna", w szczególności można łatwo uniknąć kopiowania mnożnej do rejestru pomocniczego. Chodziło jednak o to, żeby procedura działała zgodnie z konwencją, jaką stosuje umieszczony w pamięci ROM komputera pakiet procedur zmiennoprzecinkowych - dla czterech działań arytmetycznych składniki są zawsze w FR0 i FR1, a wynik umieszczany jest w FR0. Przyjęcie takiej konwencji jest wygodne, gdy mamy w programie wykonać bardziej złożone obliczenie, zwłaszcza dłuższą serię mnożeń i [[Programowanie: Dzielenie 16-bitowe z wynikiem 32-bitowym|dzieleń]] - wtedy wynik jednej procedury przechodzi w naturalny sposób jako składnik dalszych obliczeń do procedury następnej.
[[Kategoria:Niezbędnik kodera]] [[Kategoria:Niezbędnik kodera]]

Wersja z dnia 07:49, 21 gru 2005

Procedura mnoży dwie 16-bitowe liczby bez znaku umieszczone w rejestrach FR0 ($D4) i FR1 ($E0). 32-bitowy wynik umieszczany jest w FR0. Jeśli po zakończeniu procedury znacznik C jest ustawiony, oznacza to, że nastąpiło przepełnienie i wynik nie jest prawidłowy.

6502

int16mul
?frf    =       fr1+2

        clc
        lda fr0     ;gdy mnoznik albo mnozna jest zerem
        ora fr0+1   ;to zerem jest rowniez wynik.
        beq ?clr

        lda fr1
        ora fr1+1
        beq ?clr

        ldx #$01    ;kopiujemy mnozna do rejestru pomocniczego
?cp     lda fr0,x
        sta ?frf,x
        dex
        bpl ?cp

        jsr ?clr    ;zerujemy bajty wyniku

        ldx #16
?mul    lsr fr1+1   ;glowna petla
        ror fr1
        bcc ?noad

        clc
        lda fr0+2
        adc ?frf
        sta fr0+2
        lda fr0+3
        adc ?frf+1
        sta fr0+3
        bcs ?exit

?noad   lsr fr0+3
        ror fr0+2
        ror fr0+1
        ror fr0
        dex
        bne ?mul
        clc
?exit   rts

?clr    ldx #$03
        lda #$00
?cl     sta fr0,x
        dex
        bpl ?cl
        rts

Główna pętla zajmuje - w zależności od wartości mnożnika - od 612 do 944 cykli maszynowych.

65C816

int16mul
?frf    =       fr1+2

        .aw
        rep #$20    ;CPU musi byc w trybie natywnym
        clc
        lda fr0     ;gdy mnoznik albo mnozna jest zerem
        beq ?clr    ;to zerem jest rowniez wynik.

        lda fr1
        beq ?clr

        lda fr0     ;kopiujemy mnozna do rejestru pomocniczego
        sta ?frf

        jsr ?clr    ;zerujemy bajty wyniku

        ldx #16
?mul    lsr fr1     ;glowna petla
        bcc ?noad

        clc
        lda fr0+2
        adc ?frf
        sta fr0+2
        bcs ?exit

?noad   lsr fr0+2
        ror fr0
        dex
        bne ?mul
        clc
?exit   rts

?clr    stz fr0
        stz fr0+2
        rts

Uwagi

Procedura nie jest "optymalna", w szczególności można łatwo uniknąć kopiowania mnożnej do rejestru pomocniczego. Chodziło jednak o to, żeby procedura działała zgodnie z konwencją, jaką stosuje umieszczony w pamięci ROM komputera pakiet procedur zmiennoprzecinkowych - dla czterech działań arytmetycznych składniki są zawsze w FR0 i FR1, a wynik umieszczany jest w FR0. Przyjęcie takiej konwencji jest wygodne, gdy mamy w programie wykonać bardziej złożone obliczenie, zwłaszcza dłuższą serię mnożeń i dzieleń - wtedy wynik jednej procedury przechodzi w naturalny sposób jako składnik dalszych obliczeń do procedury następnej.

Personal tools