Re: C: Arduino : Přesun pole bytů do proměnné unsigned long

Jan Waclawek konfera na efton.sk
Středa Listopad 8 19:34:39 CET 2023


>Jak to tedy
>dělají profesionálové? 

Profesional znamena, ze dostane za robotu zaplatene, a nie to, ze to je
dobre (nech "dobre" znamena cokolvek)... :-)


Ak to nejakeho profesionala zaujima, ze ako to dopadlo, pozrie sa do
listingu asembleru, alebo do disasemblovaneho vysledku. Pripadne, ak by
prekladac robil velmi napriek a ak by to profesionala velmi trapilo, tak
to napise v asembleri.


Pricom odvolavam co som odvolal. Skusil som niekolko sposobov na niekolkych
verziach gcc, a "optimalne" fungoval naozaj len ten cez type punning cez
pretypovanie smernika...

  b1 = *(uint32_t*)&rx[3];
  c = b1;

  27 0018 8091 0000 		lds r24,rx+3
  28 001c 9091 0000 		lds r25,rx+3+1
  29 0020 A091 0000 		lds r26,rx+3+2
  30 0024 B091 0000 		lds r27,rx+3+3
  31 0028 8093 0000 		sts b1,r24
  32 002c 9093 0000 		sts b1+1,r25
  33 0030 A093 0000 		sts b1+2,r26
  34 0034 B093 0000 		sts b1+3,r27
  35 0038 8093 0000 		sts c,r24
  36 003c 9093 0000 		sts c+1,r25
  37 0040 A093 0000 		sts c+2,r26
  38 0044 B093 0000 		sts c+3,r27

  bb.b[0] = rx[3]; bb.b[1] = rx[4]; bb.b[2] = rx[5]; bb.b[3] = rx[6];
  c = bb.w32;

  39 0048 4091 0000 		lds r20,rx+3
  40 004c 4093 0000 		sts bb,r20
  41 0050 2091 0000 		lds r18,rx+4
  42 0054 2093 0000 		sts bb+1,r18
  43 0058 3091 0000 		lds r19,rx+5
  44 005c 3093 0000 		sts bb+2,r19
  45 0060 8091 0000 		lds r24,rx+6
  46 0064 8093 0000 		sts bb+3,r24
  47 0068 C090 0000 		lds r12,bb
  48 006c D090 0000 		lds r13,bb+1
  49 0070 E090 0000 		lds r14,bb+2
  50 0074 F090 0000 		lds r15,bb+3
  51 0078 C092 0000 		sts c,r12
  52 007c D092 0000 		sts c+1,r13
  53 0080 E092 0000 		sts c+2,r14
  54 0084 F092 0000 		sts c+3,r15

  b3 = rx[3] + 256 * rx[4] + 65536UL * rx[5] + 16777216UL * rx[6];
  c = b3;
  63 00a8 90E0      		ldi r25,0
  64 00aa B0E0      		ldi r27,0
  65 00ac A0E0      		ldi r26,0
  66 00ae BA2F      		mov r27,r26
  67 00b0 A92F      		mov r26,r25
  68 00b2 982F      		mov r25,r24
  69 00b4 8827      		clr r24
  70 00b6 830F      		add r24,r19
  71 00b8 911D      		adc r25,__zero_reg__
  72 00ba A11D      		adc r26,__zero_reg__
  73 00bc B11D      		adc r27,__zero_reg__
  74 00be DC01      		movw r26,r24
  75 00c0 9927      		clr r25
  76 00c2 8827      		clr r24
  77 00c4 30E0      		ldi r19,0
  78 00c6 322F      		mov r19,r18
  79 00c8 2227      		clr r18
  80 00ca 420F      		add r20,r18
  81 00cc 532F      		mov r21,r19
  82 00ce 511D      		adc r21,__zero_reg__
  83 00d0 052E      		mov __tmp_reg__,r21
  84 00d2 000C      		lsl r0
  85 00d4 660B      		sbc r22,r22
  86 00d6 770B      		sbc r23,r23
  87 00d8 840F      		add r24,r20
  88 00da 951F      		adc r25,r21
  89 00dc A61F      		adc r26,r22
  90 00de B71F      		adc r27,r23
  91 00e0 8093 0000 		sts b3,r24
  92 00e4 9093 0000 		sts b3+1,r25
  93 00e8 A093 0000 		sts b3+2,r26
  94 00ec B093 0000 		sts b3+3,r27
  95 00f0 8093 0000 		sts c,r24
  96 00f4 9093 0000 		sts c+1,r25
  97 00f8 A093 0000 		sts c+2,r26
  98 00fc B093 0000 		sts c+3,r27
... a to v tomto poslednom kusku sa vyuziva fakt, ze v r20/r18/r19/r24 to
cislo uz je z predchadzajuceho "vypoctu", takze prekladac este usetril
styri lds rNN, rx+N...

wek



----- Original Message ---------------
>Díky za podrobné vysvětlení. Přece ale přenos dat po bytech a jejich
>následné složení do 32bitove proměnné není zase taková exotika Jak to tedy
>dělají profesionálové? Mám to opravdu pro jistotu násobit postupně 256 a
>sčítat?



#include <stdint.h>

uint8_t rx[10];
volatile uint8_t a;    // zdroj bytovych dat
uint32_t b1, b2, b3;            // medzivysledok, do ktoreho ukladame
volatile uint32_t c;   // koncovy ciel, je volatile aby optimalizator
nevyoptimalizoval cely vypocet
uint8_t i;

union __attribute__((packed)) {
  uint8_t  b[4];
  uint32_t w32;
} bb;

int main(void) {
  for (i = 0; i < 10; i++) rx[i] = a;  // "prijmeme" data
  
  b1 = *(uint32_t*)&rx[3];
  c = b1;

#if(0)
  b2 = rx[3] + (rx[4] << 8) + ((uint32_t)rx[5] << 16) + ((uint32_t)rx[6] <<
24);
#elif(1)
  bb.b[0] = rx[3]; bb.b[1] = rx[4]; bb.b[2] = rx[5]; bb.b[3] = rx[6];
  c = bb.w32;
#else
  b2 = rx[3] | (rx[4] << 8) | ((uint32_t)rx[5] << 16) | ((uint32_t)rx[6] <<
24);
#endif
  c = b2;

  b3 = rx[3] + 256 * rx[4] + 65536UL * rx[5] + 16777216UL * rx[6];
  c = b3;

  while(1);
}



Další informace o konferenci Hw-list