logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Atmega8] Błąd w konwerterze BIN na BCD dla liczby 19999 - analiza kodu

Asmodat 11 Kwi 2012 22:44 2724 10
REKLAMA
  • #1 10784448
    Asmodat
    Poziom 10  
    Napisałem konwerter BIN na BCD, ale niestety ma on błąd którego nie sposób mi pojąć, niby wszystko powinno działać... jednak z liczby 19999 otrzymuję 19231
    Proszę o wskazówkę co mogło by być źle.

    1. Ładuję liczbę dziesiętną: 10^n
    2. Odejmuję ją od mojej liczby X tak długo aż 10^n będzie większa niż X
    3. Wyświetlam
    4. Poważam działanie aż do 10^1, i wyświetlam ostatnią cyfrę

    W przykładzie liczba dziesiętna BIN o precyzji do 9 znaków BCD

    Kod: text
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • REKLAMA
  • #3 10784619
    Asmodat
    Poziom 10  
    Wolał bym jednak uruchomić mój kod, może to odejmowanie jest winne czemuś, lub porównywanie ?
  • Pomocny post
    #4 10784651
    excray
    Poziom 41  
    Duużo masz tego kodu. Zobacz że "konkurencja" zrobiła to samo w kodzie 5 razy mniejszym. Dlatego moim zdaniem lepiej wgryźć się w kod gotowca i zrozumieć jego działanie. Poza tym próbowałem przejrzeć Twój kod ale jak dla mnie jest mocno nieczytelny.
  • #5 10784671
    Asmodat
    Poziom 10  
    Może tak będzie czytelniej:
    sprawdzanie ile razy 1000 mieści się w zadanej liczbie w rejestrach R1:R0

    Ogólnie mój kod nie różni się prawie niczym od tych wskazanych w linkach (to jest ten sam pomysł co mój), tyle tylko że ja operuję nie tylko na 16b a również na 32b, stąd też tyle kodu.

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Problem w tym, że pierwsze takie sprawdzanie zawsze się wykonuje dobrze, a kolejne już nie.

    Np. ustawiam liczbę binarnie 999 999 999 a otrzymuję 916 113 151
  • REKLAMA
  • Pomocny post
    #6 10784729
    excray
    Poziom 41  
    Asmodat napisał:
    cp R4, R0
    cpc R5, R1
    brlo IncR17x10p3 ;1000 jest mniejsze niż liczba X
    breq IncR17x10p3 ;1000 jest równe liczbie X

    ? Takie pobieżne szybkie spostrzeżenie - czy nie powinno być
    cp r0,r4
    cpc r1,r5
    brlo - liczba x jest mniejsza od 1000
    Poza tym czemu brlo i breq skaczą w to samo miejsce?

    Dodano po 5 [minuty]:

    Poza tym taka czysto kosmetyczna uwaga. Zamiast:
    ldi R16, 0b11101000 (młodsza połówka 1000-ca)
    mov R4, R16
    ldi R16, 0b00000011 (starsza połówka 1000-ca)
    mov R5, R16
    możesz pisać:
    ldi r16,(1000&255)
    ldi r17,(1000>>8)
    movw R4, R16
    oszczędzisz trochę czasu na przeliczanie dziesietnych na binarne, dwa bajty pamięci, jeden cykl zegara, i kilka kliknięć w klawiaturę :-)
  • #7 10784804
    Asmodat
    Poziom 10  
    tak powinno być erentualnie
    cp R0, R4
    brge - ale ta instrukcja nie działa mi prawidłowo, nie bardzo wiem co ona porównuje niby powinna być odpowiednikiem >= ale tak nie jest.

    Powiedzmy że w R5:R4 mamy liczbę 1000, a w R1:R0 2999
    np:
    2999 - 1000 = 1999, licznik = 1
    1999 - 1000 = 999, licznik = 2
    999 - 1000 koniec pętli wyświetl BCD

    więc 1 znak w BCD to będzie '2' dla liczby 2999
    kolejne 2,3,4 powinny być '9', a ja otrzymuję zgodnie z kodem z 1 postu '2','3','2'

    Czyli innymi słowy z binarnego 2999 -> bcd: '2','2','3','1


    jeśli R5:R4 jest mniejsze lub równe R1:R0 to znaczy że można odjąć 1000 od X
    jak by R1:R0 czyli X było mniejsze od 1000 to nie było by od czego odejmować



    Tylko jak to co niżej zrobić dla 32b ?
    ldi r16,(1000&255)
    ldi r17,(1000>>8)
    movw R4, R16
  • Pomocny post
    #8 10784817
    excray
    Poziom 41  
    a nie lepiej użyć brsh czyli większe lub równe (zamiast dwóch skoków brlo i breq) i użyć porównania takiego jakie podałem?
    Czyli u Ciebie:
    cp r5-r4, r1,r0
    brlo,breq - skocz jeśli 1000 mniejsze równe liczbie

    u mnie:
    cp r1-r0, r5,r4
    brsh - skocz jeśli liczba większa lub równa 1000

    na to samo wychodzi a kodu znowu mniej i bardziej czytelny.
  • #9 10784821
    Asmodat
    Poziom 10  
    ... już zostałem uprzedzony, przy edycji posta, pozmieniam, i sprawdzę wszystko jeszcze raz, bo tak jak pisałem chciałem użyć do tego celu brge ale nie działało

    przy użyciu brsh dostaję taki sam wynik jak przy brge czyli

    np:
    dla X = 1999, moje BCD same '0' a na końcu 'f'
    dla X = 9999, moje BCD same '0' a na końcu '?'
    dla X = 12345, moje BCD same '0' a na końcu '9'

    czyli gorzej niż było, bo wcześniej chociaż jedna BCD się zgadzała

    więc brsh tak jak brge nie łapie czegoś z rejestru flag, co jest ustawiane przy porównywaniu


    Zauważyłem też że jak ustawię liczbę 11199 to czyta ją dobrze, jako '1','1','1',','9','9'
    natomiast 22299 już nie łapie i podaje 22049

    dizała np:
    11099
    22099
    ...
    55099

    a już liczbę 66099 interpretuje jako 00051

    Jest to po prostu nie do pojęcia, bo nie ma tu żadnej prawidłowości.
  • #10 10784847
    excray
    Poziom 41  
    W r4-r7 masz mianownik. Niemniej z czasem przestajesz używać najstarszych rejestrów (słusznie) ale zapominasz je wyzerować (Twój błąd) i zamiast odejmować 10000 odejmujesz 111110000. BRGE stosuje się do liczb ze znakiem czyli nie u Ciebie, a BRSH jest OK tylko gdzieś popełniasz błąd. Pamiętaj że przy BRSH masz zamienić rejestry w cp czyli nie cp r4,r0 tylko cp r0,r4
  • REKLAMA
  • #11 10784874
    Asmodat
    Poziom 10  
    I to jest rozwiązanie.... brakło zerowania... Dzięki wielkie za pomoc, bo siedział bym nad tym nie tylko do dzisiaj ara ale i do jura pewnie też xD

    jak jak odejmowałem 100 od ponad 255 to się wywalał
    bo trzeba po kolei wszystkie rejestry użyć.

    Przykładowy (działający kod dla 4 BCD):
    Kod: text
    Zaloguj się, aby zobaczyć kod
REKLAMA