Routinensammlung und Gewusst-wie für Mikrocontroller

Schleifen auf 8051

Abweisende vs. nichtabweisende Schleifen

Ich hoffe mal, dass Sie nichtabweisende Schleifen so kodieren:
Nein!Ordentlich
	mov	r3,#Anzahl
loop1:	;<Schleifenkörper>
	dec	r3
	mov	a,r3
	jnz	loop1
	;<weiterer Kode>
	mov	r3,#Anzahl
loop1:	;<Schleifenkörper>
	djnz	r3,loop1
	;<weiterer Kode>
 BYTE i;
 for (i=Anzahl; i; i--) {
  /* Schleifenkörper */
 }
Das ist eine abweisende Schleife - verdammt nochmal!
 BYTE i;
 i=Anzahl; do{
  /* Schleifenkörper */
 }while (--i);

So können abweisende Schleifen implementiert werden:

Dummbrotbesserperfekt
	mov	r3,#Anzahl
loop1:	mov	a,r3
	jz	loop_e1
	;<Schleifenkörper>
	dec	r3
	jmp	loop1
loop_e1:;<weiterer Kode>
	mov	r3,#Anzahl
	mov	a,r3
	jz	loop_e1
loop1:	;<Schleifenkörper>
	djnz	r3,loop1
loop_e1:;<weiterer Kode>
	mov	r3,#Anzahl+1
	sjmp	foot1
loop1:	;<Schleifenkörper>
foot1:	djnz	r3,loop1
	;<weiterer Kode>
Zwei Sprünge pro Runde.
C-Compiler übersetzen so for-Schleifen (wenn sie gut sind!)
Ein Sprung, weniger geht nicht. Außerdem ist so der hübsche DJNZ-Befehl nutzbar.
Dem C-Compiler greift man mittels if-do-while unter die Arme.
 BYTE i;
 for (i=Anzahl; i; i--) {
  /* Schleifenkörper */
 }
 BYTE i;
 if (i=Anzahl) do{
  /* Schleifenkörper */
 }while (--i);
 BYTE i;
 i=Anzahl+1; goto e; do{
  /* Schleifenkörper */
e:;
 }while (--i);

Niemals ohne Grund int i schreiben!

Wenn das doch nötig ist, dann siehe unten.

16-bit-Schleifen auf 8051

Abweisend - alles schon gesehen:
Dummbrotbesserperfekt
	mov	r2,#Anzahl-High
	mov	r3,#Anzahl-Low
loop1:	mov	a,r2
	orl	a,r3
	jz	loop_e1
	;<Schleifenkörper>
	clr	c
	mov	a,r3
	subb	a,#1
	mov	r3,a
	mov	a,r2
	subb	a,#0
	mov	r2,a
	jmp	loop1
loop_e1:;<weiterer Kode>
	mov	r2,#Anzahl-High
	mov	r3,#Anzahl-Low
	sjmp	foot1
loop1:	;<Schleifenkörper>
	mov	a,r3
	jnz	fo1
	dec	r2
fo1:	dec	r3
foot1:	mov	a,r2
	orl	a,r3
	jnz	loop1
loop_e1:;<weiterer Kode>
	mov	a,#Anzahl-Low
	mov	r3,a
	addc	a,#0FFh
	mov	a,#Anzahl-High
	addc	a,#0
	mov	r2,a
	jz	loop_e1
loop1:	;<Schleifenkörper>
	djnz	r3,loop1
	djnz	r2,loop1
loop_e1:;<weiterer Kode>
Zwei Sprünge pro Runde. Und richtige 16-bit-Arithmetik.
C-Compiler übersetzen so for-Schleifen (leider, wenn sie gut sind! Schlechte benutzen Speicherplätze statt Register.)
Schon mal eine verkürzte Arithmetik. Etwas mehr Vorbereitung macht den Schleifenkörper minimal.
Regel: Inkrementiere High-Teil, wenn Low-Teil ungleich Null.
 int i;
 for (i=Anzahl; i; i--) {
  /* Schleifenkörper */
 }
 int i;
 if (i=Anzahl) do{
  /* Schleifenkörper */
 }while (--i);
 BYTE lo,hi;
 lo=(BYTE)Anzahl;
 hi=(BYTE)(Anzahl>>8);
 if (lo) hi++;
 if (hi) do{
  do{
  /* Schleifenkörper */
  }while (--lo);
 }while (--hi);
Hat jemand behauptet, dass (optimierter) C-Quelltext besser zu lesen ist Assembler?

Es versteht sich nun von selbst, dass aufsteigende Indizes zu noch komplizierten Schleifen-Konstrukten führen: vermeiden!