AVR asm Warteschleife erklären

Kann mir bitte jemand diesen Code erklären (er stammt vom Warteschleifenrechner), ich kann die Berechnung nicht klar verstehen.

; Verzögerung 1 600 000 Zyklen; 100 ms bei 16 MHz

ldi  r18, 9       ;1 clock cycle
ldi  r19, 30      ;1 clock cycle
ldi  r20, 229     ;1 clock cycle
L1: dec  r20      ;1 clock cycle
brne L1           ;2 clock cycle
dec  r19          ;1 clock cycle
brne L1           ;2 clock cycle
dec  r18          ;1 clock cycle
brne L1           ;2 clock cycle
nop               ;1 clock cycle
Hast du versucht zu zählen?
Wie viele Zyklen würde es für R18 = 1 R19 = 1 R20 = 1 dauern, Wie viele mit R20 = 2? R19=2 ? usw...

Antworten (1)

Der Code lädt 9, 30 und 229 in die Register r18, r19 bzw. r20. Dann dekrementiert er diese Register in einer dreifach verschachtelten Schleife. Die äußerste Schleife läuft 9 Mal. dec, ldi und nop dauern immer 1 Zyklus. brne benötigt 1 Zyklus plus einen zusätzlichen Zyklus, wenn es sich verzweigt. Bei der ersten Iteration der äußeren Schleife wird die mittlere Schleife 30 Mal ausgeführt. Bei der ersten Iteration der mittleren Schleife wird die innere Schleife 229 Mal ausgeführt. Die dec-Befehle dekrementieren die Register und dann vergleichen die brne-Befehle das Ergebnis mit Null - jede Schleife läuft, bis das zugehörige Register Null ist, an welchem ​​Punkt die Ausführung zum nächsten Befehl "durchfällt". Wenn das Register beim Eintritt in die Schleife Null ist, bewirkt dec, dass es auf 255 umläuft. Wenn also eine Schleife zum ersten Mal ausgeführt wird, läuft sie, bis der Zähler Null ist.

Die Befehle ldi und nop benötigen insgesamt 4 Zyklen. Die innere Schleife erfordert 3 Zyklen für jede Iteration, mit Ausnahme der letzten, die 2 erfordert, so dass das erste Mal ungefähr 229 * 3-1 Zyklen sind und nachfolgende Iterationen 256 * 3-1 Zyklen sind. Die anderen Schleifen folgen der gleichen Sequenz und fügen 3 Zyklen für jede Iteration außer der letzten hinzu. Wenn Sie alle Schleifen berücksichtigen, erhalten Sie:

3+229*3-1+3+(256*3-1+3)*29-1+3+((256*3-1+3)*256-1+3)*8-1+1 = 1600000

3 für die ldi-Anweisungen, 229*3-1 für die erste innere Schleife, 3 für die erste Iteration der mittleren Schleife, (256*3-1+3)*29-1 für den Rest der ersten mittleren Schleife, 3 für die erste äußere Schleife, ((256*3-1+3)*256-1+3)*8-1 für den Rest der äußeren Schleife und 1 für die letzte Nop.

Diese Gleichung kann umgeschrieben werden als:

6+229*3+770*(30-1)+197122*(9-1)+1

wobei 229, 30, 9 und 1 den 3 Konstanten und der Anzahl der nachgestellten nop-Anweisungen entsprechen. Sie können die drei Schleifenzählerkonstanten berechnen, indem Sie rückwärts vom größten zum kleinsten arbeiten und dann 0, 1 oder 2 nop-Anweisungen hinzufügen, um die genaue Anzahl der Zyklen zu erhalten.

Zum Beispiel würde die Neuberechnung für eine Verzögerung von 50 ms (800000 Zyklen) wie folgt funktionieren: 800000/197122 = 4, Rest 11512. 11512/770 = 14, Rest 732. 732/3 = 244, Rest 0. Sie würden also die verwenden Konstanten 4 + 1 = 5, 14 + 1 = 15, 244 – 6/3 = 244 – 2 = 242 und fügen Sie keine zusätzlichen nop-Anweisungen hinzu. Prüfen, berechnen

6+242*3+770*(15-1)+197122*(5-1)+0 = 800000

.