atarionline.pl Dzielenie w asemblerze - Forum Atarum

Jeśli chcesz wziąć udział w dyskusjach na forum - zaloguj się. Jeżeli nie masz loginu - poproś o członkostwo.

  • :
  • :

Vanilla 1.1.4 jest produktem Lussumo. Więcej informacji: Dokumentacja, Forum.

    • 1:
       
      CommentAuthorlarek
    • CommentTime10 Aug 2014 zmieniony
     
    W Tajemnicach Atari nr 4/93 są przedstawione procedury mnożenia i dzielenia w asemblerze.

    Jak jeszcze mnożenie działa poprawnie (sprawdziłem wykonując działanie kilka razy z różnymi danymi) to dzielenie już nie. Wynik dzielenia nigdy nie był prawidłowy. Wychodził jakiś kosmos nie mający nic wspólnego z dzielną i dzielnikiem.

    Tak wygląda kod:
    __div sta __bta   ;przygotowanie 
    stx __bta+1 ;danych
    ldx #0
    stx __btb
    sty __btb+1 ;dzielnik*2^8

    ldx #8 ;długość słowa

    __lop lsr __btb ;dzielnik*2(.X-1)
    ror __btb+1

    lda __bta ;dzielna-dzielnik
    sbc __btb ;a zarazem porównanie
    tay
    lda __bta+1
    sbc __btb+1
    bcc __nxt ;skok gdy __BTA<__BTB

    sty __bta ;dzielna=dzielna+
    sta __bta+1 ; -dzielnik*2(.X-1)

    __nxt rol __rsl ;"wciągnięcie" potęgi
    dex ;.X-1 do wyniku
    bne __lop
    rts

    __bta org *+2
    __btb org *+2
    __rsl org *+1


    Wykorzystanie procedury sprowadza się do umieszczenia dzielnej w .A i .X w formacie LSB i MSB, oraz dzielnika w .Y i wywołania __div. Po powrocie z podprogramu w komórce __RSL znajduje się wynik a w __BTA reszta z dzielenia.


    Przyznam, że dla mnie to wyższy stopień czarnej magii i kompletnie nie wiem, czy w procedurze jest jakiś błąd, czy też ja coś robię źle?
    Może ktoś już to kiedyś przećwiczył i jest w stanie poratować mnie informacją o ewentualnym błędzie, albo o tym, że procka jest na 100% dobra.
    Z góry dziękuję.
    • 2:
       
      CommentAuthorxeen
    • CommentTime10 Aug 2014 zmieniony
     
    Nie wiem do czego potrzebujesz dzielenia, ale może warto rozważyć procki dzielenia z tej strony, zamiast dochodzić jak działa powyższa?

    ->link<-
    • 3: CommentAuthortebe
    • CommentTime10 Aug 2014
     
    można też zajrzeć do paczki z mads-em, katalog przykładów MATH
    • 4:
       
      CommentAuthortdc
    • CommentTime10 Aug 2014
     
    Tak czytanie cudzego kodu to niezmierna przyjemność :P
  1.  
    Dla zasady dodam, że jeśli przypadkiem chcesz dzielić tylko przez 2, 4, 8, 16, itp., to możesz skorzystać z LSR.
    • 6: CommentAuthorseban
    • CommentTime10 Aug 2014
     
    proponuję zajrzeć również tu:

    ->link<-

    ->link<-
    • 7:
       
      CommentAuthorlarek
    • CommentTime10 Aug 2014
     
    Dzięki, przyjrzę się tym wszystkim przykładom.
    • 8: CommentAuthormono
    • CommentTime11 Aug 2014 zmieniony
     
    Cześć Larek. To mój artykuł i niestety z błędami. Nie umieszczono erraty, którą do nich zaniosłem :/.

    SDX w sobie ma fajną procedurę DIV32, która zrobi Ci co trzeba na 32-bit liczbach, ale niestety nie oddaje reszty.

    Linki podane przez Sebana i Xeena są jak najbardziej dobre.

    Generalnie zasada jest prosta. Jeśli potrafisz dzielić pisemnie w systemie dziesiątkowym, to zrób dokładnie to samo ale liczby zapisz binarnie i po prostu podziel tak, jakbyś to robił na liczbach dziesiątkowych :).

    Edit: Ot i cała magia.
    • 9: CommentAuthormono
    • CommentTime11 Aug 2014
     
    A tak powinna wyglądać poprawna procedura:
    __div sta __bta   ;przygotowanie
    stx __bta+1 ;danych
    ldx #0
    stx __btb
    sty __btb+1 ;dzielnik*2^8

    ldx #8 ;długość słowa

    __lop lsr __btb+1 ;dzielnik*2(.X-1)
    ror __btb
    sec
    lda __bta ;dzielna-dzielnik
    sbc __btb ;a zarazem porównanie
    tay
    lda __bta+1
    sbc __btb+1
    bcc __nxt ;skok gdy __BTA<__BTB

    sty __bta ;dzielna=dzielna+
    sta __bta+1 ; -dzielnik*2(.X-1)

    __nxt rol __rsl ;"wciągnięcie" potęgi
    dex ;.X-1 do wyniku
    bne __lop
    rts

    __bta org *+2
    __btb org *+2
    __rsl org *+1

    Bug był tutaj:
    __lop lsr __btb   ;dzielnik*2(.X-1)
    ror __btb+1

    Zamienione bajty __btb i brak sec.
    Nie jest oczywiście to najoptymalniejsza metoda i akurat dzielenie 16/8-bit można zrobić szybciej, ale zasada jest zachowana.
    • 10:
       
      CommentAuthorlarek
    • CommentTime11 Aug 2014
     
    Dzięki Mono! Nie liczyłem na to, że sam autor się znajdzie. Super, zaraz to sobie poprawię.
    • 11: CommentAuthorValdghir
    • CommentTime12 Aug 2014
     
    @larek : Co Ty tam liczysz?
    • 12:
       
      CommentAuthorlarek
    • CommentTime12 Aug 2014
     
    Na nikogo nie można w dzisiejszych czasach liczyć, to liczę na siebie ;)
    • 13:
       
      CommentAuthorKaz
    • CommentTime14 Aug 2014
     
    Chcesz sie z nami policzyc? :P

    Nie na siebie, tylko sobie liczysz :D

    (Dialogi jak z Baranowskiego :)
    • 14: CommentAuthormono
    • CommentTime14 Aug 2014
     
    Jak nie można? Przecież naprawiłem... ;]
    • 15:
       
      CommentAuthorlarek
    • CommentTime14 Aug 2014
     
    Ano właśnie, naprawiłeś i teraz już mogę liczyć :)
    • 16: CommentAuthorValdghir
    • CommentTime14 Aug 2014
     
    Tylko nie dziel przez zero... (jak mawiała babacia - cholero)
    • 17: CommentAuthormono
    • CommentTime15 Aug 2014
     
    A tam - wychodzi maksymalna możliwa liczba (co jest logiczne). W tym przypadku $FF, a reszta z dzielenia jest po prostu dzielną (no bo nic się przecież nie odjęło).
    • 18: CommentAuthorwieczor
    • CommentTime15 Aug 2014
     
    Witaj w universum Atari, gdzie dzielenie przez 0 ma rzeczywisty wynik a pętla nieskończona wykonywana jest w 4 minuty :)
    • 19: CommentAuthormono
    • CommentTime15 Aug 2014
     
    Hie hie. Wiadomo przecież nie od dziś, że odpowiedź na najważniejsze pytanie we wszechświecie to 42 :)