Какой может быть самый быстрый способ увеличить два комбинированных байта на ассемблере (при условии, что я работаю на 8-битном процессоре)? В настоящее время я делаю это:
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
Итак, в сумме есть
255 * (2+1+1+2) + (2+1+2+2+2+1+2) = 1542 cycles
для подсчета от 0 до 256 (255 раз (2+1+1+2), потому что нет переполнения, плюс 1 раз (2+1+2+2+2+1+2), когда происходит переполнение).
Верен ли мой расчет и есть ли более быстрый способ?
Побольше доверяйте своему компилятору. Напишите код на C, скомпилируйте его и посмотрите на дизассемблирование. Не уверен, какой набор инструментов вы используете, но avr-gcc создает довольно хорошо оптимизированный код.
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
Вы можете дизассемблировать файл .elf с помощью следующей команды (при условии, что вы используете набор инструментов gcc):
avr-objdump -C -d $(src).elf
Кстати: вам, вероятно, нужно заранее поместить используемые регистры в стек, а затем вытолкнуть их (по 2 цикла каждый). Также помните, что прерывание (включая reti
) длится не менее 8 тактовых циклов, кроме выполняемых инструкций.
; 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
ангелбольшой
avr-gcc
аргумент для вывода дизассемблирования в процессе компиляции.Джиппи
рука
256 * 10 = 2560
часы. Это на 1000 часов больше, чем в моем коде.Джиппи
рука
(2+1+1+2)
циклов и 1 раз требуется(2+1+2+2+2+1+2)
циклов. Я ищу не короткий код, а быстрый: o)Джиппи
reti
)рука
Джиппи
рука
Джиппи
Джиппи
рука
adiw r24 , 0x01
лишь 2 цикла. Для счета от 0 до 65535 потребуется 131072 тактовых цикла.Джиппи
Джиппи