ich brauche einen zähler, den ich inkrementieren kann. (..in assembler) er muß aber mehr als 255 werte speichern können. wie macht man das? macht man das, indem man mehrere byte-stellen zusammenfaßt? wie sage ich dem, daß er im 2. byte die stelle um eins erhöhen soll, wenn das 1. byte bei 255 übergelaufen ist? macht man das mit dem Z- oder C-bit? welches davon ist das richtige? und muß ich es nach dem auslesen zurücksetzen, oder wird dieses manuell zurück gesetzt? dann müßte ich noch eine if-anweisung realisieren, und zwar eine, bei der mehrere bedingungen erfüllt sein müssen. wie mache ich dann in assembler eine if-bedingung, die nur zu einer stelle springt, wenn mehrere bedingungen erfüllt sind?
Inkrement r2:r1 add r1, 1 adc r2, 0 ; Nur Carry wird addiert if (1. Bed. nicht erfüllt) goto weg if (2. Bed. nicht erfüllt) goto weg if (3. Bed. nicht erfüllt) goto weg ... Alle Bedingungen erfüllt; mach was
Zähler mit beliebiger Bitbreite realisiert man durch Zusammenfassung mehrerer Bytes. Bis 16 Bit kann man die X,Y,Z-Register verwenden. Überträge können mittels Carry- oder Zero-Flag berücksichtigt werden, das kommt auf die Art der Zählerprogrammierung bzw. die Vorlieben des Programmierers an. Beide Varianten funktionieren. Welche Befehle die Flags verändern oder unangetastet lassen, kannst Du der sehr übersichtlichen Instruction Set Summary im Datenblatt entnehmen. Verzweigungen mit mehreren Bedingungen realisiert man durch entsprechende Aneinanderreihung. Einfaches Beispiel: adc r16,r17 brcc Beding_ne cpi r18,36 brne Beding_ne ... ; Bedingung erfüllt rjmp Weiter Beding_ne: ; Bedingungen nicht erfüllt ... Weiter: Gruß, Frank
" add r1, 1 " adc r2, 0 ; Nur Carry wird addiert Beim AVR geht das nicht, weil 'er' diese Befehle nicht kennt ! Eine effektive Lösung vermeidet Verzweigungen und nutzt den SUBx-Befehl; ein 32-Bit Zähler kann dann so inkrementiert werden: SUBI R16,0xff SBCI R17,0xff SBCI R18,0xff SBCI R19,0xff Hierbei wird der Zähler um -1 vermindert, was ein Inkrement bewirkt. Dies geht mit Registern R16-R31. Möchte man die unteren Register nutzen, kann man das so machen: CLR R15 // R15 = 0x00 DEC R15 // R15 = 0xff SUB Rn,R15 SBC Rn+1,R15 SBC Rn+2,R15 SBC Rn+3,R15 Zweckmäßigerweise kann man auch R15 einmalig auf 0xff setzen und danach als 'Konstante' verwenden.
hm.. laß mal überlegen: d.h., ich lasse einfach beispielsweise eine 16-bit addition durchführen. und zwar lasse ich immer zu dem 16-bit wert + eins addieren. wie man die addition mit 16-bit werten macht, hab eich glaubeich wo gefunden. d.h., das überlaufbit addiert man dann irgendwie mit adc oder so. jetzt aber frage: wenn irgendein ereignis das überlauf-bit setzt, und ich adc ausführe, welches mir auch schön das überlaufbit dazuaddiert, müßte es dann nicht beim nächsten aufrufe von adc, wenn gerade kein überlaufbit gesetzt wurde, weil kein überlauf stattgefunden hat, das überlaufbit noch vom letzten male gesetzt sein, obwohl es gar nicht gesetzt sein darf? wer sorgt denn dafür, daß bei einer verarbeitung des überlaufbits danach das überlaufbit vor der nächsten rechnung wieder auf 0 steht, wenn bei der nächsten rechnung kein überlauf stattgefunden hat?
update: Hm.. ich habe unter flags "instruction set summary" jetzt nachgeguckt. da steht ja eine spalte flags, wo so Z, C, N, V, H und sowas drinsteht. sind das die flags, die der befehl 100%tig bei jedem aufrufen (neu)setzen tut?
Hallo die flags im sreg brauchst du nicht löschen. wenn z.b. bei einem befehl ein überlauf stattfindet wird das überlaufflag gesetzt. beim darrauffolgenden befehl findet kein überlauf statt also wird das bit gelöscht. gruß nico
Hallo Das gleiche Prob hatte ich grade auch. Mit dem Befehl adiw r24,1 oder SBIW r24,1 erhöht oder erniedrigt man das Registerpaar R24/25 um die Konstante 1 d.h. man hat einen 16Bit Zähler realisiert.
> SUBI R16,0xff > SBCI R17,0xff > SBCI R18,0xff > SBCI R19,0xff Zwei Dinge: Erstens würde ich nicht 0xff, sondern -1 schreiben. zweitens: addiert dieses nicht eher 0x1010101 zum Wert dazu? Mmn müßte es heißen: SUBI R16, -1 SBCI R17, 0 SBCI R18, 0 SBCI R19, 0 @Steffen Finger: > Mit dem Befehl adiw r24,1 oder SBIW r24,1 erhöht oder erniedrigt > man das Registerpaar R24/25 um die Konstante 1 d.h. man hat einen > 16Bit Zähler realisiert. Das wollte ich auch gerade vorschlagen, da es die naheliegendste Variante ist und noch nicht vorgeschlagen wurde. Wenn man ein Register als Nullregister definiert hat (also eins, in dem man immer den Wert 0 stehen hat), so wie der Compiler das auch macht, kann man das dann problemlos mit einem ADC r26, ZEROREG bzw. SBC r26, ZEROREG u.s.w. auf größere Bitanzahl erweitern.
Wie wäre es denn mit: inc r12 ;unteres Byte brne keinuebertrag ;nicht 0 inc r13 brne keinuebertrag inc r14 brne keinuebertrag inc r15 ;oberes Byte keinuebertrag: ...
@Rolf Magnus Nein, du musst das komplette -1 subtrahieren, und das ist als 32 bit komplement nun einmal $FFFFFFFF. Wie war das nochmal mit lowlow(-1), lowhigh(-1) etc.?
> Nein, du musst das komplette -1 subtrahieren, und das ist als 32 > bit komplement nun einmal $FFFFFFFF. Hmm, wenn man es so betrachtet... hast du recht. Ich hatte ja schon geahnt, irgendwas übersehen zu haben, hab mich doch dazu hinreißen lassen, die Subtraktion von -1 als Addition von 1 zu sehen.
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.