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

[Assembler] Jak dzielić liczby przez 10 lub 100 w asemblerze? Komendy FMUL i FMULS

lukaspaw 20 Kwi 2004 18:44 14034 11
REKLAMA
  • #1 604117
    lukaspaw
    Poziom 12  
    Posty: 104
    Ocena: 5
    panowie mam pytanie dotyczace asemblera. próbuje podzielić w nim dowolna liczbę przez np 10 czy 100 (1000), ale nie znalazłem do tego odpowiednich komend (jeśli oczywiście istnieją). widziałem że to sie da robić w C wiec w asemblerze też powinno się dać. myślałem że może pomnożyć razy odwrotność ale wtedy takie x/100 zmienia się w x*1/100 czyli mnoże razy 0,01 a tu wychodzą liczby z przecinkiem. są komendy takie jak FMUL i FMULS ale kompletnie nie wiem jak ich używać, chociaż to jeszcze-bo mam ze dwa przykłady, ale jak odczytywać to nie mam pojęcia. według książki w tych komendach liczby są traktowane jako dziesietne z przecinkiem miedzy 7 i 6 bitem, ale co to znaczy tego już nie piszą (bo niby 00000010 to oznacza 0,2? czy cos innego i wtedy można by było mnozyć max razy 1,127-11111111? nie mam pojecia). robiłem próby na symulatorze ale wychodziły mi liczby, które nie wiem jak połaczyć z faktycznym wynikiem. jeśli ktos cos wie na ten temat to prosze o radę, ewentualnie o jakiś sposób dzielenia ale w asemblerze byłoby mi to potrzebne do przeliczenia wyników z ADC do wyswietlania na LCD-chyba że ktoś ma jakiś pomysł jak przerobić wynik z ADC od 0 do 1023 na wartość wyświetlaną od -15,00V do +15,00V. dzieki.

    Zamykam. - arnoldziq
  • REKLAMA
  • #2 604301
    Gavian
    Poziom 14  
    Posty: 83
    Pomógł: 1
    Ocena: 2
    Do dzielenia liczb w asemblerze bez znaku służy komenda div lub idiv.
    Formaty
    DIV reg
    DIV mem

    Dzielna musi być w AX lub DX:AX lub EDX:EAX.
    Dla AX wynik jest w AL a reszta w AH (operandy 8bit)
    Dla DX:AX wynik w AX reszta DX (operandy 16 bit)
    Dla EDX:EAX wynik w EAX reszta w EDX (operandy 32 bit)

    Do dzielenia ze znakiem służy idiv

    Jak chcesz się bawić z FPU to załączam kilka materiałów o zmiennoprzecinkowych liczbach i FPU.
    Załączniki:
    • fpu.rar (421.71 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • REKLAMA
  • #3 604504
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 240
    lukaspaw napisał:
    są komendy takie jak FMUL i FMULS ale kompletnie nie wiem jak ich używać, chociaż to jeszcze-bo mam ze dwa przykłady, ale jak odczytywać to nie mam pojęcia. według książki w tych komendach liczby są traktowane jako dziesietne z przecinkiem miedzy 7 i 6 bitem, ale co to znaczy tego już nie piszą (bo niby 00000010 to oznacza 0,2? czy cos innego i wtedy można by było mnozyć max razy 1,127-11111111? nie mam pojecia). robiłem próby na symulatorze ale wychodziły mi liczby, które nie wiem jak połaczyć z faktycznym wynikiem.
    To są rozkazy koprocesora który operuje na liczbach w postaci mantysy i wykładnika, najpierw trzeba je załadować do FPU a potem dopiero wykonywac rozkazy, do dzielienia stałoprzecinkowego polecam wspomniany rozkaz DIV
  • #4 604851
    lukaspaw
    Poziom 12  
    Posty: 104
    Ocena: 5
    ale czy to na pewno są komendy do mikrokontrolera, jak na razie przegladnołem kilka książek i takich nie znalazłem (chodzi konkretnie o mikrokontroler ATMELa)
  • #5 605698
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 240
    lukaspaw napisał:
    ale czy to na pewno są komendy do mikrokontrolera, jak na razie przegladnołem kilka książek i takich nie znalazłem (chodzi konkretnie o mikrokontroler ATMELa)
    A gdzie kolega napisał że to ma być mikrokontroler? Podane rozwiązania są do procesora x86.
  • #6 606552
    lukaspaw
    Poziom 12  
    Posty: 104
    Ocena: 5
    początkuje w programowaniu i robie zasilacz sterowany cyfrowo. wszystko mi chodzi od ustawiania napięcia ,ograniczenia pradowego jak i przetworników ADC. zostało mi tylko napisać procedure do obsługi tego nieszczęsnego LCD.wszystkie pomysły jakie mi przychodza do głowy wymagaja dzielenia (ewentualnie mnożenia z przecinkami) i jak na razie siedze nad tym już tydzień i nie wiem jak ruszyć. gdyby bity z ADC zmieniały się równomiernie co 1 na np. 0,1V nie byłoby problemu ale u mnie na 0,1V jest ich 3,12 wiec musiałbym jakoś je mnożyć czy dzielić przez ułamki.
  • #7 607722
    djgod
    Poziom 1  
    Posty: 1
    to moze
    Załączniki:
    • PROG2AA.zip (1.98 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • REKLAMA
  • #8 607833
    h-doc
    Poziom 27  
    Posty: 1208
    Pomógł: 57
    Ocena: 21
    potrzebujesz odwzorowania:
    0 = -15.00
    1023 = +15.00

    Najpierw pozbędziemy się kropki dziesiętnej:
    0 = -1500
    1023 = +1500

    Teraz pozbędziemy się znaku:
    0 = 0
    1023 = 3000

    Przekształcenie sprowadza się więc do pomnożenia wartości z ADC przez 2,93255132.
    Pomnóżmy tę liczbę przez 256, otrzymamy 750,7331378, w przybliżeniu 751.

    Mamy zatem mnożenie bez znaku dwóch liczb CAŁKOWITYCH dwubajtowych
    (pierwsza z zakresu 0..1023 a druga to 751)

    Wynik dzielisz przez 256 (czyli odrzucasz najmłodzy bajt wyniku, najstarszego też nie bierzesz, bo jest on zawsze 0).

    Wynik masz zatem w dwóch środkowych bajtach i jest to liczba z zakresu 0..3000


    Teraz odejmujesz 1500 i otrzymujesz zakres -1500..+1500

    Dokonujesz konwersji bin->bcd i możesz to wrzucać na LCD.

    Uwaga! Podana procedura obarcza wynik pewnym błędem - żeby go zmniejszyć można przeskalować współczynnik proporcjonalności (2,93255132) o większą liczbę niż 256.
  • #9 608155
    lukaspaw
    Poziom 12  
    Posty: 104
    Ocena: 5
    a czy jest wogule w asemblerze dzielenie przez inne liczby niż 2 i jej wielokrotności bo znalazłem min. ldi r16,30/3 ale tylko tą komenda
  • REKLAMA
  • #10 608219
    lukaspaw
    Poziom 12  
    Posty: 104
    Ocena: 5
    dzieki za ZIP-a i RAR-a znowu troche wiadomosci sie zdobyło.zastanawiam sie nad sposobem H-DOC-a.ciekawy sposób- daje w końcu dla powiedzmy 1023bitów liczbe 1500 (bład o 1 ale to sie da poprawić)zapisana binarnie, czyli 101 1101 1100 (5 13 i 12)tylko jak to przetworzyć na BCD, bawiłem sie z binarnych na decymalne i hex-y oraz odwrotnie a o BCD znam zasade ich tworzenia z dziesietnych a jeśli chodzi o zamiane z binarnych to w ksiażce znalazłem tylko ze to cholernie cieżko wiec tego nie opisują. (ja kombinowałem wcześniej zeby dzielić te 1500 przez 1000 100 10 i 1 a potem dodać sobie do kazdego 48 i majac ASCII wysłać na LCD-no ale te dzielenie). mógłby mi ktoś wytłumaczyć jak to sie robi z binarnych na BCD?
  • #11 608412
    h-doc
    Poziom 27  
    Posty: 1208
    Pomógł: 57
    Ocena: 21
    Już kiedyś pisałem tutaj o konwersji bin->bcd. Są na to specjalne algorytmy. Ponieważ nigdy mi się nie chce ich szukać, konwersję przeprowadzam metodą łopatologiczną:
    1. Odejmuję od zadanej liczby 1000 tyle razy, aż uzyskam wynik ujemny. Liczba odejmowań (pomniejszona o jeden) daje cyfrę tysięcy.
    2. Koryguję liczbę po odejmowaniu (dodając z powrotem 1000, żeby uzyskać liczbę dodatnią) i odejmuję setki i zliczam ile razy te setki odjąłem aż do uzyskania liczby ujemnej. W ten sposób dostaję cyfrę setek.
    3. i tak dalej aż do uzyskania jedności.
  • #12 612810
    lukaspaw
    Poziom 12  
    Posty: 104
    Ocena: 5
    panowie dzieki za rady już mi zaczyna powoli wszystko działać, parę korekt w srodku programu i jest ok.jeszcze raz dzieki

Podsumowanie tematu

✨ Dyskusja dotyczy problemu dzielenia liczb przez 10, 100 lub 1000 w asemblerze, zwłaszcza w kontekście mikrokontrolera Atmel oraz operacji na liczbach zmiennoprzecinkowych i stałoprzecinkowych. W asemblerze x86 do dzielenia liczb całkowitych służą instrukcje DIV (dzielenie bez znaku) i IDIV (dzielenie ze znakiem), które operują na rejestrach AX, DX:AX lub EDX:EAX, a wynik i reszta są przechowywane w określonych rejestrach. Komendy FMUL i FMULS odnoszą się do koprocesora FPU i operują na liczbach zmiennoprzecinkowych w formacie mantysa-wykładnik, wymagając wcześniejszego załadowania danych do FPU. W przypadku mikrokontrolera Atmel brak jest bezpośrednich instrukcji dzielenia, co wymaga stosowania metod alternatywnych, takich jak mnożenie przez odwrotność i skalowanie liczb całkowitych. Przykład praktyczny pokazuje skalowanie wartości ADC z zakresu 0–1023 do wartości napięcia w zakresie -15.00 do +15.00 poprzez mnożenie i przesunięcia bitowe, a następnie konwersję wyniku na format BCD do wyświetlenia na LCD. Konwersja binarnych liczb całkowitych na BCD może być realizowana algorytmicznie przez wielokrotne odejmowanie wartości 1000, 100, 10 i 1, co pozwala na uzyskanie poszczególnych cyfr dziesiętnych. Wskazano, że dzielenie przez liczby inne niż potęgi dwójki w asemblerze mikrokontrolerów wymaga implementacji własnych procedur lub wykorzystania mnożenia przez stałe odwrotności. Ostatecznie autor potwierdził, że po zastosowaniu rad i korekt program działa poprawnie.
Wygenerowane przez model językowy.
REKLAMA