Svetelektro.com

Svetelektro.com

Meno:
Heslo:
SVETELEKTRO • Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

C,C++,C#

Moderátori: psichac, Moderátori

Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

Odosla┼ąod Dumitru » 13 Dec 2018, 00:19

K├│d: Vybra┼ą v┼íetko
uint16_t temp;
uint8_t data[2];

// be┼żn├Ż z├ípis
temp = data[1];
temp = temp<<8;
temp |= data[0];

// UDAJNE to iste ale inak

*((char *)&Temp) = data[1];
*((char *)&Temp+1) = data[0];



─îaute m├┤┼żete mi niekto vysvetli┼ą druhy z├ípis a ─Źi je naozaj toto┼żn├Ż a r├Żchlej┼í├ş ?

*(data) je to iste ako data[0]
*(data+1) je to iste ako data[1]

tomuto rozumiem ale jednasa o pole teda viac premien rovnak├ęho typu

tam ale mam jednu premenn├║ 16 bitovu ktor├║ ako keby adresovo rozbili na 2-e 8 bitove :rolleyes:

V─Ćaka
Dumitru
St├íly ─Źlen
St├íly ─Źlen
Pr├şspevky: 331
Zalo┼żen├Ż: 06.11.2011
Karma: 0

Re: Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

Odosla┼ąod peterple » 13 Dec 2018, 00:42

Je aj nie je. V pr├şpade ┼że preklada─Ź pou┼ż├şva big endian reprezent├íciu tak ├íno. Ak ale tak├Żto k├│d niekto premigruje na little endian architekt├║ru tak je to v h├íji.
A ├íno je to r├Żchlej┼íie.
Uk├í┼ż m├║dremu chybu a on sa ti po─Ćakuje. Uk├í┼ż chybu hlup├íkovi a on sa uraz├ş.
peterple
Ultimate ─Źlen
Ultimate ─Źlen
Pr├şspevky: 1847
Vek: 52.47
Zalo┼żen├Ż: 25.06.2013
Bydlisko: Krajn├ę
Karma: 52

Re: Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

Odosla┼ąod budvar10 » 13 Dec 2018, 08:50

V┼íetko z├íle┼ż├ş na kompil├ítore a na jeho nastaven├ş. Najefekt├şvnej┼íie a z poh─żadu preklada─Źa najspo─żahlivej┼íie je pou┼żitie union.

V tom prvom pr├şpade je vysok├í pravdepodobnos┼ą, ┼że sa to prelo┼ż├ş ako matematick├í oper├ícia s─Ź├ştania a preto tam m├┤┼żu by┼ą nadbyto─Źn├ę in┼ítrukcie z poh─żadu moment├ílneho pou┼żitia.
budvar10
Obr├ízok pou┼ż├şvate─ża
St├íly ─Źlen
St├íly ─Źlen
Pr├şspevky: 431
Zalo┼żen├Ż: 15.12.2014
Bydlisko: Košice
Karma: 7

Re: Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

Odosla┼ąod Dumitru » 13 Dec 2018, 09:09

Ja tomu st├íle presne nerozumiem pre─Źo toto
K├│d: Vybra┼ą v┼íetko

*((char *)&temp+1) //ukazuje (pointer) na mladšie 8bit premennej temp
*((char *)&temp)  // ukazuje (pointer) na star┼íie 8bit premennej temp


pre m┼ła z├ípis *(temp+1) je ┼że sa posuniem na ─Ćal┼íiu premenn├║ ktor├í je 16bitova :confused: ale tuto je to v r├ímci jednej premennej

ak mam 32bitovu premenn├║ tak tam m├┤┼żem takto zapisova┼ą data ?

K├│d: Vybra┼ą v┼íetko
*((char *)&temp) = , *((char *)&temp+1) = , *((char *)&temp+2) = ,*((char *)&temp+3) =...


alebo

K├│d: Vybra┼ą v┼íetko
*((uint16_t *)&temp) = , *((uint16_t *)&temp+1) =
Dumitru
St├íly ─Źlen
St├íly ─Źlen
Pr├şspevky: 331
Zalo┼żen├Ż: 06.11.2011
Karma: 0

Re: Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

Odosla┼ąod cirkus » 13 Dec 2018, 10:00

mozes to zapisat takto

K├│d: Vybra┼ą v┼íetko
((uint8_t*)&temp)[0] = data[0];
((uint8_t*)&temp)[1] = data[1];


