|
|
  |
отследить изменение переменной. |
|
|
|
Dec 15 2015, 14:48
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (Jenya7 @ Dec 15 2015, 15:39)  а что можно прямо так ? (my_struct *) my_arr Да, конечно. Преобразование типа говорящее компилятору, что там по указателю на самом деле не свалка байтов, а структура. В структуре находися какая-то 32 bit переменая. Осталось только сказать компилятору что бы взял эту переменную. ((my_struct *) my_arr)->value_32bit И сделает от это МАСИМАЛЬНО эффективным способом. Для человеческой читабельности можно спрятать преобразование в макрос, или промежуточную переменную, которую компилятор все равно заоптимизирует. Получится типа: my_struct->value_32bit
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 16 2015, 08:45
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
сделал листинг ради интереса. Код if (new_packet[4] != old_packet[4] || new_packet[5] != old_packet[5] || new_packet[6] != old_packet[6] || new_packet[7] != old_packet[7])
1db8: 7938 ldrb r0, [r7, #4] 1dba: 7933 ldrb r3, [r6, #4] 1dbc: 4298 cmp r0, r3 1dbe: d10b bne.n 1dd8 <PARSER_ParseBlePacket+0x458> 1dc0: 797a ldrb r2, [r7, #5] 1dc2: 7971 ldrb r1, [r6, #5] 1dc4: 428a cmp r2, r1 1dc6: d107 bne.n 1dd8 <PARSER_ParseBlePacket+0x458> 1dc8: 79bd ldrb r5, [r7, #6] 1dca: 79b0 ldrb r0, [r6, #6] 1dcc: 4285 cmp r5, r0 1dce: d103 bne.n 1dd8 <PARSER_ParseBlePacket+0x458> 1dd0: 79fa ldrb r2, [r7, #7] 1dd2: 79f3 ldrb r3, [r6, #7] 1dd4: 429a cmp r2, r3 1dd6: d010 beq.n 1dfa <PARSER_ParseBlePacket+0x47a>
if(*((uint32_t*)&new_packet[4]) != *((uint32_t*)&old_packet[4]))
1db8: 6878 ldr r0, [r7, #4] 1dba: 6873 ldr r3, [r6, #4] 1dbc: 4298 cmp r0, r3 1dbe: d010 beq.n 1de2 <PARSER_ParseBlePacket+0x462>
if(memcmp(&new_packet[4],&old_packet[4],4) != 0)
1a48: 1d3c adds r4, r7, #4 1a4a: 4620 mov r0, r4 1a4c: 1d31 adds r1, r6, #4 1a4e: 2204 movs r2, #4 1a50: f005 f8f8 bl 6c44 <memcmp> 1a54: b160 cbz r0, 1a70 <PARSER_ParseBlePacket+0xf0> if(*((uint32_t*)&new_packet[4]) != *((uint32_t*)&old_packet[4])) рулит. в принципе это частный случай более общего - ((my_struct *) my_arr)->value_32bit кстати я тут подумал такую запись Код tempParam.maxFlowRate = (uint32_t)new_packet[0]+((uint32_t)new_packet[1]<<8)+((uint32_t)new_packet[2]<<16)+((uint32_t)new_packet[3]<<24); можно заменить на Код tempParam.maxFlowRate = *((uint32_t*)&new_packet[0]); или tempParam.maxFlowRate = ((my_struct *) my_arr)->value_32bit или я не прав? вот листинг Код tempParam.maxFlowRate = (uint32_t)new_packet[3]+((uint32_t)new_packet[2]<<8)+((uint32_t)new_packet[1]<<16)+((uint32_t)new_packet[0]<<24); 1e32: 7878 ldrb r0, [r7, #1] 1e34: 78bc ldrb r4, [r7, #2] 1e36: 0403 lsls r3, r0, #16 1e38: 78fa ldrb r2, [r7, #3] 1e3a: eb03 2104 add.w r1, r3, r4, lsl #8 1e3e: 7838 ldrb r0, [r7, #0] 1e40: 188c adds r4, r1, r2 1e42: eb04 6300 add.w r3, r4, r0, lsl #24 1e46: 9317 str r3, [sp, #92]; 0x5c
tempParam.maxFlowRate = *((uint32_t*)&new_packet[0]); 1998: 683b ldr r3, [r7, #0] 199c: 9317 str r3, [sp, #92]; 0x5c нехилая разница.
Сообщение отредактировал Jenya7 - Dec 16 2015, 09:14
|
|
|
|
|
Dec 16 2015, 11:07
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (Jenya7 @ Dec 16 2015, 10:45)  можно заменить на Не можно, а НУЖНО. Нужно давать компилятору нормальные максимально обобщенные задания а не заставлять его жонглировать байтами и битами. Грубо говоря надо стараться давать задание "выкопай яму", а не "возьми лопату, воткни в землю, бери больше, кидай дальше...повтори...". Для этого надо в первую очередь знать язык, ибо на подмножестве языка уровня Эллочки Людоедки, объяснить компилятору нормально не реально.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 16 2015, 15:25
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(zltigo @ Dec 16 2015, 15:08)  К чему эта улыбочка? Для начала попробуйте сделать этот самый "правильно заинлайненый". Для начала этого сделать просто не удастся - это библиотечная функция. Посему посморите просто на исходник memcmp() дабы, даже если ее заинлайтить, понять написанную Вами глупость. Я делаю так: 1. пишу memcmp 2. компилирую в release c соответствующими опциями оптимизации. 3. все Например, такая вот глупая функция: int Foo_cmp(const void* apSrc, size_t aNumBytes) { unsigned char buf[100] = "abcdef"; return memcmp(apSrc, buf, aNumBytes); } компилируется в следующий кусок ассемблерной хрени: CODE return memcmp(apSrc, buf, aNumBytes); 0134103E mov esi,0Fh 01341043 lea ecx,[ebp-68h] 01341046 mov edx,offset string "qweqweqweq" (13420FCh) 0134104B jmp Foo_cmp+50h (1341050h) 0134104D lea ecx,[ecx] 01341050 mov eax,dword ptr [edx] 01341052 cmp eax,dword ptr [ecx] 01341054 jne Foo_cmp+68h (1341068h) 01341056 sub esi,4 01341059 add ecx,4 0134105C add edx,4 0134105F cmp esi,4 01341062 jae Foo_cmp+50h (1341050h) 01341064 test esi,esi 01341066 je Foo_cmp+0B9h (13410B9h) 01341068 movzx eax,byte ptr [edx] 0134106B movzx edi,byte ptr [ecx] 0134106E sub eax,edi 01341070 jne Foo_cmp+0A3h (13410A3h) 01341072 cmp esi,1 01341075 jbe Foo_cmp+0B9h (13410B9h) 01341077 movzx eax,byte ptr [edx+1] 0134107B movzx edi,byte ptr [ecx+1] 0134107F sub eax,edi 01341081 jne Foo_cmp+0A3h (13410A3h) 01341083 cmp esi,2 01341086 jbe Foo_cmp+0B9h (13410B9h) 01341088 movzx eax,byte ptr [edx+2] 0134108C movzx edi,byte ptr [ecx+2] 01341090 sub eax,edi 01341092 jne Foo_cmp+0A3h (13410A3h) 01341094 cmp esi,3 01341097 jbe Foo_cmp+0B9h (13410B9h) 01341099 movzx eax,byte ptr [edx+3] 0134109D movzx ecx,byte ptr [ecx+3] 013410A1 sub eax,ecx 013410A3 sar eax,1Fh 013410A6 pop edi 013410A7 or eax,1 013410AA pop esi В debug версии да, стоит честный вызов memcmp
Сообщение отредактировал CrimsonPig - Dec 16 2015, 15:26
|
|
|
|
|
Dec 16 2015, 15:38
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (XVR @ Dec 16 2015, 17:30)  Не всегда - у gcc например это может быть intrinsic функция компилятора (если ему включить оптимизацию, конечно) Договорились. Пререходим к следующему шагу - используем GCC и его intrinsic, получаем результат и сравниваем с: CODE if(*((uint32_t*)&new_packet[4]) != *((uint32_t*)&old_packet[4])) 1db8: 6878 ldr r0, [r7, #4] 1dba: 6873 ldr r3, [r6, #4] 1dbc: 4298 cmp r0, r3
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 16 2015, 15:43
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(zltigo @ Dec 16 2015, 15:38)  Договорились. Пререходим к следующему шагу - используем GCC и его intrinsic, получаем результат и сравниваем с: memcmp - то гарантированно работает с невыравненными данными. Если есть 100% гарантия, что данные выравнены, то и заинлайненная memcmp из библиотеки будет на 3 инструкции.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|