Hast du eigentlich schon die Optimierungen für multiplikation
mit negativen Zahlen eingebaut ?
Hier noch ein Ersatz für den Int-Befehl:
Code: Alles auswählen
_PB_Int@4
!FISTP dword[esp-4]
!MOV Eax,[esp-4]
Gruß
Stefan
Code: Alles auswählen
_PB_Int@4
!FISTP dword[esp-4]
!MOV Eax,[esp-4]
Code: Alles auswählen
;------- Unsigned Division mit konstanten Divisor; Dividend und Divisor jeweils kleiner 65336 ------
;----------- Die Division (DIV) wird ersetzt durch eine schnellere Multiplikationsroutine ----------
;----------------------------------- Helle, PB3.93, 12.6.2005 --------------------------------------
divisor.l=23 ;für Test frei gewählt
shiftwert.b=0
dividend.l=0
faktor.l=0
quotient.l=0 ;zur Korrektur von faktor
;----- Diese Routine dient zur Ermittlung von faktor und shiftwert für einen konstanten Divisor ----
MOV [v_shiftwert],16
BSR EAX,[v_divisor]
;JZ l_error ;kein gesetztes Bit gefunden, wäre Division durch Null!
ADD [v_shiftwert],AL
MOV CL,[v_shiftwert]
MOV EAX,1
SHL EAX,cl
MOV ECX,[v_divisor]
XOR EDX,EDX
DIV ECX
MOV EBX,[v_divisor]
PUSHAD
MOV EAX,[v_dividend]
XOR EDX,EDX
DIV EBX
MOV [v_quotient],EDX
POPAD
CMP [v_quotient],0
JE l_plus
SHR EBX,1
CMP EDX,EBX
JB l_noplus
PLUS:
INC EAX
NOPLUS:
MOV [v_faktor],EAX
;faktor und shiftwert für divisor 1-65335 können auch in eine Tabelle geschrieben werden, ähnlich
;wie Remi´s IMULOptimierungen.txt
;-------------------------------------- Test für Division durch 23 ---------------------------------
a1.l=0
a2.l=0
;---------------------------------------- Test mit Multiplikation ----------------------------------
StartTime = ElapsedMilliseconds()
For i=1 To 1000
For dividend = 0 To 65000
MOV EAX,[v_dividend]
IMUL EAX,45591 ;ermittelter faktor für Divisor=23
SHR EAX,20 ;ermittelter shiftwert für Divisor=23
MOV [v_a1],EAX ;zeigt hier nur den Endwert an: 65000/23=2826
Next dividend
Next i
Debug = ElapsedMilliseconds()-StartTime
Debug a1
;---------------------------------------------------------------------------------------------------
Debug "########"
;-------------------------------------- Test mit herkömmlicher Division ----------------------------
StartTime = ElapsedMilliseconds()
For i=1 To 1000
For dividend = 0 To 65000
MOV EAX,[v_dividend]
XOR EDX,EDX
DIV [v_divisor]
MOV [v_a2],EAX ;zeigt hier nur den Endwert an: 65000/23=2826
Next dividend
Next i
Debug = ElapsedMilliseconds()-StartTime
Debug a2
;---------------------------------------------------------------------------------------------------
;Werte auf Athlon64,3200+: Multiplikation: 5,3s
; Division: 6,3s
;nicht umwerfend, aber besser als garnichts
End
Code: Alles auswählen
SetPriorityClass_(GetCurrentProcess_(),#REALTIME_PRIORITY_CLASS)
M1Start=GetTickCount_()
For C=-100000000 To 100000000
!MOV EAX,[v_C]
!CDQ
!MOV EBX,2
!IDIV EBX
Next
M1Ende=GetTickCount_()
Delay(1000)
M2Start=GetTickCount_()
For C=-100000000 To 100000000
!MOV EAX,[v_C]
!CMP EAX,0
!JGE NoNeg
!NEG EAX
!SAR Eax,1
!NEG EAX
!JMP EndShift
!NoNeg:
!SAR Eax,1
!EndShift:
Next
M2Ende=GetTickCount_()
Delay(1000)
M3Start=GetTickCount_()
For C=-100000000 To 100000000
!MOV EAX,[v_C]
Next
M3Ende=GetTickCount_()
TSchleife=M3Ende-M3Start
TMethod1=M1Ende-M1Start-TSchleife
TMethod2=M2Ende-M2Start-TSchleife
A$="Method 1(IDIV) "+Str(TMethod1)+" ms"+Chr(13)
A$+"Method 2 "+Str(TMethod2)+" ms"+Chr(13)
SetPriorityClass_(GetCurrentProcess_(),#NORMAL_PRIORITY_CLASS)
MessageRequester("Result",A$)