Forum: Mikrocontroller und Digitale Elektronik 16Bit branch Vergleich


von timebeast (Gast)


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.

von Jörg B. (manos)


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.

von timebeast (Gast)


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.

von Fabian B. (fabs)


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

von timebeast (Gast)


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.

von Christoph db1uq K. (christoph_kessler)


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.

von rene (Gast)


Lesenswert?


von timebeast (Gast)


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"...

von rene (Gast)


Lesenswert?


von timebeast (Gast)


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...

von timebeast (Gast)


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

von Falk B. (falk)


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

von Falk B. (falk)


Lesenswert?


von Michael U. (Gast)


Lesenswert?

Hallo,

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

Gruß aus Berlin
Michael

von timebeast (Gast)


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?)

von timebeast (Gast)


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...

von Karl H. (kbuchegg)


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

von rene (Gast)


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.

von Andreas K. (a-k)


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.

von Rolf Magnus (Gast)


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.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

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 ?)

von Andreas K. (a-k)


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.

von timebeast (Gast)


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...

von Christoph db1uq K. (christoph_kessler)


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.

von Spess53 (Gast)


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

von Peter D. (peda)


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

von Falk B. (falk)


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

von Falk B. (falk)


Lesenswert?

Uuuups, zu langsam ;-)

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
Noch kein Account? Hier anmelden.