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
Kleines Beispiel für 'ne Pause:
PAUSE: ldi PZEIT1,255
ldi PZEIT2,1
P_WAIT: dec PZEIT1
brne P_WAIT
ldi PZEIT1,255
dec PZEIT2
brne P_WAIT
ret
Sollte von 512 'runterzählen.
>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...)
OK, das ist ziemlich kompakt, aber wenn ich zur initialisierung
ldi X_high, 0
habe, dann funktionierts nicht? Oder täusche ich mich? Dann zieht er
eins ab, obwohl er schon null ist??
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.
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 :(
Hmm.. X_high sollte 2 sein, dann sollte die X_low-Schleife 2x
'runtergezählt werden, sprich: 2x256=512. Hatte vergessen die X_high auf
2 zu ändern, sorry!
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
>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!
Notfalls durch "NOP" ein Feinabgleich vornehmen
Schleife: ldi X_low,255
ldi X_high,1
WAIT:
dec X_low
brne WAIT
ldi X_low,255
dec X_high
brne WAIT
nop ; 1 x nix tun
ret
@Sonic
Nicht ganz.
Das Problem ist, dass zuerst dekrementiert und erst dann
auf 0 geprüft wird. Du musst das umdrehen.
Geh ins extrem: low gleich 0, high gleich 0.
Wie oft werden die Schleifen durchlaufen?
Exakt: 65536 mal
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....
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