Forum: Mikrocontroller und Digitale Elektronik zwei 16-Bitzahlen vergleichen


von Stevko (Gast)


Lesenswert?

Hallo an alle Forumsteilnehmer,

wie der Betreff schon aussagt möchte ich zwei 16-Bit große Zahlen
vergleichen. Ziel ist zu erkennen ob die zu vergleichende Zahl größer
oder kleiner ist. Programmiersprache ist Assembler.
Mit 2x cp (High/Low) kommt man nicht um die Runden. Ich habe zwar eine
Routine geschrieben durch da sind mir zu viele Vergleiche und Sprünge.
Irgendwo gabs mal eine ganz kurze Routine, doch die finde ich nicht
mehr.
Hat jemand einen Codeschnipsel oder kann mir einen Tipp geben um die
Sache abzukürzen.

Gruß
  Stevko

von Rolf Magnus (Gast)


Lesenswert?

Ein cp ist nichts anderes als eine Subtraktion, bei der das Ergebnis
verworfen und nur die Flags gesetzt werden. Genauso, wie man
Subtraktionen unter Verwendung des Carry-Flags kaskadieren kann, kann
man auch die Vergleiche kaskadieren. Dazu gibt's bei AVR-Controllern
das cpc - compare with carry.

von Gerhard (Gast)


Lesenswert?

Hi,

z.B.

         cp ZL, r18           ;
         cpc ZH, r19          ;
         brge PC+5            ;


Gruss Gerhard

von Stevko (Gast)


Lesenswert?

Hallo Rolf,

der Tipp war gut. Da ich es nicht ausprobieren kann, bin auf der
Arbeit, hätte ich noch eine Frage. Kann ich nach dem Vegleich
erkennen/springen ob die Zahl größer oder kleiner ist?

.equ Vergleichzahl = 1234
;
;Wert laden
ldi R16,Low(2222)
ldi R17,High(2222)
;
;zuerst Low vergleichen
cp R16,Low(Vergleichzahl)
;jetzt High
cpc R17,High(Vergleichzahl)
breq Zahl_ist_gleich
 oder
brlo Zahl_ist_kleiner
 sonst
rjmp Zahl_ist_größer


Gruß
  Stevko

von Stevko (Gast)


Lesenswert?

Ups, da habe ich wohl zu lange für den Text gebraucht! Naja auf der
Arbeit sollte man wenigstens ab und zu mal was tun.
Danke auch an Gerhard, also sollte mein Beispiel funktionieren.

Gruß
  Stevko

von Rolf Magnus (Gast)


Lesenswert?

> Kann ich nach dem Vegleich erkennen/springen ob die Zahl
> größer oder kleiner ist?

Du kannst einfach mehrere branch-Befehle nacheinander ausführen, da sie
selbst die Flags nicht ändern.

> ;zuerst Low vergleichen
> cp R16,Low(Vergleichzahl)
> ;jetzt High
> cpc R17,High(Vergleichzahl)
> breq Zahl_ist_gleich
>  oder
> brlo Zahl_ist_kleiner
>  sonst
> rjmp Zahl_ist_größer

Einfach "oder" und "sonst" weglassen ;-)



Gruß
  Stevko

von Simon Küppers (Gast)


Lesenswert?

Äh, wenn du 2 16-Bit Werte hast, und die vergleichen willst, brauchst du
doch nur 2x CP. Low Byte und High Byte vergleichen und fertig. Wenn die
Zahl gleich war, müssen beide CPs TRUE gewesen sein.

von Stevko (Gast)


Lesenswert?

@Rolf:
Das mit den mehreren Branch habe ich mir nicht "getraut". Aber wenn
es geht kürzt es ganz schön ab. sehr gut!

@Simon:
Ich möcht auch erkennen ob eine Zahl größer/kleiner ist.

Gruß
  Stevko

von A.K. (Gast)


Lesenswert?

@Stevko: Was meinst Du wohl was Gerhard oben geschrieben hat?

von Stevko (Gast)


Lesenswert?

@A.K.
Was meinst Du mit Deiner Aussage? Hast Du alle! Threads gelesen?

Stevko

von Andi K. (Gast)


Lesenswert?

Ich denke mal, das hat er!
Siehe 3. Beitrag von oben:

         cp ZL, r18           ;
         cpc ZH, r19          ;
         brge PC+5            ;Verzweige wenn größer oder gleich
                              ;(Greather or Equal)

Auf die Art und Weise, wie es Gerhard vorschlug, mußt Du den zu
vergleichenden Wert vorher in die Register r18 (low) und r19 (high)
laden.
Möchte man das allerdings nicht machen weil man sowieso mit einer
festen Konstannte vergleicht, geht es auch mit cpi und cpc wobei man
für cpc keinen "Immediate"-Wert angeben kann, sondern nur Register:

;zuerst Low vergleichen
 ldi R18,High(Vergleichzahl) ;Temporär high-Byte in r18 für cpc
 CPI R16,Low(Vergleichzahl)
;jetzt High
 CPC R17,r18
 breq Zahl_ist_gleich
 brlo Zahl_ist_kleiner
 BRSH Zahl_ist_größer_oder_gleich ;(Same or Higher)

MfG
Andi

von Andi K. (Gast)


Lesenswert?

Ach ja, bei kleiner als, LOwer (LO) oder less then (LT), und bei größer
oder gleich, Same or Higher (SH) oder Greater or Equal (GE), mußt Du
aufpassen, welche Du für welchen Zweck benutzt.
LO und SH ist ohne Vorzeichen, also ohne negative Zahlen für den
Bereich von 0 bis 255 bei 8 Bit und LT und GE ist mit Vorzeichen für
einen Bereich von -128 bis 128 bei 8 Bit.

MfG
Andi

von Arno H. (Gast)


Lesenswert?

Ich habe dazu eine Verständnisfrage, mein Assemblerwissen ist noch auf
dem Level Z80 hi.
Wenn ich 2  16Bit Zahlen vergleichen sollte, würde ich zuerst das
Highbyte vergleichen, entweder mit compare oder durch Subtraktion. Bei
negativem Ergebnis (Flag ?)ist die eine Zahl kleiner, bleibt ein Rest,
ist sie größer und nur wenn das Ergebnis 0 (Flag ?) ist, muss ich das
Lowbyte überhaupt vergleichen.
Oder ist das so nicht praktikabel?
Arno

von Rolf Magnus (Gast)


Lesenswert?

Der Code ist dann halt länger und umständlicher und verbraucht mehr
Flash. Er ist bei Ungleichheit des High-Byte zwar um einen Taktzyklus
schneller, aber dafür bei Gleichheit langsamer.

von Arno H. (Gast)


Lesenswert?

Meiner Meinung nach muss ich doch eh zuerst das Highbyte vergleichen,
weil das Lowbyte erst dann zum Ergebnis beiträgt, wenn das Highbyte
gleich ist. Deswegen kann ich nicht nachvollziehen, warum ich das
Lowbyte zuerst vergleichen soll.
Die Codelänge und die Ausführungszeit hängen doch in erster Linie wohl
davon ab, wie oft die Gleichheit im Verhältnis zu einem ungleichen
Ergebnis erwartet wird, oder?

Arno

von Peter Dannegger (Gast)


Lesenswert?

Der Witz ist, CPC bzw. SBC werten das Z- und das C-Flag der vorherigen
Operation aus.

Du sparst also einige Sprungbefehle ein, wenn Du erst alle Bytes
vergleichst und hinterher springst.

Bei 32Bit- oder 64Bit-Zahlen wird das noch besser.


Peter

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.