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
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).
:
Bearbeitet durch User
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 |
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.
1 | #define val 1000
|
2 | ldi r24, low(val) |
3 | ldi r25, high(val) |
4 | m1: |
5 | sbiw r24, 1 |
6 | brne m1 |
Trotzdem cute, gefällt mir.
:
Bearbeitet durch User
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?
:
Bearbeitet durch User
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
:
Bearbeitet durch User
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.)
Marcel Papst schrieb: > 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 Flags und Registerwerte nach Befehlsbearbeitung.
1 | r18 = 2, r19 = 1 |
2 | ;========================================== |
3 | subi r18, 1 ; r18 = 1 / ZF = 0 / CF = 0 |
4 | sbci r19, 0 ; r19 = 1 / ZF = 0 / CF = 0 => Sprung |
5 | |
6 | subi r18, 1 ; r18 = 0 / ZF = 1 / CF = 0 |
7 | sbci r19, 0 ; r19 = 1 / ZF = 0 / CF = 0 => Sprung |
8 | |
9 | subi r18, 1 ; r18 = FF / ZF = 0 / CF = 1 |
10 | sbci r19, 0 ; r19 = 0 / ZF = 0 / CF = 0 => Sprung |
11 | ;=========================================== |
Also doch weiterer Durchlauf. Und ThomasK hat dir erklart, warum das so ist.
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.