a nemusis riesit nejake pricitavanie alebo co
cirkus
Okoloid├║ci
Okoloid├║ci
Pr├şspevky: 16
Zalo┼żen├Ż: 07.02.2017
Karma: 1

Re: Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

Odosla┼ąod Dumitru » 13 Dec 2018, 12:39

To je len vec zápisu
Dumitru
St├íly ─Źlen
St├íly ─Źlen
Pr├şspevky: 331
Zalo┼żen├Ż: 06.11.2011
Karma: 0

Re: Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

Odosla┼ąod Tribec Zacks » 13 Dec 2018, 13:58

Dumitru nap├şsal:
K├│d: Vybra┼ą v┼íetko
uint16_t temp;
uint8_t data[2];

// be┼żn├Ż z├ípis
temp = data[1];
temp = temp<<8;
temp |= data[0];

// UDAJNE to iste ale inak

*((char *)&Temp) = data[1];
*((char *)&Temp+1) = data[0];



─îaute m├┤┼żete mi niekto vysvetli┼ą druhy z├ípis a ─Źi je naozaj toto┼żn├Ż a r├Żchlej┼í├ş ?

*(data) je to iste ako data[0]
*(data+1) je to iste ako data[1]

tomuto rozumiem ale jednasa o pole teda viac premien rovnak├ęho typu

tam ale mam jednu premenn├║ 16 bitovu ktor├║ ako keby adresovo rozbili na 2-e 8 bitove :rolleyes:

V─Ćaka



@Dumitru, v podobnych situaciach je najlepsie to nakodit a pozret disassembly ako je to prelozene na instrukcie:
K├│d: Vybra┼ą v┼íetko
volatile uint16_t temp;
volatile uint8_t data[2] = {0xad, 0xde};

void merge_8bit_1(){
    temp = data[1];
    temp = temp<<8;
    temp |= data[0];
}

void merge_8bit_2(){
    *((char *)&temp) = data[1];
    *((char *)&temp+1) = data[0];
}


je to kompilovane bez optimalizacie pre cortex-f7 (armv7e)
rozdiel je ze v prvom pripade je to robene ako matematicka operacie, nacitaj register, uprav na format, uloz, zopakuj pre druhe cislo, pak nacitaj, urob OR, uloz.
v druhom pripade je to podobne, ale odpada cele zvlast ukladanie upravenych premennych, znovu nacitanie, prevedenie OR... proste ich nacita, prevede na format a ulozi na iny offset v pamati.

