Intenté compilar el siguiente código C:
period = TCNT0L;
period |= ((unsigned int)TCNT0H<<8);
El código del ensamblador que estoy obteniendo es el siguiente:
period = TCNT0L;
d2: 22 b7 in r18, 0x32 ; 50
d4: 30 e0 ldi r19, 0x00 ; 0
d6: 30 93 87 00 sts 0x0087, r19
da: 20 93 86 00 sts 0x0086, r18
period |= ((unsigned int)TCNT0H<<8);
de: 44 b3 in r20, 0x14 ; 20
e0: 94 2f mov r25, r20
e2: 80 e0 ldi r24, 0x00 ; 0
e4: 82 2b or r24, r18
e6: 93 2b or r25, r19
e8: 90 93 87 00 sts 0x0087, r25
ec: 80 93 86 00 sts 0x0086, r24
¡Así que en lugar de 4 instrucciones, obtiene 11!
Intenté elegir las opciones de optimización O1, O2, O3 y Os. El resultado es el mismo (excepto que la opción O3
optimizó para nada este código).
Podría escribir el código fuente de la siguiente manera:
period = TCNT0L | ((unsigned int)TCNT0H<<8);
Obtendré un código más pequeño, pero aún no óptimo:
de: 22 b7 in r18, 0x32 ; 50
e0: 34 b3 in r19, 0x14 ; 20
e2: 93 2f mov r25, r19
e4: 80 e0 ldi r24, 0x00 ; 0
e6: 82 2b or r24, r18
e8: 90 93 87 00 sts 0x0087, r25
ec: 80 93 86 00 sts 0x0086, r24
Sin embargo, no tendré una garantía de que primero se accederá al byte más bajo (este es un requisito esencial para mantener la lectura correcta de 16 bits). Y aún así, el código tiene muchas instrucciones adicionales innecesarias.
¿Puedo cambiar las opciones del compilador y / o cambiar el código fuente para mejorarlo? Evitaría ir al ensamblador.
UPDATE1:
Probé el código que sugirió @caveman:
((unsigned char*)(&period))[0] = TCNT0L;
((unsigned char*)(&period))[1] = TCNT0H;
Pero el resultado tampoco es muy bueno:
((unsigned char*)(&period))[0] = TCNT0L;
dc: 82 b7 in r24, 0x32 ; 50
de: e6 e8 ldi r30, 0x86 ; 134
e0: f0 e0 ldi r31, 0x00 ; 0
e2: 80 83 st Z, r24
((unsigned char*)(&period))[1] = TCNT0H;
e4: 84 b3 in r24, 0x14 ; 20
e6: 81 83 std Z+1, r24 ; 0x01