mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 16Bit branch Vergleich


Autor: timebeast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Jörg B. (manos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: timebeast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...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.

Autor: Fabian B. (fabs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: timebeast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: rene (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: timebeast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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"...

Autor: rene (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: timebeast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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...

Autor: timebeast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Michael U. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

    sub r24, YL
    sbc r25, YH
    breq ist_0_oder_minus
    brmi ist_0_oder_minus
    ...  ist +

Gruß aus Berlin
Michael

Autor: timebeast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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?)

Autor: timebeast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: rene (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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:
      sub r24, YL
      sbc r25, YH
      sbiw r25:r24, 1
      brmi Negatives_Ergebnis
      adiw r25:r24, 1

Alternativ kannst du in der ersten Subtraktion gleich noch 1 mehr 
abziehen durch geschickte Nutzung des Carry-Flags:
      sec
      sbc r24, YL
      sbc r25, YH
      brmi Negatives_Ergebnis
      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.

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SBIW subtract immediate from Word (0...63 dez)
http://www.atmel.com/dyn/resources/prod_documents/...
( AVR-Instruction set)
(wieso erlaubt das PDF kein Kopieren ?)

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: timebeast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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...

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
       cp    r24, yl
       cpc   r25, yh
       brmi  minus
       breq  null


Peter

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ 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
      sub r24, YL
      sbc r25, YH
      brcs ...       ; Sprung wenn Minus
      breq ...       ; Sprung wenn Null

MfG
Falk

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Uuuups, zu langsam ;-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.