[elektro] C aritmetika?

Skandar Graun sgraun at gmail.com
Sun Apr 4 19:25:36 CEST 2010


Ja, igen, hasonló okok miatt cserélem le a basicot, erre itt is ezt csináljuk.

2010/4/4 Skandar Graun <sgraun at gmail.com>:
> Én is, de nem mertem javasolni.
> A visszafordított lista alapján nem is lenne nehéz belenyúlni.
>
> 2010/4/4 Bali Zoltan <eltexto at freemail.hu>:
>> Ahogy gondoltam a longra már nem ad helyes eredményt, csak ha castolom
>> valamelyiket.
>> Viszont minden esetben használja a HW szorzót ( persze a 8 bit miatt
>> többször).
>>
>> Én is az elején belefutottam párszor ebbe de, azóta mindig castolok,
>> vsz. ezert csak most tünt
>> fel hogy a 8 bites példámnál nem kell castolni.
>> Nálad csak az a gond, hogyha szabályosan csinálod, nem használja a HW
>> szozót.
>> Én átirnám ASM -re ezt a kritikus részt.
>>
>> Üdv.  Zoli
>>
>>
>>
>>
>> 2010. 04. 04. 14:05 keltezéssel, hg12345 írta:
>>> Elhiszem...., az ASM rész csak nagy vonalakban értem, látni láttam, de még nem használtam AVR-t. Milyen forditó? Erre is helyes eredményt ad?  int A,B;long C=0;A=0x7FFF;B=0x7FFE;C=A*B; Nálam mindegy a szorzás eredménye mérete mindig a legnagyobb méerű taggéval egyezik, elvileg ez az alaphelyzet. (Ami egy nagy butaság)
>>> Amúgy ez egy MACRO  ill függvény definiálási hiba, ha helyesen definálja a függvént long MUL (int , int) akkor ugyan azt az értéket kapja a felhasználó mint eddig, mert a bal érték int akkor azt kapja mint most, ha balérték long akkor meg helyes eredményt..... Elég sok ilyen apró kellemetlenség van ezzel a fordítóval....
>>>
>>> Bali Zoltan<eltexto at freemail.hu>  írta:
>>>
>>>> Na már értem, pedig ilyet én is szoktam csinálni. Úgy látszik
>>>> felületesen olvastalak :( .
>>>>
>>>>
>>>>> Ez egy tipikus C hiba, reméltem valaki ismeri a kikerülését.
>>>>>
>>>> Na akkor az én forditóm hibás, mert ha jól nézem, akkor ez nem hagyja
>>>> figyelmen kivül
>>>> a felsö byte-ot.    Csak 8 bitesen tudtam kipróbálni mert a szorzó és a
>>>> CPU 8 bites.
>>>>
>>>> C teszt program:
>>>>
>>>> unsigned char    A,B;
>>>> unsigned char    res;
>>>>
>>>> void    main    (void)
>>>> {
>>>>      A = PINA; B = PINB;
>>>>
>>>>      res    = (A*B)>>4;
>>>>
>>>>      printf("Res: %u",res);
>>>>
>>>>      while(1);
>>>>
>>>> }
>>>>
>>>> ASM  result:
>>>>
>>>> main:
>>>> //    9 {
>>>> //   10     A = PINA; B = PINB;
>>>>          IN      R16, 0x19
>>>>          STS     A, R16
>>>>          IN      R16, 0x16
>>>>          STS     B, R16
>>>> //   11
>>>> //   12     res    = (A*B)>>4;
>>>>          LDS     R16, A
>>>>          LDS     R17, B
>>>>          MUL     R16, R17
>>>>          MOVW    R17:R16, R1:R0
>>>>          LDI     R20, 4
>>>>          CALL    ?SS_SHR_L02
>>>>          STS     res, R16
>>>> //   13
>>>> //   14     printf("Res: %u",res);
>>>>          LDS     R16, res
>>>>          LDI     R17, 0
>>>>          ST      -Y, R17
>>>>          ST      -Y, R16
>>>>          LDI     R16, LOW(`?<Constant "Res: %u">`)
>>>>          LDI     R17, (`?<Constant "Res: %u">`)>>  8
>>>>          CALL    printf
>>>>          ADIW    R29:R28, 2
>>>>
>>>> A     CALL    ?SS_SHR_L02        R17,R16 ot shifteli
>>>>
>>>> És castolni sem kellet, és a HW szorzót használja és a 8x8 bitet shifteli.
>>>>
>>>> Én, ha nem tetszik az amit a foditó csinál, generáltatok vele a c
>>>> forrásról egy
>>>> ASM listát, belejavítok, a C forrásfile-t leszedem és hozzáadom a módositott
>>>> asm forrást.
>>>> Hátránya, csak akkor célszerü ezt csinálni, ha már a c forráson nem lesz sok
>>>> módosítás.  Vagy mindig eljátszani ezt. Vagy a kritikus részt egy külön
>>>> C forrásfile-ba helyezni.
>>>>
>>>>
>>>> Üdv.  Zoli
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> 2010. 04. 04. 11:05 keltezéssel, hg12345 írta:
>>>>
>>>>> Az eredmény unsigned int!!!!!! Ez teljesen mindegy milyen uC, de ez a 16 bites rendszerek korlátja. (a 8 bitesnél ez előbb jön elő). Ha 32 bites használnék, akkor a második sort mosolyogva megoldaná fordító.
>>>>>
>>>>> Teljesen elvagyok szomorodva, hogy nem tudok értelmesen írni :-(
>>>>>
>>>>> A számítás pontossága miatt minél nagyobb bitszámon végzem a műveletet annál pontosabb lesz. Az egész tologatás azért van, hogy ne így kell  csinálni.
>>>>>
>>>>>     Aset.ICBUF32 *((long long)ASETS_DAcom)>>   16;   //(ez ezért durva)
>>>>>
>>>>> közvetlen 16 bites méretű kontroller gépi kódja átírata C-re, de ez a C h tudatlansága miatt nem működik (ez rövidebb és gyorsabb, kicsit pontatlanabb)
>>>>>     (((unsigned int)(Aset.ICBUF32>>12)) * ASETS_DAcom )>>4 ;
>>>>>
>>>>> ha csak az iskolai matematikát nézem a két sor elvileg megegyezik egymással, a pontosságot kivéve, mivel a számok egészek.....
>>>>>
>>>>> Ez első  64 bites aritmetikát használ, hogy véletlenűl se legyen hibás az eredmény (32bit * 16bit  az 48bit, de ilyen nincs a C-ben)
>>>>> A második végig 16 bites aritmetikával számol és kihasználja a uC HW szorzás lehetőséget (ezt a C-be már nem tudták implementálni :-(
>>>>>
>>>>> Méret és sebességben van némi különbség... (IT)
>>>>>
>>>>>
>>>>> Remélem most érthető.  Nem értem másoknak nem merűl fel ilyen probléma....
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Nem nagyon értem a dolgot ( nehezen igazodok el az asm forráson), de
>>>>> azért belevau-zok .
>>>>>
>>>>> 32 bites x értékére van szükséged ? Akkor miért int az x ?
>>>>>
>>>>> volatile long x;     nem segit ?
>>>>>
>>>>> Üdv.  Zoli
>>>>>
>>>>> ps. Gyanitom hogy ez egy PIC asm forrása. Hát, akkor már tudom, hogy életem
>>>>> hátralevö részében már PIC-et biztos nem fogok használni :)  .
>>>>>
>>>>>
>>>>>
>>>>> 2010. 04. 04. 10:15 keltezéssel, hg12345 írta:
>>>>>
>>>>>
>>>>>> Nem tudom elég érhetően fogalmaztam. Ez egy tipikus C hiba, reméltem valaki ismeri a kikerülését.
>>>>>>
>>>>>> Részletesen itt van.
>>>>>>
>>>>>> A dolog nagyon egyszerű, a C program írói a következő feltételezéseket tették (az iskolában nem figyeltek)  16bit*16bit=16bit ez a legtöbb esetben így van... (náluk szorzás művelet eredménye egyezik, a tagok méretével, az iskolában az tanítják az eredmény mérete a két tag méretének összege.....:-)
>>>>>>
>>>>>> egy kompenzációs számot szeretnék generálni IT ben, itt különösen problémás a rutin hívás, mert ilyenkor a teljes általános regiszter készletet menti, ha kell ha nem kell!
>>>>>>
>>>>>> int ASETS_DAcom; /// ICBUF32 ez egy long.....
>>>>>> int x;
>>>>>> x = (((unsigned int)(Aset.ICBUF32>>12)) * ASETS_DAcom)>>4;
>>>>>>
>>>>>> Az eredmény:
>>>>>>
>>>>>>      4D6E  804F20     mov.w Aset,w0
>>>>>>      4D70  804F31     mov.w 0x09e6,w1
>>>>>>      4D72  DD0944     sl w1,#4,w2
>>>>>>      4D74  DE004C     lsr w0,#12,w0
>>>>>>      4D76  710000     ior.w w2,w0,w0
>>>>>>      4D78  DE08CC     lsr w1,#12,w1
>>>>>>      4D7A  8050C2     mov.w ASETS_DAcom,w2
>>>>>>      4D7C  B98002     mul.ss w0,w2,w0
>>>>>>      4D7E  DE0048     lsr w0,#8,w0
>>>>>>      4D80  884FC0     mov.w w0,0x09f8
>>>>>>
>>>>>> A mul.ss jó is, de itt az eredmény 32 bites és a felső 16 bitet nem (használja) csak az alsót shifteli, az eredmény hibás lesz....
>>>>>>
>>>>>> Ha long x... akkor látszik igazán a metematikai zsenialítása (szenialítása:-)
>>>>>>      4D7C  B98002     mul.ss w0,w2,w0
>>>>>>      4D7E  DE0044     lsr w0,#4,w0
>>>>>>      4D80  200001     mov.w #0x0,w1  ;//itt törli a felső 16 bitet
>>>>>>      4D82  DD0A4C     sl w1,#12,w4
>>>>>>      4D84  DE0044     lsr w0,#4,w0
>>>>>>      4D86  720000     ior.w w4,w0,w0
>>>>>>      4D88  DE88C4     asr w1,#4,w1
>>>>>>      4D8A  884FC0     mov.w w0,0x09f8
>>>>>>
>>>>>> mivel optimalizálva van a fordítás, és később csak 16 biten használom így látja, hogy nem kell csak az alsó word-t menteni. Röviden törölte shiftelte a semmit és még nem is használta.
>>>>>>
>>>>>>
>>>>>> Ha bármelyik  tényezőt cast-olom:
>>>>>>
>>>>>> x = (((unsigned int)(Aset.ICBUF32>>12)) *((unsigned long) ASETS_DAcom))>>4;
>>>>>>
>>>>>>      4D6E  804F20     mov.w Aset,w0
>>>>>>      4D70  804F31     mov.w 0x09e6,w1
>>>>>>      4D72  DD0944     sl w1,#4,w2
>>>>>>      4D74  DE004C     lsr w0,#12,w0
>>>>>>      4D76  710000     ior.w w2,w0,w0
>>>>>>      4D78  DE08CC     lsr w1,#12,w1
>>>>>>      4D7A  200001     mov.w #0x0,w1
>>>>>>      4D7C  8050C2     mov.w ASETS_DAcom,w2
>>>>>>      4D7E  DE91CF     asr w2,#15,w3
>>>>>>      4D80  07DABD     rcall __mulp32eds3
>>>>>>      4D82  DD0A4C     sl w1,#12,w4
>>>>>>      4D84  DE0044     lsr w0,#4,w0
>>>>>>      4D86  720000     ior.w w4,w0,w0
>>>>>>      4D88  DE08C4     lsr w1,#4,w1
>>>>>>      4D8A  DE8044     asr w0,#4,w0
>>>>>>      4D8C  884FC0     mov.w w0,0x09f8
>>>>>>
>>>>>> Igy jó az eredmény, de még van egy halom PUSH és POP amit nem szeretnék..... kicsit tovább tart a másik tökéletesen kiszámítja de nem ismeri fel hogy még van az eredményben tartalék.
>>>>>>
>>>>>> -----------------------------------------------
>>>>>>
>>>>>> Nagyon nagy kár, hogy a segíteni akarnak a programozóknak minél kevesebb hibát elkövetni, ahelyett hogy megtanítanák a programozókat programozni. A C-ben a korlátok kikerülése több energiát és időt igényel mint a maga a programozás.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>      Huu, ez kissé zavaros.
>>>>>> Felső 16 bit törölve?
>>>>>> Utána long-ban?
>>>>>> Castolás átteszi szoftver rutinba?
>>>>>> Vagy csak én vagyok nagyon gyenge?
>>>>>>
>>>>>> 2010/4/4 hg12345<hg12345 at freemail.hu>:
>>>>>>
>>>>>>
>>>>>>
>>>>>>> Hi C-ben kikerülhető valamilyen módon, hogy 16bit * 16bit eredmény valóban 32 bit legyen? MPLAB C (GCC 4.03) elvégzi a szorzást az eredmény tényleg 32 bites (ez HW csinálja) majd ami biztos alapon a gyorsan törli a felsö 16 bitet és az így kapott eredményt tárolja egy long változóban. A művelet elött castolom akkor jó az eredmény, nem véletlen mert 32b * 322b szorzást csinál és HW helyet szubrutin.... A fordító program írói nem ismerték a szorzás tulajdonságát?!  Üdv
>>>>>>>
>>>>>>>
>>>>>>>
>>>> -----------------------------------------
>>>>           elektro[-flame|-etc]
>>>>
>>> -----------------------------------------
>>>            elektro[-flame|-etc]
>>>
>>>
>>>
>>
>> -----------------------------------------
>>          elektro[-flame|-etc]
>>
>



More information about the Elektro mailing list