PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : while-Schleife in AVR-Assembler



lalas
08.07.2008, 14:05
Hi,

kann mir jemand einen Tipp geben wie ich folgenden C-code in assembler umsetzen könnte:

while (a < 5 && b !=c)
{
Anweisungen
}

Ich bekomme das zwar hin mit der Abfrage einer einzelnen Bedingung, aber gleich 2 Bedingungen....

Dazu kommt das a,b,c in jeweils verschiedenen Registern liegen und keine konstanten Werte haben.


Gibt es eine Möglichkeit mehrere Vergleiche hintereinander zu machen, also quasi:

cpi r17, 5
cpi r18,r19
brlo + brne Sprungmarke1

Wäre dankbar für einen Hinweis

Gruss,
Lalas

fhs
08.07.2008, 14:14
Hallo Lalas,

in Assembler kann ich Dir das nur dann sinnvoll umsetzen, wenn Du mir die Wertebereiche (uint8_t oder int8_t?) Deiner Variablen nennst.
Aber Du schaffst es mit diesem Pseudo-Code (!) bestimmt selbst:

if (a>=5) goto leave;
while (b!=c) {
Anweisungen;
}
leave:
Mehr_anweisungen;


Unter der Bedingung "a<5 && b!=c" sitzt Du dann natürlich in einer Endlosschleife; ich nehme mal an, dass Du z.B. jedes Mal Werte aus SFRs o.ä. neu liest.

Gruß

Fred

lalas
08.07.2008, 15:29
Hi, danke für die Antwort

Also wir schreiben am Donnerstag unsere Assembler-Klausur. Es sind keine Hilfsmittel erlaubt und als Vorbereitung haben wir so nen paar Beispielaufgaben.
Hier gehts konkret um folgendes:

Umsetzung Sprung-/Schleifenkonstrukte (gegeben Pseudocode C)

a=0 (r16)
b=2 (r17)
c=10 (r18)


while (a < 5 && b != c)
{
a = a+b

if (b < 5)

b = b+1
else
b=b+2
}

Die inneren Anweisungen bekomme ich hin, nur diese while-Bedingung macht mich verrückt ;)

Aber Danke, ich tüftel mal mit deinem Tipp

Gruss,
Lalas

fhs
08.07.2008, 15:55
Hallo Lalas,

hier mal ganz schnell und schmutzig und ohne Garantie eine Variante. Man könnte sicher noch ein paar Zeilen sparen, "b" z.B. 2x inkrementieren und alles auch ganz anders machen... So sollte es aber leicht verständlich sein, da es eine praktisch direkte Umsetzung Deines Pseudo-Codes (ohne Optimierung!) darstellt:



while_entry:
cpi r16, 5 ; a - 5 ?
brpl leave_while ; "while" verlassen wenn a>=5
cp r17, r18 ; b - c
breq leave_while ; "while" verlassen wenn b==c

add r16, r17 ; a += b
cpi r17, 5 ; b - 5
brpl b_plus_2 ; verzweige wenn b >= 5
inc r17 ; else ++b
rjmp while_entry ; und noch einmal
b_plus_2:
subi r17,-2 ; b+=2
rjmp while_entry ; und noch einmal

leave_while: ; fettisch!



---Kommentare hinzugefügt!---

Gruß

Fred

PicNick
08.07.2008, 16:05
Vielleicht findest du da was, nicht vom Titel schrecken lassen
https://www.roboternetz.de/wissen/index.php/Assembler_Einf%C3%BChrung_f%C3%BCr_Bascom-User#Schleifen

lalas
08.07.2008, 18:29
Hallo fhs,

vielen Dank erstmal. Aber denke das ist nen kleiner Denkfehler (woran es auch mir wohl hapert)
Deine ersten Zeilen machen ja folgendes:


cpi r16,5 ;vergleiche r16 mit 5
brpl leave_while ;wenn r16 >5 dann verlassen
cpi r17, r18 ;vergleiche r17 mit r18
breq leave_while ;wenn r17=r18 verlassen

