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 18:08 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 19:08 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 21:08
       
      można też zajrzeć do paczki z mads-em, katalog przykładów MATH
      • 4:
         
        CommentAuthortdc
      • CommentTime10 Aug 2014 21:08
       
      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 22:08
       
      proponuję zajrzeć również tu:

      ->link<-

      ->link<-
      • 7:
         
        CommentAuthorlarek
      • CommentTime10 Aug 2014 23:08
       
      Dzięki, przyjrzę się tym wszystkim przykładom.
      • 8: CommentAuthormono
      • CommentTime11 Aug 2014 11:08 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 12:08
       
      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 14:08
       
      Dzięki Mono! Nie liczyłem na to, że sam autor się znajdzie. Super, zaraz to sobie poprawię.
      • 11: CommentAuthorValdghir
      • CommentTime12 Aug 2014 21:08
       
      @larek : Co Ty tam liczysz?
      • 12:
         
        CommentAuthorlarek
      • CommentTime12 Aug 2014 22:08
       
      Na nikogo nie można w dzisiejszych czasach liczyć, to liczę na siebie ;)
      • 13:
         
        CommentAuthorKaz
      • CommentTime14 Aug 2014 16:08
       
      Chcesz sie z nami policzyc? :P

      Nie na siebie, tylko sobie liczysz :D

      (Dialogi jak z Baranowskiego :)
      • 14: CommentAuthormono
      • CommentTime14 Aug 2014 16:08
       
      Jak nie można? Przecież naprawiłem... ;]
      • 15:
         
        CommentAuthorlarek
      • CommentTime14 Aug 2014 19:08
       
      Ano właśnie, naprawiłeś i teraz już mogę liczyć :)
      • 16: CommentAuthorValdghir
      • CommentTime14 Aug 2014 22:08
       
      Tylko nie dziel przez zero... (jak mawiała babacia - cholero)
      • 17: CommentAuthormono
      • CommentTime15 Aug 2014 14:08
       
      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 14:08
       
      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 17:08
       
      Hie hie. Wiadomo przecież nie od dziś, że odpowiedź na najważniejsze pytanie we wszechświecie to 42 :)