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