Soweit verständlich, ABER in die while-Bedingung lautet ja (a < 5 && b != c). Dieses UND da drin stört mich, es müssen also beide Bedingungen zutreffen um die while-Schleife zu verlassen.
Dein code prüft aber erst die erste Bedingung und würde die Schleife schon verlassen wenn diese zutrifft. Danach prüfst du ja erst die zweite Bedinung.

Also müssten ja erste Bedinung A geprüft werden ("ist a > 5?") und wenn die antwort TRUE ist, dann Bedingung B prüfen (ist c != c) und wenn das auch TRUE ist nur dann die Schleife verlassen.
Ist aber einer der beiden Bedingungen FALSE dann muss die Schleife weiterlaufen.

Oder hab ich da ein Denkfehler ??

Hallo Lalas,

hier mal ganz schnell und schmutzig und ohne Garantie eine Variante....


while_entry:
cpi r16, 5 ; a - 5 ?
brpl leave_while ; "while" verlassen wenn a>=5
cp r17, r18 ; b - c
breq leave_while ; "while" verlassen wenn b==c

add r16, r17 ; a += b
cpi r17, 5 ; b - 5
brpl b_plus_2 ; verzweige wenn b >= 5
inc r17 ; else ++b
rjmp while_entry ; und noch einmal
b_plus_2:
subi r17,-2 ; b+=2
rjmp while_entry ; und noch einmal

leave_while: ; fettisch!



---Kommentare hinzugefügt!---

Gruß

Fred

fhs
08.07.2008, 18:53
Hi,


Soweit verständlich, ABER in die while-Bedingung lautet ja (a < 5 && b != c).

Und das ist doch identisch mit
while ( (!(a>=5)) && (!(b==c))) -- und genau das überprüft mein Code!


Dieses UND da drin stört mich, es müssen also beide Bedingungen zutreffen um die while-Schleife zu verlassen.
Nein, beide Bedingungen müssen zutreffen, um in der Schleife zu bleiben! Wenn eine der Bedingungen nicht erfüllt ist (oder beide nicht erfüllt sind -- ist egal, was man zuerst testet), muss die Schleife verlassen werden; Du siehst es genau falsch herum.

Gruß

Fred

PicNick
08.07.2008, 18:55
Ich versuch's. Keine Ahnung, ob der aus der Schleife jemals rauskommt, aber das ist ja nicht die Frage



LDI r16, 0 ; a=0 (r16)
LDI r17, 2 ; b=2 (r17)
LDI r18, 10 ; c=10 (r18)
While:
cpi r16, 5
brlo _a_lower a < 5
jmp exit_while
_a_lower:
cp r17, r18
breq exit_while b = c
;-----------------------------------------------------
add r16, r17 ; a = a+b
;-----------------------------------------------------
cpi r17, 5 ; if (b < 5)
brlo _if_lower
_if_gt_eq:
ldi r0, 2
add r17, r0 b = b + 2
rjmp While ; continue
_if_lower:
ldi r0, 1
add r17, r0 b = b + 1
rjmp While ; continue
exit_while:

lalas
08.07.2008, 19:00
Alles klar, hab es falsch rum gesehen. Beides muss zutreffen um DRIN zu bleiben.
Also einfach nacheinander prüfen, sobald eines von beiden nicht mehr TRUE ist einfach rausspringen.

Spitze, danke fhs und auch Danke an PicNick für den code und den Link weiter oben, der ist echt hilfreich.

Gruss,
Lalas

Felix G
08.07.2008, 19:57
Beides muss zutreffen um DRIN zu bleiben.
Also einfach nacheinander prüfen, sobald eines von beiden nicht mehr TRUE ist einfach rausspringen.Genau, denn wenn die erste Bedingung schon False ist, kann man die zweite getrost ignorieren.

Bei Oder kann man nach dem gleichen Schema vorgehen, nur daß man da eben erst dann raus springt wenn beide Bedingungen False sind, bzw. anders formuliert: man bleibt drin solange zumindest eine von beiden True ist.