PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Division mit AVR



LinuxMan
18.11.2003, 01:47
;************************************************* ***********************
;* *
;* unsigned division 16 bit *
;* fast *
;* *
;************************************************* ***********************

udiv16rnd:
mov a, op2l
mov i, op2h
lsr i ;2.operand / 2
ror a
add op1l, a ;1.Op = 1.Op + 2.Op / 2
adc op1h, i

;cycles: 94/186 (min/max)
;words: 33
udiv16:
tst op2h
brne udi4
ldi i, 16 ;divisor < 256
udi1: lsl op1l ;loop: 16 * 11 - 1 = 175 cycles
rol op1h
rol op2h
brcs udi2
cp op2h, op2l
brcs udi3
udi2: sub op2h, op2l
inc op1l
udi3: dec i
brne udi1
mov op2l, op2h ;store remainder
clr op2h
ret

udi4: ldi i, 8 ;divisor >= 256
clr a
udi5: lsl op1l ;loop: 8 * 12 - 1 = 95 cycles
rol op1h
rol a
cp op1h, op2l ;test
cpc a, op2h
brcs udi6
sub op1h, op2l
sbc a, op2h
inc op1l
udi6: dec i
brne udi5
mov op2l, op1h ;store remainder
mov op2h, a
clr op1h
ret
;------------------------------------------------------------------------

hrrh
16.03.2004, 11:33
Bei der C-controll1:
a=b/c
Basic ist doch einfacher, wenn auch langsamer!!!

16.03.2004, 11:42
In AVR-Basic (Bascom):

a=b/c

Nur halt viel schneller als bei der C-Control :-) und zudem noch genauer - nämlich wahlweise auch mit Nachkommastellen

REB
20.03.2004, 23:04
Wie war dieGeschichte mit den Prgrammierern und der Großwildjagd noch mal?
Man kann natürlich alles in Assembler programmieren oder in Basic / C++ / iC, Delphi,... . Wenns denn sein muss auch in VBA.
Manches ist aber nicht sehr sinnvoll.
Assembler hat seine unereichbaren Vorteile bei dem Speicher / Portzugriff bzw. ~manipulation; ist aber bei Rechenoperationen etwas umständlich. Für den Rest der Sprachen gilt das vice versa.

REB

cht
11.06.2004, 17:41
Das hab ich gerade produziert: es lehnt an die schriftliche Division aus der Grundschule (verschlafen?) an, wie man sieht funzt dieses Verfahren auch in Binär. Es ist zwar Delphi-Code weil ich zum Testen nicht extra den µC proggen wollte, aber wens interessiert, der kanns ja in assembler übersetzen.


procedure TForm1.Button1Click(Sender: TObject);
var
r16, r18, r20:word;//r16=Dividend, r18=Divisor, r20=Ergebnis
i:byte; //Schleifenzähler
begin
r16:=StrToIntDef(Edit1.Text,1);//Dividend laden, bei Mist im Eingabefeld 1
r18:=StrToIntDef(Edit2.Text,1);//Divisor laden
while (r18<high(r16) shr 1) do //Divisor bis zum Anschlag...
r18:=r18 shl 1; //nach links schieben.
for i:=0 to 15 do begin //Schleife, für jedes Ergebnis-Bit
r20:=r20 shl 1; //Ergebnis weiterschieben
if (r16>=r18) then begin //wenns reinpasst...
r16:=r16-r18; //einmal subtrahieren ...
r20:=r20 or 1; //und ne Eins ins Ergebnis.
end; //Ende If.
r18:=r18 shr 1; //Divisor weiterschieben
end; //Ende Schleife.
r18:=StrToIntDef(Edit2.Text,1);//Divisor nochmal laden
while (r18>1) do begin //Ergebnis so oft...
r20:=r20 shr 1; //nach rechts schieben...
r18:=r18 shr 1; //...wie der Divisor lang ist.
end; //Ende Schleife.
Edit3.Text:=IntToStr(r20); //Ergebnis ausgeben.
end;

Das Ergebnis wird immer ABgerundet, wer will kann den Code ja so midifizieren dass er richtig rundet. Ich denke, für natürliche Zahlen oder Festkommawerte ist das eine praktische Lösung. Oder weiss jemand was schnelleres? Bitte posten!

mfG

cht