Byti in floati in poravnave

Vse o programiranju na in za PC

Moderatorji: Kroko, tilz0R

Byti in floati in poravnave

OdgovorNapisal/-a Kroko » 08 Mar 2017, 18:53

Spet ena preprostih stvari, ki mi je ukradla dva dneva (in noči).
(Keil in Arm)

1. dan
Začelo se je pred mnogimi leti, ko so pisci Ethernet protokola določili, da je lahko header dolg 14 bytov. Za headerjem pride payload, ki pa seveda ni poravnan na 4. Če torej naredim tole:
float vrednost =*(float*)&payload[0];
dobim hard fault error.

2. dan
Ok, sedaj ko je problem poznan je rešitev enostavna. Ker gre za del kode, kjer optimizacijja ni pomembna sem preprosto napisal takole:
float vrednost = (float)(payload[0] + (payload[1]<<8) + (payload[2] <<16) + (payload[3]<<24));
potem pa sem še cel dan ugotavljal, zakaj dobim napačno vrednost

Vzrok sem našel. Me pa zanima, kaj si ostali mislite, da je bil problem?
http://www.planet-cnc.comKroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 3193
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 566 krat
Prejel zahvalo: 1060 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 192

Re: Byti in floati in poravnave

OdgovorNapisal/-a mujo » 08 Mar 2017, 19:00

Pravilo tankega konca/pravilo debelega konca.
Nisem si jaz zmislil prevodov (islovar).
mujo
 
Prispevkov: 593
Pridružen: 21 Jan 2015, 10:50
Kraj: MB
Zahvalil se je: 0 krat
Prejel zahvalo: 114 krat
Uporabnika povabil: VolkD
Število neizkoriščenih povabil: 14

Re: Byti in floati in poravnave

OdgovorNapisal/-a Kroko » 08 Mar 2017, 19:04

Ne ni bil to problem. Vrstni red je bil pravilen.
Sem pa zgornji post napisal na pamet tako da možno, da sem v postu naredil napako.

PS
Hvala za slovenski izraz. Tega nisem vedel.
http://www.planet-cnc.comKroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 3193
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 566 krat
Prejel zahvalo: 1060 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 192

Re: Byti in floati in poravnave

OdgovorNapisal/-a TilenS » 08 Mar 2017, 19:45

Izpiše ti samo int v "float" obliki in ne IEE754.

Jaz za te byte pakirane IEE754 vrednosti ponavadi uporabim kar union:
Koda: Izberi vse
union {
  float f;
  uchar b[4];
} u;
u.b[3] = b0;
u.b[2] = b1;
u.b[1] = b2;
u.b[0] = b3;
return u.f;

Moraš pa pazit na endianness.
TilenS
 
Prispevkov: 249
Pridružen: 05 Feb 2015, 00:40
Zahvalil se je: 0 krat
Prejel zahvalo: 36 krat
Uporabnika povabil: DusanK
Število neizkoriščenih povabil: 7

Re: Byti in floati in poravnave

OdgovorNapisal/-a Kroko » 08 Mar 2017, 20:20

Epilog:
Po IEE754 je 24000.0f enako 0x46BB8000
V Keil pa je 24000.0f enako 0x00005DC0

"Floating point representation" je tudi ena takih stvari, ker vsi takoj pomislimo na IEE754, resnica je je lahko drugačna.

Takole imam sedaj in deluje pravilno:
uint8_t tmp[4] = {payload[0], payload[1], payload[2], payload[3]};
float vrednost = *(float*)tmp;
http://www.planet-cnc.comKroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 3193
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 566 krat
Prejel zahvalo: 1060 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 192

Re: Byti in floati in poravnave

OdgovorNapisal/-a tilz0R » 09 Mar 2017, 13:01

Kroko je napisal/-a:Spet ena preprostih stvari, ki mi je ukradla dva dneva (in noči).
(Keil in Arm)

1. dan
Začelo se je pred mnogimi leti, ko so pisci Ethernet protokola določili, da je lahko header dolg 14 bytov. Za headerjem pride payload, ki pa seveda ni poravnan na 4. Če torej naredim tole:
float vrednost =*(float*)&payload[0];
dobim hard fault error.

2. dan
Ok, sedaj ko je problem poznan je rešitev enostavna. Ker gre za del kode, kjer optimizacijja ni pomembna sem preprosto napisal takole:
float vrednost = (float)(payload[0] + (payload[1]<<8) + (payload[2] <<16) + (payload[3]<<24));
potem pa sem še cel dan ugotavljal, zakaj dobim napačno vrednost

Vzrok sem našel. Me pa zanima, kaj si ostali mislite, da je bil problem?


1. Hardfault dobiš samo na CPU-ju, kjer unaligned access ni dovoljen (Če imaš Cortex-M, potem je CM0 je takšen, CM0+ že dovoli, ostali tudi dovolijo).
2. Float si pa narobe dobil ker pač to ni isto kot integer, da so biti linearno postavljeni in jih samo premikaš. Tukaj je potrebno paziti tudi na endianess. Tvoja koda nikakor ni portabilna.
"Words come easy, when they're true!"
Robbie Williams, Gary Barlow
Moj nickname je tilz[NULA]R.
Uporabniški avatar
tilz0R
 
Prispevkov: 1055
Pridružen: 18 Jan 2015, 00:12
Kraj: Črnomelj
Zahvalil se je: 149 krat
Prejel zahvalo: 250 krat
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255

Re: Byti in floati in poravnave

OdgovorNapisal/-a zanka » 09 Mar 2017, 13:19

Prenosljivost kode je trd oreh in zelo težko je narediti, da bo en program delal vsepovsod. Že klic ene sistemske funkcije (npr. operacijskega sistema), uporaba nekih knjižnic ali uporaba asm v samem programu lahko prenosljivost konča.
Uporabniški avatar
zanka
 
Prispevkov: 1097
Pridružen: 17 Mar 2016, 01:16
Kraj: Krško
Zahvalil se je: 66 krat
Prejel zahvalo: 100 krat
Uporabnika povabil: DusanK
Število neizkoriščenih povabil: 19


Vrni se na Programski jeziki

Kdo je na strani

Po forumu brska: 0 registriranih uporabnikov in 1 gost