Re: přístup na byty v int C

Jaromir Sukuba jarin.hw na gmail.com
Úterý Říjen 29 09:39:14 CET 2013


Trebars XC8 kompilator, derivat PICC od Hi-Techu, skompiluje tento kusok kodu:

unsigned char a,b;
unsigned int ab;
...
ab = (((unsigned int)(a))<<8)|b;

takto:

0xFFEE: MOVF a, W, ACCESS
0xFFF0: MOVWF 0x2, ACCESS
0xFFF2: MOVF b, W, ACCESS
0xFFF4: MOVWF ab, ACCESS

Teda fakt tie 4 riadky. Stary PICC od HiTechu nemam poruke.

2013/10/29 Miroslav Draxal <evik na volny.cz>:
> Dobrý den,
>
> Tak konkrétně, vynechme načítání z eeprom, a dejme tomu, že do int potřebuji
> zapsat 0xAA a 0xBB aby výsledek byl 0xAABB. Jde o PIC, hitech kompiler. V
> asm jsou to 4 řádky, hitech si stím moc neporadí. Chci mu napovědět. Ale
> nějak nenapadá jak.
>
>
>
> From: hw-list-bounces na list.hw.cz [mailto:hw-list-bounces na list.hw.cz] On
> Behalf Of Josef Štengl
> Sent: Tuesday, October 29, 2013 8:35 AM
> To: HW-news
> Subject: Re: přístup na byty v int C
>
>
>
> Souhlasím, jen doplním.
>
> Pokud převádíte číslo z jedné velikosti typu do jiné a to oběma směry včetně
> prohazování bytů (pro ten samý typ) zapomeňte
> na na ukazatele a použijte bitové posuny:
>   · ukazatele jsou závislé na endianitě (litte endian je sice dominantní leč
> ne jediný používaný)
>   · přistupování ke stejné oblasti paměti pomocí ukazatelů na rozdílné
> velikosti je poněkud ošemetná věc, a je od C99
> poněkud zpřísněna (viz  strict aliasing rule), see níže.
>   · kompilátory většinou tyto konstrukce rozpoznávají a překládají
> optimalizovaně. Je pak docela deprimující, že se píšete
> se čtyřmi delšími řádkami a vypadne z toho jedna instrukce :-)
>
> Na union také pozapomeňte, protože u něj není zaručeno nic, kromě vnějšího
> chování (viz norma). Když už je vhodné ho
> nasadit, tak se nasazuje se znalostí implementace daného kompilátoru. Další
> možný problém je při přístupu k proměnným
> zarovnaným na hranici typu, ale to jsem nikdy neměl potřebu ověřovat.
>
> A máte to vyřešeno :-).
>
> Na ukazatele to chce vhodnější příklad.
>
> ced
>
>
>
>
> ==================================================================
>
> Zpřísněná pravidla pro přistupování k datům různými typy (pro C99 z C90)
>
> – more precise aliasing rules via effective type
>
> Info: Tuto problematiku lze vyhledat pod heslem strict aliasing rule.
>
> Strict aliasing7) znamená, že kompilátor předpokládá, že dva objekty různého
> typu neodkazují na stejnou oblast paměti. Při
> nedodržení tohoto pravidla mohou po překladu vzniknout obtížně odhalitelné
> chyby8).
>
> Důvodem zavedení tohoto pravidla je aby autoři kompilátoru mohly bezpečně
> předpokládat, že změna jedné proměnné se
> neprojeví změnou jiné. A naopak, kdy mají předpokládat, že proměnné mohou
> ukazovat na stejnou oblast paměti.
>
> Například:
>
> typedef struct
> {
>          uint16_t a;
>          uint32_t b;
> } sa_t;
>
> typedef struct
> {
>          uint16_t a;
>          uint32_t b;
> } sb_t;
>
> sa_t *a;
> sb_t *b;
>
> V tomto případě kompilátor předpokládá, že *a a *b neodkazují na stejnou
> oblast paměti ačkoliv formát struktur je shodný.
>
> sa_t *c, *d;
>
> int16_t i;
> int16_t *p = &i;
>
> Kompilátor předpokládá, že *c a *d resp i a *p mohou respektive odkazují na
> stejnou oblast paměti a nebude používat
> příslušné optimalizace.
>
> Nebo.
>
> int16_t i;
> void fce(int16_t *j, int16_t *k);
>
> fce(&i, &i);
>
> Pokud je funkce fce() volána tímto stylem (stejné typy parametrů, resp
> hodnota parametru), tak se předpokládá, žej a k
> ukazují na stejnou oblast paměti.
>
> Převedení a dereference neshodných ukazatelů obvykle znamená porušení tohoto
> pravidla. Striktní aliasing je předpokládán C
> kompilátorem, kterýžto předpokládá, že dereference ukazatelů na objekty
> rozdílného typu nebudou odkazovat na shodnou
> oblast paměti9)
>
> Pravidla pro aliasing určují okolnosti za kterých objekt může mít alias10)
> jsou definovány v kapitole 6.5 bod 7 standardu C99.
> Možné vytváření aliasů
>
> Vytváření aliasů je možné jen pro objekt k němuž je přistupováno pouze
> výrazem odkazujícím do oblasti paměti (lvalue) v
> těchto případech.
>
>      Efektivní typ nebo kvalifikovaná verze typu je shodná nebo kompatibilní
> s efektivním typem objektu.
>
> Prakticky to znamená, že typy jsou kompatibilní pokud nejsou rozdílné datové
> typy, modifikátory mohou být různé.
>
> uint32_t var;
> uint32_t* const       a = &var;
> uint32_t* volatile    b = &var;
>
>
>      Typ celých nebo přirozených čísel kompatibilní s typem (efektivní nebo
> s kvalifikovanou verzí) objektu.
>
> int32_t*              c = (int32_t*)&var;
> int32_t* const        d = (int32_t*)&var;
> int32_t* volatile     e = (int32_t*)&var;
> const int32_t* const  f = (int32_t*)&var;
>
>
>      Jednotlivé členy agregovaného typu (stuct) a typu union splňující
> předchozí podmínky (včetně vnořených členů).
>
> struct s
> {
>          int32_t j;
>          int32_t i;
>          union u
>          {
>                  uint32_t u;
>                  double d;
>          }
> };
>
> double *f = &s.u.d;
>
>
>      typ char Datové typy char*, signed char*, nebo unsigned char* mohou
> ukazovat kamkoliv na platnou adresu paměti bez
> omezení.
>
> uint64_t long;
> int8_t* malej = (int8_t *)&long;
>
>
>
>
> Dne 29.10.2013 01:17, Radek Benedikt napsal(a):
>> Miroslav Draxal píše v Po 28. 10. 2013 v 23:10 +0100:
>>> Samozřejmě, tudy cesta vede. Mě vrtá spíš jak to udělat přes ukazatele.
>>> Určitě to nějak jde. Abych se něco naučil. Míra
>>
>>>> Ještě jsem zapomněl přidat jak to dělám do teď. Ale moc se mi to
>>>> nelíbí.**
>>>> **
>>>>
>>>>                                Linear.Krok = eeprom_read
>>>> (EEpromLinearKorekce);****
>>>>
>>>>                                Linear.Krok <<= 8;****
>>>>
>>>>                                Linear.Krok |= eeprom_read
>>>> (EEpromLinearKorekce+1);****
>>>>
>>>> ** **
>>>>
>>>> Jak přistoupit přes ukazatele na int Linear.krok (byt1 ; byt2)?****
>>
>>       Slo by pretypovat pointer na Linear.krok na typ pointer na byte,
>> protoze inkrement ukazatele je o delku typu, nikoliv o byte. Nicmene je
>> to trochu drbani levou rukou za pravym uchem.
>>       Ukazatele bych nechal na pokoji a napsal bych to nacteni na jeden
>> radek, misto na tri.Usnadni se tim kompilatoru prace s optimalizaci.
>> Tohle je zrovna dost bezna konstrukce a kompilatory ji obvykle umi.
>> Nesmi v ni byt ale neco co zavisi na poradi cteni te korekce z EEprom.
>> Pak se ale neda spolehnout ani na to rozepsani na tri
>> radky.Optimalizatory pri agresivnim nastaveni umi sahnout i do takoveto
>> konstrukce. Optimalizace pointrove aritmetiky v prekladaci uz obvykle
>> tak slusna neni, je to spis o rucni optimalizaci. Jenze pri ni se do
>> toho zacinaji michat strojove zavisle veci a je pak sranda ten zdrojak
>> portovat jinam. Objevi se napr. problem little/big endian.
>>       Navic na vyse popsane konstrukci je videt, ze v podstate prirazeni
>> int
>> do int muze byt zpracovavane na nekolik kroku a neni proto atomicke. Je
>> to docela sranda pri preruseni, kdyz by se cela ta korekce jednou za cas
>> doladovala a skocila napr. z  0x3FF na 0x400. To ale jen na okraj.
>>
>>       Radek (bendikt2hw.cz)
>>
>>
>> _______________________________________________
>> HW-list mailing list  -  sponsored by www.HW.cz
>> Hw-list na list.hw.cz
>> http://list.hw.cz/mailman/listinfo/hw-list
>>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
>
>
>
> __________ Informace od ESET NOD32 Antivirus, verze databaze 8978 (20131028)
> __________
>
>
>
> Tuto zpravu proveril ESET NOD32 Antivirus.
>
> http://www.eset.cz
>
>
>
> __________ Informace od ESET NOD32 Antivirus, verze databaze 8978 (20131028)
> __________
>
>
> Tuto zpravu proveril ESET NOD32 Antivirus.
>
> http://www.eset.cz
>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
>


Další informace o konferenci Hw-list