Programowanie: Mnożenie 16-bitowe z wynikiem 32-bitowym: Różnice pomiędzy wersjami

Z Atariki
Przejdź do nawigacji Przejdź do wyszukiwania
Nie podano opisu zmian
ulepszenia i poprawki
 
(Nie pokazano 11 pośrednich wersji utworzonych przez tego samego użytkownika)
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.
 
== 6502 ==


<pre>
<pre>
Linia 5: Linia 7:
?frf    =      fr1+2
?frf    =      fr1+2


        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
         lda fr0     ;kopiujemy mnozna do rejestru pomocniczego
?cp    lda    fr0,x
         sta ?frf
         sta     ?frf,x
         lda fr0+1
         dex
         sta ?frf+1
         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


?noad  lsr    fr0+3
?noad  ror 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
?exit  rts
?exit  rts


Linia 53: Linia 51:
</pre>
</pre>


Procedura nie jest "optymalna", w szczególności mozna ł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.
Główna pętla zajmuje - w zależności od wartości mnożnika - od 612 do 944 cykli maszynowych.
 
== 65C816 ==


Główna pętla zajmuje - w zależności od wartości mnożnika - od 612 do 944 cykli maszynowych.
<pre>
int16mul
?frf    =      fr1+2
 
        .aw
        .ib
        rep #$21    ;CPU musi byc w trybie natywnym
        sep #$10
 
        lda fr0    ;gdy mnoznik albo mnozna jest zerem
        and fr1    ;to zerem jest rowniez wynik
        beq ?clr
 
        lda fr0    ;kopiujemy mnozna do rejestru pomocniczego
        sta ?frf
 
        stz fr0    ;zerujemy bajty wyniku
        lda #$0000
 
        ldx #16
?mul    lsr fr1    ;glowna petla
        bcc ?noad
 
        clc
        adc ?frf
 
?noad  ror
        ror fr0
        dex
        bne ?mul
 
        sta fr0+2
 
?exit  rts
 
?clr    stz fr0
        stz fr0+2
        rts
        .ab
        .ib
</pre>
 
Główna pętla zajmuje od 384 do 464 cykli maszynowych.
 
Elegancka procedura biblioteczna powinna jeszcze przechowywać na stosie i przed powrotem do miejsca wywołania przywracać rozmiar rejestrów. W powyższym przykładzie pominięto to, żeby nie zaciemniać zagadnienia.
 
== 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]]

Aktualna wersja z 8 wrz 2015, 00:52

Procedura mnoży dwie 16-bitowe liczby bez znaku umieszczone w rejestrach FR0 ($D4) i FR1 ($E0). 32-bitowy wynik umieszczany jest w FR0.

6502

int16mul
?frf    =       fr1+2

        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

        lda fr0     ;kopiujemy mnozna do rejestru pomocniczego
        sta ?frf
        lda fr0+1
        sta ?frf+1

        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

?noad   ror fr0+3
        ror fr0+2
        ror fr0+1
        ror fr0
        dex
        bne ?mul
?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
        .ib
        rep #$21    ;CPU musi byc w trybie natywnym
        sep #$10

        lda fr0     ;gdy mnoznik albo mnozna jest zerem
        and fr1     ;to zerem jest rowniez wynik
        beq ?clr

        lda fr0     ;kopiujemy mnozna do rejestru pomocniczego
        sta ?frf

        stz fr0     ;zerujemy bajty wyniku
        lda #$0000

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

        clc
        adc ?frf

?noad   ror
        ror fr0
        dex
        bne ?mul

        sta fr0+2

?exit   rts

?clr    stz fr0
        stz fr0+2
        rts
        .ab
        .ib

Główna pętla zajmuje od 384 do 464 cykli maszynowych.

Elegancka procedura biblioteczna powinna jeszcze przechowywać na stosie i przed powrotem do miejsca wywołania przywracać rozmiar rejestrów. W powyższym przykładzie pominięto to, żeby nie zaciemniać zagadnienia.

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.