Forum: Mikrocontroller und Digitale Elektronik Vergleichen von x und y in Assembler


von R. Brettschneider (Gast)


Lesenswert?

Hallo liebe Forenmitglieder.
Ich stehe vor der Aufgabe folgendes in Assembler zu realisieren:

Jeweils nur eine der Bedingungen sollen geprüft werden

Eine Bedingung ist:
Ist y+x>Konstante1 dann x=Konstante1-y

Die andere Bedienung ist:
Ist y-x<Konstante2 dann x=y-Konstante2

Die erste Bedingung habe ich so umgesetzt:
1
   .equ Konstante1=39230
2
   .equ Konstante2=93
3
4
   mov   r15,xl
5
   mov   r16,xh
6
   add   r15,yl
7
   adc   r16,yh
8
   
9
   mov   r17,r15  ; In r17 und r18 das Ergebnis sichern für später
10
   mov   r18,r16
11
   
12
   subi  r15,low(Konstante1)
13
   sbci  r16,high(Konstante1)
14
   brcs  ende_v1
15
   
16
   sub   xl,r15
17
   sbc   xh,r16
18
   ldi   r17,low(Konstante1)
19
   ldi   r18,high(Konstante1)
20
   
21
ende_v1:


Damit dachte ich die erste Bedingung gelöst zu haben.
Doch bei der Zweiten bin ich am verzweifeln.
Könnte mir jemand auf die Sprünge helfen?

von Falk B. (falk)


Lesenswert?

R. Brettschneider schrieb:
> Hallo liebe Forenmitglieder.
> Ich stehe vor der Aufgabe folgendes in Assembler zu realisieren:
>
> Jeweils nur eine der Bedingungen sollen geprüft werden
>
> Eine Bedingung ist:
> Ist y+x>Konstante1 dann x=Konstante1-y

Ist doch einfach. Addieren, vergleichen, springen, zuweisen.

> Die andere Bedienung ist:
> Ist y-x<Konstante2 dann x=y-Konstante2

Dito.

> Die erste Bedingung habe ich so umgesetzt:   .equ Konstante1=39230
>    .equ Konstante2=93
>
>    mov   r15,xl
>    mov   r16,xh
>    add   r15,yl
>    adc   r16,yh
>
>    mov   r17,r15  ; In r17 und r18 das Ergebnis sichern für später
>    mov   r18,r16
>
>    subi  r15,low(Konstante1)
>    sbci  r16,high(Konstante1)

Vergleichen tut man mit cp bzw. cpc. Das ist mathematisch identisch zum 
Subtrahieren, allerdings wird das Ergebnis nicht ins Register 
geschrieben, nur die Flags werden gesetzt.

>    brcs  ende_v1
>
>    sub   xl,r15
>    sbc   xh,r16
>    ldi   r17,low(Konstante1)
>    ldi   r18,high(Konstante1)

Na das überlegen wir uns noch einmal.

> ende_v1:
>
> Damit dachte ich die erste Bedingung gelöst zu haben.

Nö.

> Doch bei der Zweiten bin ich am verzweifeln.

Warum? Die ist doch nahezu identisch? Oder hast du die "Lösung" nur 
abgeschrieben?

> Könnte mir jemand auf die Sprünge helfen?

Wo liegt das Problem? Wenn du x+y rechnen kannst, kannst du doch wohl 
auch y-x rechnen, oder?

von R. Brettschneider (Gast)


Lesenswert?

Entschuldigung habe vergessen meinen Lösungsansatz für die zweite 
Bedingung mitzugeben.
1
   mov   r15,yl
2
   mov   r16,yh
3
   sub   r15,xl
4
   sbc   r16,xh
5
6
   mov   r17,r15  ; In r17 und r18 das Ergebnis sichern für später
7
   mov   r18 r16
8
   brmi  negativ
9
   
10
   subi  r15,low(Konstante2)
11
   sbci  r16,high(Konstante2)
12
   brcc  ende_v2
13
negativ:
14
   mov   r15,yl
15
   mov   r16,yh
16
   subi  r15,low(Konstante2)
17
   sbci  r16,high(Konstante2)
18
   mov   xl,r15
19
   mov   xh,r16
20
   ldi   r17,low(Konstante2)
21
   ldi   r18,high(Konstante2)
22
23
ende_v2:

von Falk B. (falk)


Lesenswert?

R. Brettschneider schrieb:
> mov   r15,yl
>    mov   r16,yh
>    sub   r15,xl
>    sbc   r16,xh
>
>    mov   r17,r15  ; In r17 und r18 das Ergebnis sichern für später
>    mov   r18 r16
>    brmi  negativ

Was soll das hier?

>    subi  r15,low(Konstante2)
>    sbci  r16,high(Konstante2)
>    brcc  ende_v2

> negativ:
>    mov   r15,yl
>    mov   r16,yh
>    subi  r15,low(Konstante2)
>    sbci  r16,high(Konstante2)
>    mov   xl,r15
>    mov   xh,r16

Das kann man gleich in xl, xh rechnen, spart 2 Befehle und Takte.

Dieser Vergleich incl. der Zuweisung stimmt.

von R. Brettschneider (Gast)


Lesenswert?

Ich dachte, geht die Rechnung schon ins negative bin ich ja schon unter 
der Konstante2
1
   mov   r15,yl
2
   mov   r16,yh
3
   sub   r15,xl
4
   sbc   r16,xh
5
6
   mov   r17,r15  ; In r17 und r18 das Ergebnis sichern für später
7
   mov   r18 r16
8
   brmi  negativ

In r17 und r18 möchte ich das Ergebnis für später aufbewahren.

von Ingo Less (Gast)


Lesenswert?

R. Brettschneider schrieb:
> Doch bei der Zweiten bin ich am verzweifeln.
Als ich mal asm programmieren musste und nicht weiter kam, habe ich es 
in C programmiert und angeschaut, was der Compiler draus macht im 
asm-listing. Das kann helfen.

von R. Brettschneider (Gast)


Lesenswert?

Ingo Less schrieb:
> Als ich mal asm programmieren musste und nicht weiter kam, habe ich es
> in C programmiert und angeschaut, was der Compiler draus macht im
> asm-listing. Das kann helfen.

Danke für die Antwort doch dazu müsste ich C können.

von Falk B. (falk)


Lesenswert?

R. Brettschneider schrieb:
> Ich dachte, geht die Rechnung schon ins negative bin ich ja schon unter
> der Konstante2

Das ist nicht gefordert. Vergiss bei solchen Sachen erstmal irgendwelche 
Optimierung und Tricks sondern schreib das ganz formal auf.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Ein paar Tipps:

- Die Bedingungen lassen sich folgendermaßen umschreiben:

  Erste Bedingung:

  t = Konstante1 - y
  Ist x > t dann x = t

  Zweite Bedingung:

  t = y - Konstante2
  Ist x > t dann x = t

- Die Befehle mit Immediate-Operanden (LDI, SUBI usw.) funktionieren nur
  für die Register R16..R31. Insbesondere

1
    subi  r15,low(Konstante2)
  geht also nicht.


- Lädt man 16-Bit-Werte so in die Register, dass das Low-Byte in einem
  geradzahligen und das High-Byte im nächsthöheren (ungeradzahligen)
  Register steht, kann man MOVW für schnelle 16-Bit-Registertransfers
  nutzen.

von R. Brettschneider (Gast)


Lesenswert?

Falk B. schrieb:
> Das ist nicht gefordert. Vergiss bei solchen Sachen erstmal irgendwelche
> Optimierung und Tricks sondern schreib das ganz formal auf.

Nun: Ist y-x<Konstante2 dann x=y-Konstante2

Y-X könnte ja bei:

.equ Konstante2=0x5D (93)

Y=0x5E (94)
X=0x9C (156)


Y-X=0xFFC2 (65474) werden. Da nachher ein Vergleich ob 0xFFC2<0x5D ist, 
nicht erfolgreich wäre dachte ich mir ich prüfe es mit dem N-Flag im 
SREG.

Möchte mit der Erklärung nur meine Denkweise aufzeigen.

von Falk B. (falk)


Lesenswert?

R. Brettschneider schrieb:

> Y-X=0xFFC2 (65474) werden. Da nachher ein Vergleich ob 0xFFC2<0x5D ist,
> nicht erfolgreich wäre dachte ich mir ich prüfe es mit dem N-Flag im
> SREG.

OK, hast recht.

> Möchte mit der Erklärung nur meine Denkweise aufzeigen.

Vollkommen OK.

von R. Brettschneider (Gast)


Lesenswert?

Yalu X. schrieb:
> - Die Befehle mit Immediate-Operanden (LDI, SUBI usw.) funktionieren nur
>   für die Register R16..R31. Insbesondere
>
>     subi  r15,low(Konstante2)
>     geht also nicht.

Richtig und danke. Ich habe hier meine .def für die Register entfernt 
und bei umschreiben in rxx fälschlicherweise bei r15 angefangen. Also 
nur ein reiner hier rein geschriebener Fehler.

Danke für den Tipp mit MOVW bin noch ganz am Anfang im Assembler.

von R. Brettschneider (Gast)


Lesenswert?

Falk B. schrieb:
> R. Brettschneider schrieb:
>
>> Y-X=0xFFC2 (65474) werden. Da nachher ein Vergleich ob 0xFFC2<0x5D ist,
>> nicht erfolgreich wäre dachte ich mir ich prüfe es mit dem N-Flag im
>> SREG.
>
> OK, hast recht.
>
>> Möchte mit der Erklärung nur meine Denkweise aufzeigen.
>
> Vollkommen OK.


Doch leider wird bei:

Y=0x80F2 (33010)
X=0xA0 (160)
1
   mov   r16,yl
2
   mov   r17,yh
3
   sub   r16,xl
4
   sbc   r17,xh
5
6
   mov   r18,r16  ; In r18 und r19 das Ergebnis sichern für später
7
   mov   r19 r17
8
   brmi  negativ

Das N-Flag im SREG auch gesetzt.

von (prx) A. K. (prx)


Lesenswert?

Bei Operationen ohne Vorzeichen ist das C-Flag massgeblich, brhs/brlo.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Müssen Unter- und Überläufe tatsächlich in der Aufgabe berücksichtigt
werden? Wenn ja, dann musst du auch den Fall x+y>65535 in der ersten
Bedingung behandeln.

Und was soll bei

  x=Konstante1-y

und

  x=y-Konstante2

geschehen, wenn y>Konstante1 bzw. y<Konstante2 ist und damit das
Ergebnis negatiov wird?

von R. Brettschneider (Gast)


Lesenswert?

Die Bedingung:
Ist y+x>Konstante1 dann x=Konstante1-y

Habe ich nun so umgesetzt:
1
   mov   r16 Dummy2,xl
2
   mov   r17 Dummy3,xh
3
   add   r16,yl
4
   adc   r17,yh
5
6
   mov   r18,r16
7
   mov   r19,r17
8
   subi  r16,low(Konstante1)
9
   sbci  r17,high(Konstante1)
10
   BRCS  ende_v1
11
   sub   xl,r16
12
   sbc   xh,r17
13
   ldi   r18,low(Konstante1)
14
   ldi   r19,high(Konstante1)
15
16
ende_v1:

X wird nun nie höher als das Y+X den Wert von Konstante1 überschreiten 
und in R18 und R19 habe ich das Ergebnis von Y+X. Y bleibt davon 
unverändert. Das war mein Ziel.

Die Bedingung:
Ist y-x<Konstante2 dann x=y-Konstante2

Habe ich nun auch zum laufen gebracht:
1
   mov   r16,yl
2
   mov   r17,yh
3
   sub   r16,xl
4
   sbc   r17,xh
5
6
   mov   r18,r16
7
   mov   r19,r17
8
   cpi   r17,0xC0
9
   brsh  Negativ
