16Bit branch Vergleich

Gast #664641
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.
Gast #664645
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.
Gast #664648
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.
Gast #664655
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"...
Gast #664661
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...
Gast #664667
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
Gast #664676
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?)
Gast #664678
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...
Gast #664684
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.
#664692
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.
Gast #664693
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:
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.
Gast #664727
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...
#664765
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:
1
       cp    r24, yl
2
       cpc   r25, yh
3
       brmi  minus
4
       breq  null


Peter
#664766
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
1
      sub r24, YL
2
      sbc r25, YH
3
      brcs ...       ; Sprung wenn Minus
4
      breq ...       ; Sprung wenn Null

MfG
Falk

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren