Banale Assembler-Schleifenfrage

Gast #456757
Lesenswert?

Hallo!

Ich habe ein ziemlich banales "Problem" ich habe eine Schleife die x mal 
durchlaufen werden soll, x ist ein zwei Registern, aber maximal 512 
gross.
Wie mache ich das am Besten mit möglichst wenig Branches. Es gibt da 
eine unzahl an Branches, welche geschickte kombination aus denen aber 
eine kompakte Abzähl/Überprüf-Fuktion hat ist mir schleierhaft. Kann man 
das überhaupt elegant lösen?
Danke für eure Tipps, achja, verwende einen ATmega
Gruss
Gast #456779
Lesenswert?

>Sollte von 512 'runterzählen.
Zählt aber von 511 runter...

Das 2. ldi PZEIT1,255 müsste man sich aufgrund des begrenzten 
Zahlenraums sparen können.
(Bin aber niocht ganz so asmbewandert...)
Gast #456789
Lesenswert?

Hat wohl keiner bemerkt:

Schleife:   ldi  X_low,255
            ldi  X_high,1
WAIT:

>hier Code einfügen<

            dec  X_low
            brne WAIT
            ldi  X_low,255
            dec  X_high
            brne WAIT
ret

So muss es aussehen.
Kannst auch von 0 abwärtszählen, dann wird das 'N'-Flag gesetzt. Wenn 
das nicht stört zählt er halt von 256 'runter.
Gast #456833
Lesenswert?

Wenn ich obigen code simuliere, dann erhalte ich wie bereits vermutet 
komische ergebnisse, die schleife wird nicht mit jedem wert <512 korrekt 
oft mal durchlaufen, anscheinend geht es doch nicht so einfach...
zum Beipiel mit 256 also x_low=0 und x_high=1, dann wird die Schleife 
511 mal durchlaufen. Man muss (wie ich bereits befürchtet habe) auch auf 
null testen bevor man abzählen kann :(
Gast #456860
Lesenswert?

wenn ich 255 wie folgt initialisiere:
x_low = 255
und x_high = 1
dann gehts

wenn ich für 256 folgendes eingebe:
x_low = 0
x_high = 2
dann machts die schleife eben 511 mal

deshalb wäre es irgendwie von Vorteil, wenn es eine Möglichkeit gibt die 
auch  geht...
An so einem einfachen Ding verzweifle ich noch
Gast #456866
Lesenswert?

>wenn ich 255 wie folgt initialisiere:
x_low = 255 und x_high = 1
dann gehts

Na, ist doch auch richtig. In Assembler und C wird ab 0 gezählt, also 
0..255 sind 256 Schritte. Sobald beim Abwärtszählen von 255 die 0 
erreicht wird (und das Zero-Flag gesetzt wird) sind 256 Schritte 
durchlaufen. Bau' die Schleife so auf und es funktioniert!
Gast #456906
Lesenswert?

Danke Karl, so kam ich der Sache auf die Spur, man musste aber noch 
überprüfen ob denn von high nicht abgezogen wird obwohl schon null, 
folgendes ist entstanden:
ldi  X_low,255
ldi  X_high,0
WAIT:

//>hier Code einfügen<

            dec  X_low
            brne WAIT
      tst X_high
      breq finito
            dec  X_high
            rjmp WAIT
finito:

wer was einfachere kennt, bei dem man die Zahlen einsetzen kann und es 
läuft dann auch so viel mal, der möge sich melden....
#456912
Lesenswert?

So implementierts der Compiler

  for( Counter = i; Counter != 0; --Counter )
  72:  c0 91 60 00   lds  r28, 0x0060
  76:  d0 91 61 00   lds  r29, 0x0061
  7a:  20 97         sbiw  r28, 0x00  ; 0
  7c:  19 f0         breq  .+6        ; 0x84 <main+0x1a>
    foo();
  7e:  ee df         rcall  .-36       ; 0x5c <foo>
  80:  21 97         sbiw  r28, 0x01  ; 1
  82:  fb cf         rjmp  .-10       ; 0x7a <main+0x10>
  84:  00 c0         rjmp  .+0        ; 0x86 <_exit>
#456925
Lesenswert?

Bernhard Schulz wrote:

> diese Schleife gefällt mir, aber müsste es nicht so sein?

Nein, der AVR hat ne sogenannte "Zero-Propagation":

Ein Folge von SUBI, SBCI, ... SBCI setzt nur dann das Zero-Flag, wenn 
sämtliche Ergebnisbytes Null sind.
Gilt analog für CP, CPC, ... CPC.


Peter

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren