Hallo Leute, ich hoffe es kann mir jemand helfen, ist eigendlich ein relativ einfaches Problem... Vorweg ich programmiere in ASM in AVR Studio, Processor ATmega32. Ich habe zwei 16-Bit Register (r24,r25 und YL,YH). Ich ziehe beide Register von einander ab: sub r24, YL sbc r25, YH In r24, r25 ist nun mein Ergebnis. Nun soll verzweigt werden und zwar entweder wenn Ergebnis '0' oder negativ ist. Habe es mit "brmi negatives_Ergebnis" probiert, klappt auch, allerdings nur bei negativen Ergebnis und nicht beim Ergebnis '0'. Ich hoffe jemand hatte schonmal ein ähnliches Problem und kann helfen. Gruß Ralf P.S.: Im Prinzip suche ich eine Funktion "branch if zero or minus" aber die gibt es nicht... äääh, naja, zumindest hab ich sie nicht gefunden.
Wenn es keine Funktion <= gibt versuch mal eine Funktion > zu nutzen (wenn es die gibt) und was dann übrig bleibt ist <=. 2. Möglichkeit: zieh einfach noch mal "1" ab.
...Nachtrag: Es würde auch reichen, wenn ich jemand wüßte wie ich eine 16-Bit Zahl auf '0' überprüfen kann ;-) Ich meine, "tst" überprüft halt nur 8-Bit also im Prizip ein "Test with carry" wäre toll.
du könntest beide register ver-ODER-n. wenn das ergebnis 0 ist, waren auch beide ausgangsregister 0. also: 1. brmi negativ 2. or r24, r25 3. tst r24 4. breq null 5. sonstiger code gruß fabian
Intressante Idee, Größer gibt es... Aber das Problem bleibt das Gleiche, '0' ist halt weder positiv noch negativ... Es gibt halt noch ein >=, bringt mir aber auch nicht wirklich was, da er ja den "negativ-Threat" ausführen soll, wenn die Zahl '0' ist.
Wird durch die Subtraktion nicht schon das Zeroflag gesetzt? Aber das gilt vermutlich nur für die letzte Operation, also für das Highbyte. Jörgs 2. Lösung gefällt mir am besten, eins abziehen geht mit einem einzigen 16Bit-Befehl. Aus Null wird dann FFFF, das ist negativ.
Also die Idee mit dem Ver-Odern hab ich gerad mal Gedanklich durchgespielt, grundsätzlich möglich, da ich das Ergebnis der Subtraktion aber noch brauche, müßte ich das Ergebnis vorher zwischenspeichern und bei "nicht-null" wieder zurückschreiben,...geht aber umständlich... kommen wir nun zur Idee mit dem "-1"...
@Rene: der zweite Link hat nunmal gar nichts mit meinem Problem einer Branch Anweisung tun,...wie ich rudimentäre Rechenschritte in 16-Bit Registern durchführe weiß ich,...dafür brauch ich auch keine Macros. Und aus dem ersten Link werd ich nicht schlau, kannst Du bitte im Zweifelsfall SCHREIBEN was Dein Vorschlag wäre für das Problem...
So, hab das mit "-1" mal versucht, scheint auch zu klappen. Ich find´s aber immer noch irgendwie, naja,... Ästetisch nicht ansprechend ;-) sub r24, YL sbc r25, YH brmi Negatives_Ergebnis subi r24, LOW(1) sbci r25, HIGH(1) brmi Negatives_Ergebnis adiw r25:r24, 1
Nach einer 16/32/whatever Subtraktion/Vergleich aknn man ganz normal mit den Branch Befehlen arbeiten, genauso wie bei einer 8 Bit Operation. MFG Falk
Hallo, sub r24, YL sbc r25, YH breq ist_0_oder_minus brmi ist_0_oder_minus ... ist + Gruß aus Berlin Michael
@Christoph Kessler: Moment ich lese gerade Du kennst "einen" Befehl für das Abziehen von '1' von einem 16Bit Register?? Das wäre sozusagen Kollosal, oder Kollusal,...prima halt, he he Wie heißten der? (dec with carry?)
Oh nein,... Danke Michael U., genau, oh man, also manchmal sieht man den Wald vor lauter Bäumen nicht... unglaublich und so einleuchtend... Danke trotzdem an alle anderen die sich dem Problem angenommen haben... Vielleicht sollte ich auch langsam mal ins Bett, das Licht draußen ist ja schon wieder an, nerv...
timebeast wrote: > brmi Negatives_Ergebnis > subi r24, LOW(1) > sbci r25, HIGH(1) > brmi Negatives_Ergebnis Nur der Vollständigkeit halber. Das zeiht keine 1 ab, sondern $0101
Den SubW fuer die immediate-subtraktion von einer konstanten von einem Word ist im Instruction manual ersichtlich. compares as from p14-7 assumes the compare as cp, cpi, cp16, cpi16, the last two to be seen on my macro page, or Appnote 202 cpXX(Rd,Rr) BRXX as below signed compare mnemo cp - para Rd > Rr BRLT Rr,Rd (swap) Rd >= Rr BRGE Rd,Rr Rd = Rr BREQ Rd,Rr Rd <= Rr BRGE Rr,Rd (swap) Rd < Rr BRLT Rd,Rr unsigned compare mnemo cp - para Rd > Rr BRLO Rr,Rd (swap) Rd >= Rr BRCC Rd,Rr Rd = Rr BREQ Rd,Rr Rd <= Rr BRSH Rr,Rd (swap) Rd < Rr BRLO Rd,Rr eg 'skip if (U1 >= 0x10)' becomes when unsigned byte cpi U1,0x10 brcc _next eg 'skip if (U1 <= 0x10)' becomes when unsigned byte ldi U2,0x10 ; cannot be constant compare - use reg cp U2,U1 brsh _next fuer 16 bit .MACRO Cpi16 ; CP16 UL,UH,immediate U-immediate cp @0,low(@2) ldi temp,high(@2) cpc @1,temp .ENDMACRO cpi16 R16,R17,0x1234 brcc groessergleich ist nicht so schwierig.
Karl heinz Buchegger wrote: > Nur der Vollständigkeit halber. > Das zeiht keine 1 ab, sondern $0101 Sicher? HIGH(1) sollte doch eigentlich 0 sein. @alle: Die besondere Handhabung vom Z-Flag bei Carry-Befehlen, um solche Vergleiche schmerzfrei durchzuführen, ist nicht allen Prozessorfamilien eigen. Es hat recht lang gebraucht, bis die Entwickler auf diese Idee kamen.
> Wie heißten der? (dec with carry?)
adiw hast du doch schon gefunden. Wie hast du es denn geschafft, sbiw
dabei zu übersehen?
Zu deinem Code: Wozu brauchst du den ersten Vergleich? Wie wäre es
damit:
1 | sub r24, YL |
2 | sbc r25, YH |
3 | sbiw r25:r24, 1 |
4 | brmi Negatives_Ergebnis |
5 | adiw r25:r24, 1 |
Alternativ kannst du in der ersten Subtraktion gleich noch 1 mehr abziehen durch geschickte Nutzung des Carry-Flags:
1 | sec |
2 | sbc r24, YL |
3 | sbc r25, YH |
4 | brmi Negatives_Ergebnis |
5 | adiw r25:r24, 1 |
Das ist nochmal einen Taktzyklus schneller. ;-) Natürlich darfst du in beiden Fällen nicht vergessen, am Sprungziel auch das adiw einzufügen. Aber auf das umständliche Abziehen und wieder Dazuzählen würde ich hier verzichten und es so machen, wie Michael U. vorschlägt.
SBIW subtract immediate from Word (0...63 dez) http://www.atmel.com/dyn/resources/prod_documents/doc0856.pdf ( AVR-Instruction set) (wieso erlaubt das PDF kein Kopieren ?)
Rolf Magnus wrote:
> Das ist nochmal einen Taktzyklus schneller. ;-)
Ist gefährlich, weil bei dieser Sequenz das Z-Flag nicht korrekt ist.
Bei BMI kein Problem, bei manch anderen Abfragen schon.
@Karl heinz Buchegger: > Nur der Vollständigkeit halber. > Das zeiht keine 1 ab, sondern $0101 Nö, zieht nur '1' ab @Andreas Kaiser: >Sicher? HIGH(1) sollte doch eigentlich 0 sein. eben, so ist das, daher klappt das auch. @Rolf Magnus: >adiw hast du doch schon gefunden. Wie hast du es denn geschafft, sbiw >dabei zu übersehen? So im nachhinein betrachtet frag ich mich das allerdings auch ;-) irgendwie hat´s nicht "klick" gemacht,... keine Ahnung, danke aber...
und nochn Trick: die 8Bit-Immediate Addition gibts nicht, aber eine Subtraktion des negativen Werts mit SBCI ergibt dasselbe, der Assembler läßt das zu.
Hi Ich würde es ähnlich wie Fabian machen sbc r24, YL sbc r25, YH brcs ... ; Sprung wenn Minus or r24,r25 breq ... ; Sprung wenn Null MfG Spess
Spess53 wrote: > sbc r24, YL > sbc r25, YH > brcs ... ; Sprung wenn Minus > or r24,r25 > breq ... ; Sprung wenn Null Ein Fehler ist drin, Du ziehst den zufälligen Wert des Carry mit ab. Und statt "or r24,r25" kannst Du auch "nop" schreiben, es ist überflüssig. Und wenn man die Register nicht zerstören will, nimmt man cp/cpc statt sub/sbc:
1 | cp r24, yl |
2 | cpc r25, yh |
3 | brmi minus |
4 | breq null |
Peter
@ Spess53 (Gast) >Ich würde es ähnlich wie Fabian machen Ich nicht, denn das ist falsch. > sbc r24, YL Hier muss ein SUB! hin, ohne carry! > sbc r25, YH > brcs ... ; Sprung wenn Minus > or r24,r25 Das Or ist vollkommen überflüssig > breq ... ; Sprung wenn Null Also eher so
1 | sub r24, YL |
2 | sbc r25, YH |
3 | brcs ... ; Sprung wenn Minus |
4 | breq ... ; Sprung wenn Null |
MfG Falk
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.