Programowanie: Dzielenie 16-bitowe z wynikiem 32-bitowym
From Atariki
(Różnice między wersjami)
Wersja z dnia 07:07, 21 gru 2005 KMK (Dyskusja | wkład) ← Previous diff |
Aktualna wersja KMK (Dyskusja | wkład) (w sumie po co dwa razy odejmowanie ...) |
||
Linia 1: | Linia 1: | ||
- | Procedura dzieli 16-bitową liczbę bez znaku umieszczoną we FR0 ($D4) przez takąż liczbę umieszczoną w FR1 ($E0). 16-bitowy wynik umieszczany jest w FR0, a 16-bitowa reszta z dzielenia w FR0+2. Opuszczenie procedury z ustawionym znacznikiem C sygnalizuje przepełnienie. | + | Procedura dzieli 16-bitową liczbę bez znaku umieszczoną we FR0 ($D4) przez takąż liczbę umieszczoną w FR1 ($E0). 16-bitowy wynik całkowity umieszczany jest w FR0, a 16-bitowa reszta z dzielenia w FR0+2. Opuszczenie procedury z ustawionym znacznikiem C sygnalizuje przepełnienie. |
+ | |||
+ | == 6502 == | ||
<pre> | <pre> | ||
int16div | int16div | ||
- | lda fr1 ;dzielnik musi byc wiekszy od zera | + | lda fr1 ;dzielnik musi byc wiekszy od zera |
- | ora fr1+1 | + | ora fr1+1 |
- | beq ?e | + | beq ?e |
- | lda fr0 ;dzielnik wiekszy od dzielnej | + | ; <-- czesc pomijalna |
- | cmp fr1 ;daje w wyniku zero, a dzielna | + | lda fr0 ;dzielnik wiekszy od dzielnej |
- | lda fr0+1 ;stanowi reszte | + | cmp fr1 ;daje w wyniku zero, a dzielna |
- | sbc fr1+1 | + | lda fr0+1 ;stanowi reszte |
- | bcs ?div | + | sbc fr1+1 |
+ | bcs ?div | ||
- | ldx #$01 | + | lda fr0 |
- | ?d lda fr0,x | + | sta fr0+2 |
- | sta fr0+2,x | + | lda fr0+1 |
- | dex | + | sta fr0+3 |
- | bpl ?d | + | lda #$00 |
- | lda #$00 | + | sta fr0 |
- | sta fr0 | + | sta fr0+1 |
- | sta fr0+1 | + | |
rts | rts | ||
+ | ; --> | ||
- | ?div lda #$00 ;kasujemy reszte | + | ?div lda #$00 ;kasujemy reszte |
- | sta fr0+2 | + | sta fr0+2 |
- | sta fr0+3 | + | sta fr0+3 |
- | ldx #16 | + | ldx #16 |
- | ?l asl fr0 | + | ?l asl fr0 |
- | rol fr0+1 | + | rol fr0+1 |
- | rol fr0+2 | + | rol fr0+2 |
- | rol fr0+3 | + | rol fr0+3 |
- | lda fr0+2 | + | sec |
- | cmp fr1 | + | lda fr0+2 |
- | lda fr0+3 | + | sbc fr1 |
- | sbc fr1+1 | + | tay |
- | bcc ?s | + | lda fr0+3 |
+ | sbc fr1+1 | ||
+ | bcc ?s | ||
- | lda fr0+2 | + | sty fr0+2 |
- | sbc fr1 | + | sta fr0+3 |
- | sta fr0+2 | + | |
- | lda fr0+3 | + | |
- | sbc fr1+1 | + | |
- | sta fr0+3 | + | |
- | inc fr0 | + | inc fr0 |
- | bne ?s | + | bne ?s |
- | inc fr0+1 | + | inc fr0+1 |
- | bne ?s | + | bne ?s |
?e sec | ?e sec | ||
Linia 56: | Linia 57: | ||
?s dex | ?s dex | ||
- | bne ?l | + | bne ?l |
clc | clc | ||
rts | rts | ||
</pre> | </pre> | ||
+ | |||
+ | Główna pętla zajmuje - w zależności od składników - od 624 do 1152 cykli maszynowych. | ||
+ | |||
+ | == 65C816 == | ||
+ | |||
+ | <pre> | ||
+ | int16div | ||
+ | .aw | ||
+ | .ib | ||
+ | rep #$20 ;CPU musi byc w trybie natywnym | ||
+ | sep #$10 | ||
+ | |||
+ | lda fr1 ;dzielnik musi byc wiekszy od zera | ||
+ | beq ?e | ||
+ | |||
+ | ; <-- czesc pomijalna | ||
+ | lda fr0 ;dzielnik wiekszy od dzielnej | ||
+ | cmp fr1 ;daje w wyniku zero, a dzielna | ||
+ | bcs ?div ;stanowi reszte | ||
+ | |||
+ | lda fr0 | ||
+ | sta fr0+2 | ||
+ | stz fr0 | ||
+ | rts | ||
+ | ; --> | ||
+ | |||
+ | ?div stz fr0+2 ;kasujemy reszte | ||
+ | |||
+ | ldx #16 | ||
+ | |||
+ | ?l asl fr0 | ||
+ | rol fr0+2 | ||
+ | |||
+ | sec | ||
+ | lda fr0+2 | ||
+ | sbc fr1 | ||
+ | bcc ?s | ||
+ | |||
+ | sta fr0+2 | ||
+ | |||
+ | inc fr0 | ||
+ | bne ?s | ||
+ | |||
+ | ?e sec | ||
+ | rts | ||
+ | |||
+ | ?s dex | ||
+ | bne ?l | ||
+ | |||
+ | clc | ||
+ | rts | ||
+ | </pre> | ||
+ | |||
+ | 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 jest "kompatybilna" z procedurą [[Programowanie: Mnożenie 16-bitowe z wynikiem 32-bitowym|mnożenia]] (quod vide). | ||
[[Kategoria:Niezbędnik kodera]] | [[Kategoria:Niezbędnik kodera]] |
Aktualna wersja
Procedura dzieli 16-bitową liczbę bez znaku umieszczoną we FR0 ($D4) przez takąż liczbę umieszczoną w FR1 ($E0). 16-bitowy wynik całkowity umieszczany jest w FR0, a 16-bitowa reszta z dzielenia w FR0+2. Opuszczenie procedury z ustawionym znacznikiem C sygnalizuje przepełnienie.
[Edytuj]
6502
int16div lda fr1 ;dzielnik musi byc wiekszy od zera ora fr1+1 beq ?e ; <-- czesc pomijalna lda fr0 ;dzielnik wiekszy od dzielnej cmp fr1 ;daje w wyniku zero, a dzielna lda fr0+1 ;stanowi reszte sbc fr1+1 bcs ?div lda fr0 sta fr0+2 lda fr0+1 sta fr0+3 lda #$00 sta fr0 sta fr0+1 rts ; --> ?div lda #$00 ;kasujemy reszte sta fr0+2 sta fr0+3 ldx #16 ?l asl fr0 rol fr0+1 rol fr0+2 rol fr0+3 sec lda fr0+2 sbc fr1 tay lda fr0+3 sbc fr1+1 bcc ?s sty fr0+2 sta fr0+3 inc fr0 bne ?s inc fr0+1 bne ?s ?e sec rts ?s dex bne ?l clc rts
Główna pętla zajmuje - w zależności od składników - od 624 do 1152 cykli maszynowych.
[Edytuj]
65C816
int16div .aw .ib rep #$20 ;CPU musi byc w trybie natywnym sep #$10 lda fr1 ;dzielnik musi byc wiekszy od zera beq ?e ; <-- czesc pomijalna lda fr0 ;dzielnik wiekszy od dzielnej cmp fr1 ;daje w wyniku zero, a dzielna bcs ?div ;stanowi reszte lda fr0 sta fr0+2 stz fr0 rts ; --> ?div stz fr0+2 ;kasujemy reszte ldx #16 ?l asl fr0 rol fr0+2 sec lda fr0+2 sbc fr1 bcc ?s sta fr0+2 inc fr0 bne ?s ?e sec rts ?s dex bne ?l clc rts
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.
[Edytuj]
Uwagi
Procedura jest "kompatybilna" z procedurą mnożenia (quod vide).