¿Cuál podría ser la forma más rápida de incrementar dos bytes combinados en ensamblador (suponiendo que estoy trabajando en una CPU de 8 bits)? Actualmente estoy haciendo esto:
OVF1_handler: ; TIMER1 overflow ISR
lds r21, timerhl ; load low byte into working register; 2 cycles
add r21, counter_inc ; add 1 to working register (value of counter_inc is 1); 1 cycle
brbs 0, OVF1_handler_carry ; branch if bit 0 (carry flag bit) of SREG is set; 1 cycle if false . 2 cycles if true
sts timerhl, r21 ; otherwise write value back to variable; 2 cycles
reti ; we're done
OVF1_handler_carry: ; in case of carry bit is set
sts timerhl, r21 ; write value of low byte back to variable; 2 cycles
lds r21, timerhh ; load high byte into working register; 2 cycles
inc r21 ; increment it by 1 (no carry check needed here); 1 cycle
sts timerhh, r21 ; write value of high byte back to variable; 2 cycles
reti ; we're done
Así que en suma hay
255 * (2+1+1+2) + (2+1+2+2+2+1+2) = 1542 cycles
para contar de 0 a 256 (255 veces (2+1+1+2) porque no hay desbordamiento más 1 vez (2+1+2+2+2+1+2) cuando ocurre desbordamiento).
¿Mi cálculo es correcto y hay una forma más rápida?
Confía un poco más en tu compilador. Escribe el código en C, compilalo y mira el desmontaje. No estoy seguro de qué cadena de herramientas usa, pero avr-gcc crea un código bastante bien optimizado.
lds r24 , lowbyte ; 2 clocks
lds r25 , highbyte ; 2 clocks
adiw r24 , 0x01 ; 2 clocks - Add Immediate to Word (= 16 bit)
sts lowbyte , r24 ; 2 clocks
sts highbyte , r25 ; 2 clocks
Puede desensamblar el archivo .elf con el siguiente comando (siempre que use la cadena de herramientas gcc):
avr-objdump -C -d $(src).elf
Por cierto: probablemente necesite empujar los registros usados para apilarlos de antemano y abrirlos después (2 ciclos cada uno). Recuerde también que una interrupción (incluido reti
) dura al menos 8 ciclos de reloj aparte de las instrucciones que se ejecutan.
; TIMER1_OVF ; 4 clocks
push r24 ; 2 clocks
IN r24 , SREG ; 1 clock - save CPU flags
push r24 ; 2 clocks
push r25 ; 2 clocks
; do the addition above - 10 clocks
pop r25 ; 2 clocks
pop r24 ; 2 clocks
OUT SREG , r24 ; 1 clock
pop r24 ; 2 clocks
reti ; 4 clocks
; total 32 clock ticks
angelagrande
avr-gcc
un argumento para desmontar la salida en el proceso de compilación.yippie
armando
256 * 10 = 2560
relojes. Eso es 1000 relojes más que en mi código.yippie
armando
(2+1+1+2)
ciclos y 1 vez toma(2+1+2+2+2+1+2)
ciclos. No estoy buscando un código de aspecto corto, sino rápido: o)yippie
reti
)armando
yippie
armando
yippie
yippie
armando
adiw r24 , 0x01
que solo tomaría 2 ciclos. Eso tomaría 131072 ciclos de reloj para contar de 0 a 65535.yippie
yippie