Was könnte der schnellste Weg sein, um zwei kombinierte Bytes in Assembler zu erhöhen (vorausgesetzt, ich arbeite an einer 8-Bit-CPU)? Aktuell mache ich das:
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
Also in Summe gibt es
255 * (2+1+1+2) + (2+1+2+2+2+1+2) = 1542 cycles
von 0 bis 256 zu zählen (255 Mal (2+1+1+2), weil kein Überlauf plus 1 Mal (2+1+2+2+2+1+2), wenn ein Überlauf auftritt).
Ist meine Berechnung korrekt und gibt es einen schnelleren Weg?
Haben Sie etwas mehr Vertrauen in Ihren Compiler. Schreiben Sie den Code in C, kompilieren Sie ihn und schauen Sie sich die Disassemblierung an. Sie sind sich nicht sicher, welche Toolchain Sie verwenden, aber avr-gcc erstellt ziemlich gut optimierten Code.
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
Sie können die .elf-Datei mit dem folgenden Befehl disassemblieren (vorausgesetzt, Sie verwenden die gcc-Toolchain):
avr-objdump -C -d $(src).elf
Übrigens: Sie müssen wahrscheinlich die verwendeten Register vorher stapeln und danach platzen lassen (jeweils 2 Zyklen). Denken Sie auch daran, dass ein Interrupt (einschließlich reti
) mindestens 8 Taktzyklen dauert, abgesehen von den ausgeführten Anweisungen.
; 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
Engelgroß
avr-gcc
ein Argument angeben, um die Disassemblierung im Kompilierungsprozess auszugeben.Jippie
arminb
256 * 10 = 2560
Takte dauern. Das sind 1000 Takte mehr als in meinem Code.Jippie
arminb
(2+1+1+2)
Zyklen und 1 Mal dauert es(2+1+2+2+2+1+2)
Zyklen. Ich suche keinen kurz aussehenden Code, sondern den schnellsten :o)Jippie
reti
)arminb
Jippie
arminb
Jippie
Jippie
arminb
adiw r24 , 0x01
was nur 2 Zyklen dauern würde. Das würde 131072 Taktzyklen dauern, um von 0 bis 65535 zu zählen.Jippie
Jippie