Verfasst: 12.06.2005 19:11
Hm... und was heisst das
Naja, wenn ich Zeit find, werd ichs trotzdem mal einbauen..
Naja, wenn ich Zeit find, werd ichs trotzdem mal einbauen..
Code: Alles auswählen
divisor.l=0
shiftwert.b=0
dividend.l=0
faktor.l=0
z.l=0
q.l=0
For dividend= -2000 To 2000
For divisor= 2 To 20
;----- Diese Routine dient zur Ermittlung von Faktor und Shiftwert für einen konstanten Divisor ----
MOV [v_shiftwert],16
MOV EBX,[v_divisor]
NOAND:
BSR EAX,EBX
ADD [v_shiftwert],AL
MOV CL,[v_shiftwert]
MOV EAX,1
SHL EAX,CL
MOV ECX,EBX
XOR EDX,EDX
DIV ECX
PUSHAD
MOV EAX,[v_dividend]
TEST EAX,80000000h
JZ l_nominus0
NEG EAX
NOMINUS0:
XOR EDX,EDX
DIV EBX
MOV [v_q],EDX
POPAD
CMP [v_q],0
JE l_plus
SHR EBX,1
CMP EDX,EBX
JB l_noplus
PLUS:
INC EAX
NOPLUS:
MOV [v_faktor],EAX
;-------------- Test ------------
MOV EAX,[v_dividend]
TEST EAX,80000000h
JZ l_nominus
NEG EAX
NOMINUS:
IMUL EAX,[v_faktor]
MOV CL,[v_shiftwert]
SHR EAX,CL
TEST [v_dividend],80000000h
JZ l_nominus1
NEG EAX
NOMINUS1:
MOV [v_z],EAX
;---------------- Test "herkömmliche Methode" ------------
MOV EAX,[v_dividend]
MOV EBX,[v_divisor]
CDQ
IDIV EBX
MOV [v_q],EAX
;---------------------------------------------------------
CMP EAX,[v_z]
JE l_noerror
Debug "Error!"
Debug dividend
Debug divisor
Debug z
Debug q
End
NOERROR:
Debug z
Debug q
Next
Next
End
Code: Alles auswählen
;--- "Ersatz" für IDIV mit konstanten positiven Divisor. Für negativen Divisor ist gesonderte Routine angebracht.
;--- Divisor darf keine 2-er Potenz sein! Dafür gibt es Extra-Routinen
;--- Werte-Bereich Dividend von -65335 bis +65335
;--- Werte-Bereich Divisor von +3 bis +65335
divisor.l = 0
shiftwert.b = 0
dividend.l = 0
faktor.l = 0
kwert.l = 0
multi.l = 0
divi.l = 0
For dividend = -6533 To 6533
For divisor = 3 To 653
;(Werte in o.g. Grenzen willkürlich gewählt)
;-------------------------------------------------------------------------------------------------------
;Diese Routine dient zur Ermittlung von Faktor, Shiftwert und Korrekturwert für einen konstanten Divisor
;Hier hat natürlich der Dividend nichts zu suchen!
MOV [v_shiftwert],16
MOV EBX,[v_divisor]
BSR EAX,EBX
;JZ l_error ;divisor ist Null
ADD [v_shiftwert],AL
MOV CL,[v_shiftwert]
MOV EAX,1
SHL EAX,CL
MOV ECX,EBX
XOR EDX,EDX
DIV ECX
OR EDX,EDX
;JZ l_error
JZ l_pot2 ;divisor ist 2-er Potenz! Normalerweise Sprung zu error, hier wegen Schleife nicht
MOV [v_kwert],0
SHR EBX,1
CMP EDX,EBX
JBE l_noplus
INC EAX
JMP l_plus
NOPLUS: MOV [v_kwert],1
PLUS: MOV [v_faktor],EAX
;-------------------------------------------------------------------------------------------
;-------------- Test mit Multiplikation ------------
MOV EAX,[v_dividend]
TEST EAX,80000000h
JZ l_nominus
SUB EAX,[v_kwert]
NEG EAX
JMP l_nominus1
NOMINUS: ADD EAX,[v_kwert]
NOMINUS1: IMUL EAX,[v_faktor]
MOV CL,[v_shiftwert]
SHR EAX,CL
TEST [v_dividend],80000000h
JZ l_nominus2
NEG EAX
NOMINUS2: MOV [v_multi],EAX
;---------------- Test "herkömmliche Methode" ------------
;---- Das Kürzere ist nicht immer das Schnellere!
MOV EAX,[v_dividend]
MOV EBX,[v_divisor]
CDQ
IDIV EBX
MOV [v_divi],EAX
;---------------------------------------------------------
CMP EAX,[v_multi]
JE l_noerror
Debug "Error!"
Debug dividend
Debug divisor
Debug faktor
Debug kwert
Debug multi
Debug divi
End
NOERROR:
Debug multi
Debug divi
POT2:
Next divisor
Next dividend
End
Code: Alles auswählen
;--- "Ersatz" für IDIV mit konstanten positiven Divisor. Für negativen Divisor ist gesonderte Routine angebracht.
;--- Divisor darf keine 2-er Potenz sein! Dafür gibt es Extra-Routinen
;--- Voller Werte-Bereich (signed long), aber erstmal nur positiver Divisor
;----------------------------------- Helle, PB3.93, 16.6.2005 --------------------------------------
divisor.l = 123
shiftwert.b = 0
dividend.l = 0
faktor.l = 0
kwert.l = 0
multitime.l = 0
divitime.l = 0
multiwert.l = 0
diviwert.l = 0
;---------------------------------------------------------------------------------------------------
;Diese Routine dient zur Ermittlung von Faktor, Shiftwert und Korrekturwert für einen konstanten positiven Divisor
;----------------------------- Aussieben von Null und 2-er-Potenzen des Divisors -------------------
;---------------- wird benötigt, wenn in einer Testschleife auch der Divisor geändert wird ---------
MOV EAX,[v_divisor]
AND EAX,7fffffffh ;zur Sicherheit, falls doch negativ
MOV CL,31
XOR DL,DL
WEITER: SHR EAX,1
ADC DL,0
DEC CL
JNZ l_weiter
CMP DL,1
JBE l_error ;kein oder nur ein Bit gesetzt (nur ein Bit=2-er-Potenz)
;----------------------------------------- Eigentliche Routine -------------------------------------
MOV EBX,[v_divisor]
AND EBX,7fffffffh ;falls negativ, Vorzeichen weg
BSR EAX,EBX
MOV [v_shiftwert],AL
MOV CL,[v_shiftwert]
MOV EDX,1
SHL EDX,CL
MOV ECX,EBX
XOR EAX,EAX
DIV ECX
MOV [v_kwert],0
SHR EBX,1
CMP EDX,EBX
JBE l_noplus
INC EAX
JMP l_plus
NOPLUS: MOV [v_kwert],1
PLUS: MOV [v_faktor],EAX
;-------------------------------------- Test für Division durch 123 --------------------------------
;---------------------------------------- Test mit Multiplikation ----------------------------------
StartTime = ElapsedMilliseconds()
For i = 1 To 10000
For dividend = -56789 To 56789
MOV EAX,[v_dividend]
MOV EDX,85340853h ;[v_faktor] für Divisor=123
TEST EAX,80000000h
JZ l_nominus
DEC EAX ;weil [v_kwert]=1. Bei Null kann Zeile komplett entfallen
NEG EAX
JMP l_nominus1 ;kann bei [v_kwert]=0 auch entfallen!
NOMINUS: INC EAX ;weil [v_kwert]=1. Bei Null kann INC entfallen (nicht die Zeile!)
NOMINUS1: MUL EDX
SHR EDX,6 ;[v_shiftwert] für Divisor=123
TEST [v_dividend],80000000h
JZ l_nominus2
NEG EDX
NOMINUS2: MOV [v_multiwert],EDX
Next dividend
Next i
multitime = ElapsedMilliseconds()-StartTime
;---------------------------------------------------------------------------------------------------
;-------------------------------------- Test mit herkömmlicher Division ----------------------------
StartTime = ElapsedMilliseconds()
For i = 1 To 10000
For dividend = -56789 To 56789
MOV EAX,[v_dividend]
CDQ
IDIV [v_divisor]
MOV [v_diviwert],EAX
Next dividend
Next i
divitime = ElapsedMilliseconds()-StartTime
;---------------------------------------------------------------------------------------------------
multit$ = Str(multitime)
divit$ = Str(divitime)
multiw$ = Str(multiwert)
diviw$ = Str(diviwert)
MessageRequester("Vergleichstest","Multiplikationszeit = "+multit$+Chr(13)+"Divisionszeit = " +divit$+Chr(13)+"Multiplikationsendwert = "+multiw$+Chr(13)+"Divisionsendwert = "+diviw$)
End
ERROR: ;irgendwas
End
Code: Alles auswählen
;--- "Ersatz" für IDIV mit konstanten negativen Divisor. Für positiven Divisor existiert gesonderte Routine.
;--- Divisor darf keine 2-er Potenz sein! Dafür gibt es Extra-Routinen.
;--- Voller Werte-Bereich (signed long).
;----------------------------------- Helle, PB3.93, 17.6.2005 --------------------------------------
divisor.l = -123
shiftwert.b = 0
dividend.l = 0
faktor.l = 0
kwert.l = 0
multitime.l = 0
divitime.l = 0
multiwert.l = 0
diviwert.l = 0
;---------------------------------------------------------------------------------------------------
;Diese Routine dient zur Ermittlung von Faktor, Shiftwert und Korrekturwert für einen konstanten negativen Divisor
;----------------------------- Aussieben von Null und 2-er-Potenzen des Divisors -------------------
;---------------- wird benötigt, wenn in einer Testschleife auch der Divisor geändert wird ---------
MOV EAX,[v_divisor]
NEG EAX
MOV CL,31
XOR DL,DL
WEITER: SHR EAX,1
ADC DL,0
DEC CL
JNZ l_weiter
CMP DL,1
JBE l_error ;kein oder nur ein Bit gesetzt (nur ein Bit=2-er-Potenz)
;----------------------------------------- Eigentliche Routine -------------------------------------
MOV EBX,[v_divisor]
NEG EAX
BSR EAX,EBX
MOV [v_shiftwert],AL
MOV CL,[v_shiftwert]
MOV EDX,1
SHL EDX,CL
MOV ECX,EBX
XOR EAX,EAX
DIV ECX
MOV [v_kwert],0
SHR EBX,1
CMP EDX,EBX
JBE l_noplus
INC EAX
JMP l_plus
NOPLUS: MOV [v_kwert],1
PLUS: MOV [v_faktor],EAX
;-------------------------------------- Test für Division durch -123 -------------------------------
;---------------------------------------- Test mit Multiplikation ----------------------------------
StartTime = ElapsedMilliseconds()
For i = 1 To 10000
For dividend = -56789 To 56789
MOV EAX,[v_dividend]
MOV EDX,85340853h ;[v_faktor] für Divisor=-123
TEST EAX,80000000h
JZ l_nominus
DEC EAX ;weil [v_kwert]=1. Bei Null kann Zeile komplett entfallen
NEG EAX
JMP l_nominus1 ;kann bei [v_kwert]=0 auch entfallen!
NOMINUS: INC EAX ;weil [v_kwert]=1. Bei Null kann INC entfallen (nicht die Zeile!)
NOMINUS1: MUL EDX
SHR EDX,6 ;[v_shiftwert] für Divisor=-123
TEST [v_dividend],80000000h
JNZ l_nominus2
NEG EDX
NOMINUS2: MOV [v_multiwert],EDX
Next dividend
Next i
multitime = ElapsedMilliseconds()-StartTime
;---------------------------------------------------------------------------------------------------
;-------------------------------------- Test mit herkömmlicher Division ----------------------------
StartTime = ElapsedMilliseconds()
For i = 1 To 10000
For dividend = -56789 To 56789
MOV EAX,[v_dividend]
CDQ
IDIV [v_divisor]
MOV [v_diviwert],EAX
Next dividend
Next i
divitime = ElapsedMilliseconds()-StartTime
;---------------------------------------------------------------------------------------------------
multit$ = Str(multitime)
divit$ = Str(divitime)
multiw$ = Str(multiwert)
diviw$ = Str(diviwert)
MessageRequester("Vergleichstest","Multiplikationszeit = "+multit$+Chr(13)+"Divisionszeit = " +divit$+Chr(13)+"Multiplikationsendwert = "+multiw$+Chr(13)+"Divisionsendwert = "+diviw$)
End
ERROR: ;irgendwas
End