K├│d: Vybra┼ą v┼íetko
void merge_8bit_1(){
merge_8bit_1:
  push    {r7}
  add     r7, sp, #0
    temp = data[1];
  ldr     r3, [pc, #56]   ; (0x20003ee0 <merge_8bit_1+64>)
  ldrb    r3, [r3, #1]
  uxtb    r3, r3
  uxth    r2, r3
  ldr     r3, [pc, #52]   ; (0x20003ee4 <merge_8bit_1+68>)
  strh    r2, [r3, #0]
    temp = temp<<8;
  ldr     r3, [pc, #48]   ; (0x20003ee4 <merge_8bit_1+68>)
  ldrh    r3, [r3, #0]
  uxth    r3, r3
  lsls    r3, r3, #8
  uxth    r2, r3
  ldr     r3, [pc, #40]   ; (0x20003ee4 <merge_8bit_1+68>)
  strh    r2, [r3, #0]
    temp |= data[0];
  ldr     r3, [pc, #32]   ; (0x20003ee0 <merge_8bit_1+64>)
  ldrb    r3, [r3, #0]
  uxtb    r3, r3
  uxth    r2, r3
  ldr     r3, [pc, #28]   ; (0x20003ee4 <merge_8bit_1+68>)
  ldrh    r3, [r3, #0]
  uxth    r3, r3
  orrs    r3, r2
  uxth    r2, r3
  ldr     r3, [pc, #16]   ; (0x20003ee4 <merge_8bit_1+68>)
  strh    r2, [r3, #0]
}


K├│d: Vybra┼ą v┼íetko
void merge_8bit_2(){
merge_8bit_2:
  push    {r7}
  add     r7, sp, #0
    *((char *)&temp) = data[1];
  ldr     r3, [pc, #32]   ; (0x20003f10 <merge_8bit_2+40>)
  ldrb    r3, [r3, #1]
  uxtb    r2, r3
  ldr     r3, [pc, #32]   ; (0x20003f14 <merge_8bit_2+44>)
  sxtb    r2, r2
  strb    r2, [r3, #0]
    *((char *)&temp+1) = data[0];
  ldr     r3, [pc, #20]   ; (0x20003f10 <merge_8bit_2+40>)
  ldrb    r3, [r3, #0]
  uxtb    r2, r3
  ldr     r3, [pc, #24]   ; (0x20003f18 <merge_8bit_2+48>)
  sxtb    r2, r2
  strb    r2, [r3, #0]
}


ak zapnes optimalizaciu (gcc -O1), situacia je podstatne lepsia, ale stale v prospech druheho zapisu koli ORovaniu v prvom:
K├│d: Vybra┼ą v┼íetko
*((char *)&temp) = data[1];
merge_8bit_1:
  ldr     r1, [pc, #24]   ; (0x200027c8 <merge_8bit_1+28>)
  ldrb    r2, [r1, #1]
  ldr     r3, [pc, #24]   ; (0x200027cc <merge_8bit_1+32>)
  strh    r2, [r3, #0]
    temp = temp<<8;
  ldrh    r2, [r3, #0]
  lsls    r2, r2, #8
  uxth    r2, r2
  strh    r2, [r3, #0]
    temp |= data[0];
  ldrb    r2, [r1, #0]
  ldrh    r1, [r3, #0]
  orrs    r2, r1
  strh    r2, [r3, #0]
}


K├│d: Vybra┼ą v┼íetko
*((char *)&temp) = data[0];
merge_8bit_2:
  ldr     r2, [pc, #12]   ; (0x200027e0 <merge_8bit_2+16>)
  ldrb    r1, [r2, #1]
  ldr     r3, [pc, #12]   ; (0x200027e4 <merge_8bit_2+20>)
  strb    r1, [r3, #0]
    *((char *)&temp+1) = data[0];
  ldrb    r2, [r2, #0]
  strb    r2, [r3, #1]
}


situacia je velmi podobna aj na x86 (gcc -o0):
K├│d: Vybra┼ą v┼íetko
merge_8bit_1:
  movzbl  0x295b(%rip),%eax        # 0x404089 <data+1>
  movzbl  %al,%edx
  lea     0x7238(%rip),%rax        # 0x408970 <temp>
  mov     %dx,(%rax)
    temp = temp<<8;
  lea     0x722e(%rip),%rax        # 0x408970 <temp>
  movzwl  (%rax),%eax
  shl     $0x8,%eax
  mov     %eax,%edx
  lea     0x721f(%rip),%rax        # 0x408970 <temp>
  mov     %dx,(%rax)
    temp |= data[0];
  movzbl  0x292d(%rip),%eax        # 0x404088 <data>
  movzbl  %al,%edx
  lea     0x720b(%rip),%rax        # 0x408970 <temp>
  movzwl  (%rax),%eax
  or      %eax,%edx
  lea     0x71ff(%rip),%rax        # 0x408970 <temp>
  mov     %dx,(%rax)
}


K├│d: Vybra┼ą v┼íetko
*((char *)&temp) = data[1];
merge_8bit_2:
  movzbl  0x290c(%rip),%edx        # 0x404089 <data+1>
  lea     0x71ec(%rip),%rax        # 0x408970 <temp>
  mov     %rax,%rcx
  mov     %edx,%eax
  mov     %al,(%rcx)
    *((char *)&temp+1) = data[0];
  movzbl  0x28f6(%rip),%edx        # 0x404088 <data>
  lea     0x71d7(%rip),%rax        # 0x408970 <temp>
  lea     0x1(%rax),%rax
  mov     %dl,(%rax)
}


so zapnutou optimalizaciou -O1
K├│d: Vybra┼ą v┼íetko
temp = data[1];
merge_8bit_1:
  movzbl  0x199f(%rip),%eax        # 0x403061 <data+1>
  movzbl  %al,%eax
  mov     %ax,0x62a4(%rip)        # 0x407970 <temp>
    temp = temp<<8;
  movzwl  0x629d(%rip),%eax        # 0x407970 <temp>
  shl     $0x8,%eax
  mov     %ax,0x6293(%rip)        # 0x407970 <temp>
    temp |= data[0];
  movzbl  0x197c(%rip),%eax        # 0x403060 <data>
  movzwl  0x6285(%rip),%edx        # 0x407970 <temp>
  movzbl  %al,%eax
  or      %edx,%eax
  mov     %ax,0x6279(%rip)        # 0x407970 <temp>


K├│d: Vybra┼ą v┼íetko
*((char *)&temp) = data[1];
merge_8bit_2:
  movzbl  0x1962(%rip),%eax        # 0x403061 <data+1>
  mov     %al,0x626b(%rip)        # 0x407970 <temp>
    *((char *)&temp+1) = data[0];
  movzbl  0x1954(%rip),%eax        # 0x403060 <data>
  mov     %al,0x625f(%rip)        # 0x407971 <temp+1>


ak aj zvolis vysie optimalizacie, situacia je stale rovnaka, v druhom pripade usetris OR medzi dvoma registrami
Kreativita a motivacia je to, co prinasa originalne napady a myslienky, disciplina je to, co ich dokaze zrealizovat.
Tribec Zacks
Obr├ízok pou┼ż├şvate─ża
Pokro─Źil├Ż ─Źlen
Pokro─Źil├Ż ─Źlen
Pr├şspevky: 612
Vek: 36.73
Zalo┼żen├Ż: 26.06.2010
Bydlisko: Levice / Cork IRL
Karma: 21

Re: Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

Odosla┼ąod peterple » 13 Dec 2018, 20:46

Tak toto bude mo┼żno ┼ąa┼żk├Ż boj, preto to rozdel├şm na viacero pr├şspevkov.Na za─Źiatok ─żahk├í delostreleck├í pr├şprava:
Dumitru nap├şsal:Ja tomu st├íle presne nerozumiem pre─Źo toto
K├│d: Vybra┼ą v┼íetko

*((char *)&temp+1) //ukazuje (pointer) na mladšie 8bit premennej temp
*((char *)&temp)  // ukazuje (pointer) na star┼íie 8bit premennej temp

pre m┼ła z├ípis *(temp+1) je ┼że sa posuniem na ─Ćal┼íiu premenn├║ ktor├í je 16bitova :confused: ale tuto je to v r├ímci jednej premennej

Nu┼ż to by bola pravda keby si tam nemal to pretypovanie. Ale ked┼że pretypovanie je bli┼ż┼íia ko┼íe─ża ako +1 k├íbat tak si z toho najprv urobil ukazate─ż na byte. A potom si potom posunul o jeden byte ─Ćalej. To je v skuto─Źnosti druh├Ż byte toho int16
Mlad┼íie a star┼íie byty to sa kde pou┼ż├şva tak├íto hant├şrka? Jedno je doln├Ż byte toho intu a druh├ę je horn├Ż byte toho int (ked┼że je 16 bitov├Ż)
D├║fam ┼że sa to d├í pochopi┼ą z prilo┼żen├ęho obr├ízka. Je to kompilovan├ę v AVR studiu pre nejak├Ż ATMega328P ─Źo je arduine (nech zabijeme dve muchy jednou ranou)
Tam si treba uvedomi┼ą jednu vec. Je to little endian architektura (podobne ako je aj x86)

A na tejto architekt├║re to bude fungova┼ą chybne
teda prv├Ż k├│d vyr├íta nejak├ę ─Ź├şslo a druh├Ż k├│d vyr├íta ├║plne in├ę ─Ź├şslo. Kto chce m├┤┼że sk├║si┼ą na to pr├şs┼ą s├ím ak├ę to bud├║ ─Ź├şsla.
Budem pokra─Źova┼ą ─Ćal┼í├şm pr├şspevkom
Pr├şlohy
byte2word01.png
Uk├í┼ż m├║dremu chybu a on sa ti po─Ćakuje. Uk├í┼ż chybu hlup├íkovi a on sa uraz├ş.
peterple
Ultimate ─Źlen
Ultimate ─Źlen
Pr├şspevky: 1847
Vek: 52.47
Zalo┼żen├Ż: 25.06.2013
Bydlisko: Krajn├ę
Karma: 52

Re: Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

Odosla┼ąod Dumitru » 13 Dec 2018, 22:03

─Äakujem pekne za ob┼í├şrne vysvetlenie u┼ż je mi to jasne :) :agree:

─îo sa tyk├í big endian a little endian s├║ mi jasne rizika :) jedna architektura uklad├í od An ......... A0 a ─Ćal┼íia presne naopak :)
Dumitru
St├íly ─Źlen
St├íly ─Źlen
Pr├şspevky: 331
Zalo┼żen├Ż: 06.11.2011
Karma: 0

Re: Zlu─Źenie 2-och 8-bit premennych do 1-ej 16-bitovej

Odosla┼ąod peterple » 13 Dec 2018, 22:17

Tak teraz ukazuje obr├ízok situ├íciu po vykonan├ş prvej ─Źasti k├│du. Tento k├│d je platformovo neutr├ílny a bude dobre fungova┼ą v┼żdy aj na little endian aj na big endian architekt├║re. Preto tento k├│d pova┼żujem za prioritn├Ż.
Teraz ─Źo je to endianita. https://sk.wikipedia.org/wiki/Endianita.
Ked┼że pam├Ą┼ą be┼żn├Żch po─Ź├şta─Źov sa sklad├í z po─ża bytov tak v├Ą─Ź┼íie ─Ź├şsla treba uklada┼ą do pamete nejako za sebou. Tak┼że ak ni┼ż┼í├ş byte ─Ź├şsla je na ni┼ż┼íej adrese je to little endian (Intel 8080, x86, 8051, AVR) Ale s├║ aj exotick├ę procesory kde sa to uklad├í presne naopak. Teda od najvy┼í┼íieho byte ktor├Ż je na najni┼ż┼íej adrese.
Konkr├ętne na obr├ízku premenn├í temp za─Ź├şna na adrese 0x100 a obsahuje dva byte ─Źo je 16 bitov

Teraz si pozri na obr├ízku ten prv├Ż v├Żpo─Źet. Ten predpoklad├í ┼że data[1] je horn├Ż byte toho intu. Preto lebo ho naprv na─Ź├ştaj├║ do premenej a ako byte (teda do doln├ęho byte) a potom ho rot├íciou 8x doprava vy┼íupn├║ do horn├ęho byte. N├ísledne k nemu logicky pripo─Ź├ştaj├║ ten druh├Ż byte ktor├Ż sa nerotuje tak┼że mus├ş by┼ą doln├Ż. Ked┼że sme na little endian architekt├║re tak vidno ┼że horn├Ż byte (data[1]) sa ulo┼żil na vy┼í┼íiu adresu premennej temp (0x101) a doln├Ż byte (data[0]) sa umiestnil na adresu 0x100
Ke─Ć sa to urob├ş a berie sa to ako jedno 16bitov├ę ─Ź├şslo little endian tak v├Żsledok je 513 (2*256+1).
No a ako to bude s posledn├Żm v├Żpo─Źtom zase v ─Ćal┼íom pr├şspevku

-- Spojen├Ż pr├şspevok 13 Dec 2018, 21:24 --

Ok ke─Ć je to jasn├ę tak fajn. Len to pre ├║plnos┼ą teda dokon─Ź├şm. Ten posledn├Ż k├│d vyr├íta dobr├ę ─Ź├şslo len na big endian architekt├║re. Tu na little endian to vyjde 258 (1*256+2).

U┼ż len dopln├şm ┼że podobn├Ż hokej m├┤┼że nasta┼ą aj vtedy ke─Ć sa spracov├ívaj├║ data z nejak├ęho komunika─Źn├ęho streamu. Napr IP adredsa v hlavi─Źke IP datagramu je vo form├íte big endian.
Pr├şlohy
byte2word02.png
byte2word03.png
Uk├í┼ż m├║dremu chybu a on sa ti po─Ćakuje. Uk├í┼ż chybu hlup├íkovi a on sa uraz├ş.
peterple
Ultimate ─Źlen
Ultimate ─Źlen
Pr├şspevky: 1847
Vek: 52.47
Zalo┼żen├Ż: 25.06.2013
Bydlisko: Krajn├ę
Karma: 52


Nasp├Ą┼ą na C,C++,C#

Kto je pr├ştomn├Ż

U┼ż├şvatelia prezeraj├║ci si toto f├│rum: ┼Żiadny registrovan├Ż pou┼ż├şvate─ż a 0 host├ş.

Forums ©
Autor str├ínky je Ondrej Z├ívodsk├Ż(zawin), o graficky design sa star├í ─Żubo┼í Fabo(BUFU).

TOPlist

Powered by Copyright © UNITED-NUKE CMS. All Rights Reserved.
─îas potrebn├Ż k spracovaniu str├ínky 0.41 sek├║nd