Programowanie: Dzielenie 16-bitowe z wynikiem 32-bitowym

From Atariki

(Różnice między wersjami)
Jump to: navigation, search
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.

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.

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.

Uwagi

Procedura jest "kompatybilna" z procedurą mnożenia (quod vide).

Personal tools