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

From Atariki

(Różnice między wersjami)
Jump to: navigation, search
Wersja z dnia 07:57, 21 gru 2005
KMK (Dyskusja | wkład)
(65C816)
← Previous diff
Aktualna wersja
KMK (Dyskusja | wkład)
(ulepszenia i poprawki)
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 == == 6502 ==
Linia 7: 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.
Linia 16: Linia 15:
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
Linia 36: Linia 34:
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
Linia 44: Linia 41:
dex dex
bne ?mul bne ?mul
- clc 
?exit rts ?exit rts
Linia 75: Linia 71:
sta ?frf sta ?frf
- jsr ?clr ;zerujemy bajty wyniku+ stz fr0 ;zerujemy bajty wyniku
 + lda #$0000
ldx #16 ldx #16
Linia 82: Linia 79:
clc clc
- lda fr0+2 
adc ?frf adc ?frf
- sta fr0+2 
- bcs ?exit 
-?noad lsr fr0+2+?noad ror
ror fr0 ror fr0
dex dex
bne ?mul bne ?mul
- clc+ sta fr0+2
 + 
?exit rts ?exit rts
Linia 98: Linia 93:
stz fr0+2 stz fr0+2
rts rts
 + .ab
 + .ib
</pre> </pre>
-Główna pętla zajmuje od 432 do 656 cykli maszynowych.+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 == == Uwagi ==

Aktualna wersja

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.

Personal tools