Programowanie: Mnożenie 16-bitowe z wynikiem 32-bitowym: Różnice pomiędzy wersjami
Nie podano opisu zmian |
fmt + procedura dla 816 |
||
| 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 | lda fr0 ;gdy mnoznik albo mnozna jest zerem | ||
ora | ora fr0+1 ;to zerem jest rowniez wynik. | ||
beq | beq ?clr | ||
lda | lda fr1 | ||
ora | ora fr1+1 | ||
beq | beq ?clr | ||
ldx | ldx #$01 ;kopiujemy mnozna do rejestru pomocniczego | ||
?cp lda | ?cp lda fr0,x | ||
sta | sta ?frf,x | ||
dex | dex | ||
bpl | bpl ?cp | ||
jsr | jsr ?clr ;zerujemy bajty wyniku | ||
ldx | ldx #16 | ||
?mul lsr | ?mul lsr fr1+1 ;glowna petla | ||
ror | ror fr1 | ||
bcc | bcc ?noad | ||
clc | clc | ||
lda | lda fr0+2 | ||
adc | adc ?frf | ||
sta | sta fr0+2 | ||
lda | lda fr0+3 | ||
adc | adc ?frf+1 | ||
sta | sta fr0+3 | ||
bcs | bcs ?exit | ||
?noad lsr | ?noad lsr fr0+3 | ||
ror | ror fr0+2 | ||
ror | ror fr0+1 | ||
ror | ror fr0 | ||
dex | dex | ||
bne | bne ?mul | ||
clc | clc | ||
?exit rts | ?exit rts | ||
| Linia 52: | Linia 54: | ||
rts | rts | ||
</pre> | </pre> | ||
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. | 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 21 gru 2005, 08:49
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.