10
   
11
   subi  r16,low(Konstante2)
12
   sbci  r17,high(Konstante2)
13
   brcc  ende_v2
14
Negativ:
15
   mov   r16,yl
16
   mov   r17,yh
17
   subi  r16,low(Konstante2)
18
   sbci  r17,high(Konstante2)
19
   mov   xl,r16
20
   mov   xh,r17
21
   ldi   r18,low(Konstante2)
22
   ldi   r19,high(Konstante2)
23
24
ende_v2:

X wird nun nie kleiner als das Y-X den Wert von Konstante2 
unterschreitet und in R18 und R19 habe ich das Ergebnis von Y-X. Y 
bleibt davon unverändert. Auch das war mein Ziel.

Läuft also soweit. Doch habe ich gemerkt das ich wohl einiges falsch 
mache, bzw umständlich. Aller Anfang ist schwer.

Was könnte ich noch mal überdenken? MOVW werde ich nun mal angehen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Yalu X. schrieb:
> Müssen Unter- und Überläufe tatsächlich in der Aufgabe berücksichtigt
> werden? Wenn ja, dann musst du auch den Fall x+y>65535 in der ersten
> Bedingung behandeln.
>
> Und was soll bei
>
>   x=Konstante1-y
>
> und
>
>   x=y-Konstante2
>
> geschehen, wenn y>Konstante1 bzw. y<Konstante2 ist und damit das
> Ergebnis negatiov wird?

 Ja, das sollte man tun.

 Hier etwas zum ausprobieren (Aus dem Kopf, All Wrongs reserved)
1
;***** Register Variables
2
.def  cmp_lo = r16
3
.def  cmp_hi = r17
4
 
5
.def  x_lo = r18
6
.def  x_hi = r19
7
.def  y_lo = r20
8
.def  y_hi = r21
9
10
.def  add_lo = r24
11
.def  add_hi = r25
12
13
.equ  Konstante1 = 39230
14
.equ  Konstante2 = 93
15
16
;***** 
17
cpBdng1:
18
  ldi  cmp_lo, low(Konstante1)
19
  ldi  cmp_hi, high(Konstante1)
20
  movw  add_lo, x_lo
21
22
  add  add_lo, y_lo
23
  adc  add_hi, y_hi
24
  brcs  err_ovrflw    ;* (x+y) > 0xFFFF
25
26
  sbiw  add_lo, 1    ;* Damit nicht auf >= geprueft wird
27
  cp  add_lo, cmp_lo
28
  cpc  add_hi, cmp_hi
29
  brcs  SumLow      ;* Summe kleiner als Konstante1
30
SumGrt:  
31
  sub  cmp_lo, y_lo
32
  sbc  cmp_hi, y_hi
33
  movw  x_lo, cmp_lo
34
  ret
35
SumLow:
36
  ;* Fehler - do etwas mit x_Reg (oder auch nicht)
37
  ret
38
err_ovrflw:
39
  ;* Fehler - do etwas mit x_Reg (oder auch nicht)
40
  ret
41
42
;***** 
43
cpBdng2:
44
  cp  y_lo, x_lo
45
  cpc  y_hi, x_hi
46
  brcs  Bdng2_YLow      ;* Y kleiner als X
47
48
  ldi  cmp_lo, low(Konstante2)
49
  ldi  cmp_hi, high(Konstante2)
50
  movw  add_lo, y_lo
51
  sub  add_lo, x_lo
52
  sbc  add_hi, x_hi    ;* Y-X
53
  cp  add_lo, cmp_lo    ;* (Y-X) < Konstante2 ?
54
  cpc  add_hi, cmp_hi
55
  brcs  Bdng2_OK
56
Bdng2_Err:
57
  ;* Fehler - do etwas mit x_Reg (oder auch nicht)
58
  ret
59
Bdng2_OK:
60
  cp  y_lo, cmp_lo
61
  cpc  y_hi, cmp_hi
62
  brcs  Bdng2_ovrflw    ;* Y < Konstante2 == Error
63
  movw  add_lo, y_lo
64
  sub  add_lo, cmp_lo
65
  sbc  add_hi, cmp_hi
66
  movw  x_lo, add_lo
67
  ret
68
Bdng2_YLow:
69
  ;* Fehler - do etwas mit x_Reg (oder auch nicht)
70
  ret
71
Bdng2_ovrflw:
72
  ;* Fehler - do etwas mit x_Reg (oder auch nicht)
73
  ret

von R. Brettschneider (Gast)


Lesenswert?

Yalu X. schrieb:
> Müssen Unter- und Überläufe tatsächlich in der Aufgabe berücksichtigt
> werden? Wenn ja, dann musst du auch den Fall x+y>65535 in der ersten
> Bedingung behandeln.

Das kann in diesem Fall nicht passieren, weil Konstante1 bei 39230 oder 
kleiner liegt und Y bei Konstante2 erst anfängt, in dem Fall bei 93 oder 
größer. X wird nie mehr als 255 auf ein Schlag größer und bei jeder 
Zunahme getestet.

von R. Brettschneider (Gast)


Lesenswert?

Marc V. schrieb:
> Hier etwas zum ausprobieren (Aus dem Kopf, All Wrongs reserved)

Wow danke das werde ich mal versuchen zu verstehen.

von Peter D. (peda)


Lesenswert?

R. Brettschneider schrieb:
> Ich dachte, geht die Rechnung schon ins negative bin ich ja schon unter
> der Konstante2

Ich würde daher die Vereinfachung von Yalu nehmen:
Beitrag "Re: Vergleichen von x und y in Assembler"

Daß Konstante1 >= y >= Konstante2 gilt, dafür muß Du natürlich sorgen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter D. schrieb:
> Daß Konstante1 >= y >= Konstante2 gilt, dafür muß Du natürlich sorgen.

 Und auch dafür, daß Y > X ist.
 Und auch dafür, daß (Y + X) <= #FFFF.
 Nachdem das alles geprüft wird, bleibt einmal addieren oder
 subtrahieren, danach einmal vergleichen und ev. das Resultat
 in X-Reg. umladen auf jeden Fall.


> Ich würde daher die Vereinfachung von Yalu nehmen:
> Beitrag "Re: Vergleichen von x und y in Assembler"

 Deswegen ist die Vereinfachung (und es ist nicht gesagt, daß dies
 überhaupt eine Vereinfachung ist) nicht immer der bessere Weg.

 Vor allem in Assembler sind übersichtliches codieren und reichlich
 Komentare sehr, sehr wichtig.
 Ansonsten überlegt man was der Zweck dieser Vereinfachung ist,
 vor allem wenn man sich das Ganze nach ein paar Monaten anschaut.

von Peter D. (peda)


Lesenswert?

Marc V. schrieb:
> Vor allem in Assembler sind übersichtliches codieren und reichlich
>  Komentare sehr, sehr wichtig.

Das sehe ich auch so.
Die original Aufgabe ist für mich völlig unverständlich.
Erst die Vereinfachung macht die Funktion klar erkennbar, X soll auf 
einen Bereich begrenzt werden.
Gerade in Assembler sollte man daher zu verschwurbelte Konstrukte 
meiden.
Hier mal die einfache Variante:
1
;  t = Konstante1 - y
2
  ldi   tl, low(K1)
3
  ldi   th, high(K1)
4
  sub   tl, yl
5
  sbc   th, vh
6
;  brcs error           ; handle overflow
7
;  Ist x > t dann x = t
8
  cp    tl, xl
9
  cpc   th, xh
10
  brcc  m1
11
  movw  xl, tl
12
m1:
13
;  t = y - Konstante2
14
  movw  tl, yl
15
  subi  tl, low(K2)
16
  sbci  th, high(K2)
17
;  brcs error           ; handle overflow
18
;  Ist x > t dann x = t
19
  cp    tl, xl
20
  cpc   th, xh
21
  brcc  m2
22
  movw  xl, tl
23
m2:

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.