Das AVR Studio hat einen Simulator. Ich empfehl das mal da laufen zu
lassen. Man muss dort nicht die 1000 Loops machen, sondern kann einen
Breakpoint setzen, nachdem man ein paar Loops per single-step
durchgestept ist.
Bert Siegfried schrieb:> Hi,>> warum ist für obiges Programm die Antwort (4,500) falsch? Dies führt> doch auch zu 1000 Ausführungen, genauso wie (16,125)?>> Gruss Bert
Hallo Bert,
das Listing ist sehr wahrscheinlich ein Assembler Programm für einen
8bit AVR µC. r18 und r19 sind somit 8bit Register. Damit ist das laden
von 500 nicht möglich. So mal die Vermutung.
Der Vergleich mit brne in Zusammenhang mit dem subi r18, 2 setzt eine
gerade Zahl für Value1 vorraus.
Somit kann nur Antwort 2 (16,125) richtig sein
Gruß Thomas
Hallo, der uC sollte eigentlich wie im Labor ein Atmega128 sein.
Value1 ist in beiden Fällen jeweils eine gerade Zahl, value2 nicht, doch
value2 wird ja auch immer nur subi r19, 0x01. Muss das mal mit dem
Simulator testen.
Bert Siegfried schrieb:> value2 wird ja auch immer nur subi r19, 0x01. Muss das mal mit dem> Simulator testen.
Brauchst du nicht, Thomas hat es dir schon erklart, aber hier
nochmal:
1) 4, 500 - geht nicht, auch ein ATMega 128 hat nur 8-bit Register.
2) 16, 125 - Richtig, weil: 16/2 = 8*125 = 1000
3) 200, 5 - Falsch, weil: 200/2 = 100 * 5 = 500
4) 125, 16 - 125 ist ungerade Zahl, geht auch nicht
(und aus diesem Loop kommst du nie raus).
Peter Dannegger schrieb:> Immer diese praxisfernen Beispiele.> So würde das ein Programmierer nie schreiben, sondern so:#define val> 1000> ldi r18, low(val)> ldi r19, high(val)> m1:> subi r18, low(1)> sbci r19, high(1)> brne m1
Süß, aber beim AVR unnötig.
Peter Dannegger schrieb:> Immer diese praxisfernen Beispiele.
Harharhar...
> So würde das ein Programmierer nie schreiben, sondern so:
[...]
Jetzt wird mir klar, warum du unfähig bist, gestaffelte Zählschleifen
korrekt zu bewerten. Du machst es einfach immer so, wie es dein
geliebter Compiler machen würde...
Aber nein, in manchen Fällen ist eine gestaffelte Schleife halt die
bessere Lösung, z.B. wenn man in der inneren Schleife die eine Sache mit
der Häufigkeit X erledigen will, in der äußeren Schleife aber eine
andere Sache mit der Häufigkeit Y.
Übrigens ein sehr schönes Beispiel für die mangelnde Intelligenz von
Compilern. KEINER ist in der Lage, die Ambition zweier Quasi-Parallel
laufender Vorgänge mit unterschiedlicher Häufigkeit in einer Schleife
aus dem C-Code zu erahnen und die Optimierung als gestaffelte Schleife
zu wählen. Ich liebe es, wenn die C-Lover selber die Munition liefern,
mit denen ich sie beschiessen kann...
Peter Dannegger schrieb:> Immer diese praxisfernen Beispiele.> So würde das ein Programmierer nie schreiben, sondern so:>
1
> #define val 1000
2
> ldi r18, low(val)
3
> ldi r19, high(val)
4
> m1:
5
> subi r18, low(1)
6
> sbci r19, high(1)
7
> brne m1
8
>
Peter, ich bin sicher nicht derjenige der grad Deinen Code in Frage
stellen würde, aber bricht das nicht bei 0xFF bereits ab? Wegen
(bei val 0x100, d.h. r18=0x00, r19=0x01)
subi r18, 1 -> r18=0xff, CF=1, ZF=0
sbci r19, 0 -> r19=0x00, CF=0, ZF=1
brne -> false wegen ZF=1 -> Kein Sprung.
Ich hätte gemeint, dass ein dec r18 vor der Schleife (mit vorherigem
oder implizitem Sicherstellen von val>=1 beim Start) mit brsh als
Schleifenbedingung korrekt wäre. Also, Abbruch auf CF=1 statt ZF=1, und
das dec halt weil wir bis "-1" statt bis 0 zählen müssen.
Oder wo hab ich den Denkfehler?
Heinz L. schrieb:> subi r18, 1 -> r18=0xff, CF=1, ZF=0> sbci r19, 0 -> r19=0x00, CF=0, ZF=1> brne -> false wegen ZF=1 -> Kein Sprung.>> Ich hätte gemeint, dass ein dec r18 vor der Schleife (mit vorherigem> oder implizitem Sicherstellen von val>=1 beim Start) mit brsh als> Schleifenbedingung korrekt wäre. Also, Abbruch auf CF=1 statt ZF=1, und> das dec halt weil wir bis "-1" statt bis 0 zählen müssen.
Wird ZF bei gesetztem CF denn 1?
Datenblatt sagt:
SBCI Rd, K => "Rd ← Rd - K - C"
Heißt für mich:
r19 ← 0x00 - 0 - 1
r19 ← 0xFF
Woraus doch folgt:
CF = 1, ZF = 0
r19 ist vor der Schleife ja 1, nicht 0. 0x100 ist der Wert von val vor
dem Schleifendurchgang, mit r19=1, r18=0. r18 wird mit "subi r18, 1" um
1 erniedrigt, damit das CF gesetzt. Mit "sbci r19, 0" wird von r19 0 und
das CF (gesetzt) abgezogen, also 1 - 0 - 1 = 0, damit dann CF=0 und
ZF=1.
Heinz L. schrieb:> r19 ist vor der Schleife ja 1, nicht 0. 0x100 ist der Wert von val vor> dem Schleifendurchgang, mit r19=1, r18=0. r18 wird mit "subi r18, 1" um> 1 erniedrigt, damit das CF gesetzt. Mit "sbci r19, 0" wird von r19 0 und> das CF (gesetzt) abgezogen, also 1 - 0 - 1 = 0, damit dann CF=0 und> ZF=1.
Ok, mein Fehler.
Ich habe nicht alles bedacht, als ich meine Ausführung schrieb.
Heinz L. schrieb:> (bei val 0x100, d.h. r18=0x00, r19=0x01)>> subi r18, 1 -> r18=0xff, CF=1, ZF=0> sbci r19, 0 -> r19=0x00, CF=0, ZF=1> brne -> false wegen ZF=1 -> Kein Sprung.
Hier nochmal, aber diesmal (hoffentlich) richtig bedacht. Ich habe
r18 bzw. r19 durch den jeweils aktuellen Wert ersetzt
angefangen bei 0x102.
subi 0x02, 0x01 -> 0x01, CF=0, ZF=0
sbci 0x01, 0x00 -> 0x01, CF=0, ZF=0
brne => Sprung
subi 0x01, 0x01 -> 0x00, CF=0, ZF=1
sbci 0x01, 0x00 -> 0x01, CF=0, ZF=0
brne => Sprung
subi 0x00, 0x01 -> 0xff, CF=1, ZF=0
sbci 0x01, 0x00 -> 0x00, CF=0, ZF=1
brne => kein Sprung
also kein weiterer Durchlauf.
wo bleibt c-hater wenn man ihn mal braucht?
Marcel Papst schrieb:> subi 0x00, 0x01 -> 0xff, CF=1, ZF=0> sbci 0x01, 0x00 -> 0x00, CF=0, ZF=1> brne => kein Sprung
das ist falsch, weil laut der Beschreibung zum SBCI-Befehl:
1
[the Z-flag] remains unchanged when the result is zero; cleared otherwise
Oder auf deutsch: der SBCI-Befehl lässt das Z-Flag unverändert wenn das
Resultat null ist und löscht das Z-Flag wenn das Resultat nicht null
ist.
Dies genau aus diesem Grund: damit bei einer Subtraktion über 2 oder
mehr Bytes das Z-Flag genau dann gesetzt ist, wenn alle Teilergebnisse
null sind (und damit das Gesamtresultat null ist.)