[elektro] C aritmetika?
hg12345
hg12345 at freemail.hu
Sun Apr 4 14:05:04 CEST 2010
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]
More information about the Elektro
mailing list