Well, I do not answer exactly the post, but played a bit with PB and FASM instructions.
Code: Select all
;
; FWeil : 20040421
;
; The best way to divide any integer by 10 !
;
; They are many possibilities giving unexpected results.
;
; Just consider that to write y = x / 10 takes 5 to 10 seconds. Examining
; optimization cases took me a full 20 hours day of work. As it is.
; And probably then other PB coders will add some more days on it.
;
; By using the Console for output gives the most accurate results. Never test
; such tuning code using the debugger And Debug output.
;
; The code is written so that all embedding is 'outside' the process to
; evaluate. I tried To make it well so that you should only focus on the given
; request : how To divide fast an integer by 10 ...
;
; Notice that using Inline ASM does not apply well on floating operations, so
; that I prefered To use ! prefixed ASM lines.
;
;
; May you want To test up To 100 algorithms !
;
#MaxAlgo = 100
Dim tz.l( #MaxAlgo)
Dim Good.l( #MaxAlgo)
;
; Well ... from there just understand that I only expected to find a good template for testing possibilities and code results.
; As you will see, not all code parts give a good result in value, and you will not find good results in time.
; But it was a good self-training I made for dividing by 10 either using PB or FASM calls.
;
; For a good understanding of possible use of FASM in PB programs, do never forget that you manipulate the CPU and its registers
; which means that you work at the same level the compiler does. And the results you will obtain may exciting in a sample code
; but disastrous when expecting to use it in true application if you do not care enough about what registers do (and especially using
; the stack by pushing / poping values.
;
; I did not work enough for processing the whole possible knowledge required for doing better FASM samples, but I guess that
; just some small tuning from experts would give good values and better times.
;
OpenConsole()
;
; Let's use Count1 loops doing Count2 calculation of each algorythm. The x
; start value may vary Or not wether you decide To use an increment inside
; each Count1 loop. The total calculation you will have is Count1 * Count2.
; So may you adapt both paramters according To your CPU For seeing results at
; a human life scale time.
;
; The Algo variable is the algorithm index for a nice rendering of results
;
Count1.l = 40 : Count2.l = 250000 : x.l = 123456789 : Increment.l = 17 ; I inserted a random x value below
;
; Here is the main loop inside which you will test each algorithm by
; processing Count2 loops inside.
;
;
; The variable x is there for testing most possible cases. So you can
; choose To adjust either iCount1 And iCount2 And x start value Or x
; increment. The cases studies should be made with varying values so that
; rounding issues may be detected (ie by incrementing x so that the decimal
; resulting part varies from 0.0 to 0.9. May you prefer to use Random($FFFFFFFF) ... as you like it !
;
consoleLocate(1, 0)
PrintN("Title Algo# Result Time OK/False Pass#")
For iCount1 = 1 To Count1 : x = Random($7FFFFFFF) : Check.l = x / 10 ; Check is the regular result you should find.
Algo = 1 : Title.s = "PB Integers : " : tz = GetTickCount_() : For i = 1 To Count2
y = x / 10
Next : tz(Algo) = tz(Algo) + GetTickCount_() - tz : ConsoleLocate(1, Algo) : Print(Title + RSet(Str(Algo), 2, " ") + " " + RSet(Str(y), 10, " ") + " " + " " + RSet(Str(tz(Algo)), 5, " ")) : If y = Check : Good(Algo) + 1 : Print(" OK ") : Else : Print(" Failed") : EndIf : Print(RSet(Str(Good(Algo)), 4, " ") + "/" + RSet(Str(iCount1), 4, " ")) : If Good(Algo) = iCount1 : PrintN("") : Else : PrintN(" * ") : EndIf
Algo + 1 : k = 10 : Title.s = "PB Integers : " : tz = GetTickCount_() : For i = 1 To Count2
y = x / k
Next : tz(Algo) = tz(Algo) + GetTickCount_() - tz : ConsoleLocate(1, Algo) : Print(Title + RSet(Str(Algo), 2, " ") + " " + RSet(Str(y), 10, " ") + " " + " " + RSet(Str(tz(Algo)), 5, " ")) : If y = Check : Good(Algo) + 1 : Print(" OK ") : Else : Print(" Failed") : EndIf : Print(RSet(Str(Good(Algo)), 4, " ") + "/" + RSet(Str(iCount1), 4, " ")) : If Good(Algo) = iCount1 : PrintN("") : Else : PrintN(" * ") : EndIf
Algo + 1 : Title.s = "PB Floats : " : tz = GetTickCount_() : For i = 1 To Count2
y = Round(x / 8 / 1.25, 0)
Next : tz(Algo) = tz(Algo) + GetTickCount_() - tz : ConsoleLocate(1, Algo) : Print(Title + RSet(Str(Algo), 2, " ") + " " + RSet(Str(y), 10, " ") + " " + " " + RSet(Str(tz(Algo)), 5, " ")) : If y = Check : Good(Algo) + 1 : Print(" OK ") : Else : Print(" Failed") : EndIf : Print(RSet(Str(Good(Algo)), 4, " ") + "/" + RSet(Str(iCount1), 4, " ")) : If Good(Algo) = iCount1 : PrintN("") : Else : PrintN(" * ") : EndIf
Algo + 1 : Title.s = "PB Floats : " : tz = GetTickCount_() : For i = 1 To Count2
y = Round(x * 0.1, 0)
Next : tz(Algo) = tz(Algo) + GetTickCount_() - tz : ConsoleLocate(1, Algo) : Print(Title + RSet(Str(Algo), 2, " ") + " " + RSet(Str(y), 10, " ") + " " + " " + RSet(Str(tz(Algo)), 5, " ")) : If y = Check : Good(Algo) + 1 : Print(" OK ") : Else : Print(" Failed") : EndIf : Print(RSet(Str(Good(Algo)), 4, " ") + "/" + RSet(Str(iCount1), 4, " ")) : If Good(Algo) = iCount1 : PrintN("") : Else : PrintN(" * ") : EndIf
Algo + 1 : Title.s = "PB Floats : " : tz = GetTickCount_() : For i = 1 To Count2
y = Round(x / 10, 0)
Next : tz(Algo) = tz(Algo) + GetTickCount_() - tz : ConsoleLocate(1, Algo) : Print(Title + RSet(Str(Algo), 2, " ") + " " + RSet(Str(y), 10, " ") + " " + " " + RSet(Str(tz(Algo)), 5, " ")) : If y = Check : Good(Algo) + 1 : Print(" OK ") : Else : Print(" Failed") : EndIf : Print(RSet(Str(Good(Algo)), 4, " ") + "/" + RSet(Str(iCount1), 4, " ")) : If Good(Algo) = iCount1 : PrintN("") : Else : PrintN(" * ") : EndIf
Algo + 1 : Title.s = "ASM Integers : " : tz = GetTickCount_() : For i = 1 To Count2
! PUSH dword [v_x]
! POP dword [v_y]
! MOV eax, dword[v_x]
! MOV ebx, 10
! CDQ
! IDIV ebx
! MOV dword [v_y],eax
Next : tz(Algo) = tz(Algo) + GetTickCount_() - tz : ConsoleLocate(1, Algo) : Print(Title + RSet(Str(Algo), 2, " ") + " " + RSet(Str(y), 10, " ") + " " + " " + RSet(Str(tz(Algo)), 5, " ")) : If y = Check : Good(Algo) + 1 : Print(" OK ") : Else : Print(" Failed") : EndIf : Print(RSet(Str(Good(Algo)), 4, " ") + "/" + RSet(Str(iCount1), 4, " ")) : If Good(Algo) = iCount1 : PrintN("") : Else : PrintN(" * ") : EndIf
Algo + 1 : f.f = 1.25 : Title.s = "ASM Floats : " : tz = GetTickCount_() : For i = 1 To Count2
! MOV ebx,dword [v_x]
! SAR ebx,3
! MOV dword [esp-4],ebx
! FILD dword [esp-4]
! FDIV dword [v_f]
! FISTP dword [v_y]
Next : tz(Algo) = tz(Algo) + GetTickCount_() - tz : ConsoleLocate(1, Algo) : Print(Title + RSet(Str(Algo), 2, " ") + " " + RSet(Str(y), 10, " ") + " " + " " + RSet(Str(tz(Algo)), 5, " ")) : If y = Check : Good(Algo) + 1 : Print(" OK ") : Else : Print(" Failed") : EndIf : Print(RSet(Str(Good(Algo)), 4, " ") + "/" + RSet(Str(iCount1), 4, " ")) : If Good(Algo) = iCount1 : PrintN("") : Else : PrintN(" * ") : EndIf
Algo + 1 : f.f = 1.25 : Title.s = "ASM Floats : " : tz = GetTickCount_() : For i = 1 To Count2
! PUSH dword [v_x]
! POP dword [v_y]
! MOV ebx,dword [v_x]
! SAR ebx,3
! MOV dword [esp-4],ebx
! FILD dword [esp-4]
! FDIV dword [v_f]
! FISTP dword [v_y]
Next : tz(Algo) = tz(Algo) + GetTickCount_() - tz : ConsoleLocate(1, Algo) : Print(Title + RSet(Str(Algo), 2, " ") + " " + RSet(Str(y), 10, " ") + " " + " " + RSet(Str(tz(Algo)), 5, " ")) : If y = Check : Good(Algo) + 1 : Print(" OK ") : Else : Print(" Failed") : EndIf : Print(RSet(Str(Good(Algo)), 4, " ") + "/" + RSet(Str(iCount1), 4, " ")) : If Good(Algo) = iCount1 : PrintN("") : Else : PrintN(" * ") : EndIf
Algo + 1 : f1.f = 0.1 : f2.f : Title.s = "ASM Floats : " : tz = GetTickCount_() : For i = 1 To Count2
! MOV ebx,dword [v_x]
! MOV dword [esp-4],ebx
! FILD dword [esp-4]
! FMUL dword [v_f1]
! FISTP dword [v_y]
Next : tz(Algo) = tz(Algo) + GetTickCount_() - tz : ConsoleLocate(1, Algo) : Print(Title + RSet(Str(Algo), 2, " ") + " " + RSet(Str(y), 10, " ") + " " + " " + RSet(Str(tz(Algo)), 5, " ")) : If y = Check : Good(Algo) + 1 : Print(" OK ") : Else : Print(" Failed") : EndIf : Print(RSet(Str(Good(Algo)), 4, " ") + "/" + RSet(Str(iCount1), 4, " ")) : If Good(Algo) = iCount1 : PrintN("") : Else : PrintN(" * ") : EndIf
Algo + 1 : f1.f = 10 : f2.f : Title.s = "ASM Floats : " : tz = GetTickCount_() : For i = 1 To Count2
! MOV ebx,dword [v_x]
! MOV dword [esp-4],ebx
! FILD dword [esp-4]
! FDIV dword [v_f1]
! FISTP dword [v_y]
Next : tz(Algo) = tz(Algo) + GetTickCount_() - tz : ConsoleLocate(1, Algo) : Print(Title + RSet(Str(Algo), 2, " ") + " " + RSet(Str(y), 10, " ") + " " + " " + RSet(Str(tz(Algo)), 5, " ")) : If y = Check : Good(Algo) + 1 : Print(" OK ") : Else : Print(" Failed") : EndIf : Print(RSet(Str(Good(Algo)), 4, " ") + "/" + RSet(Str(iCount1), 4, " ")) : If Good(Algo) = iCount1 : PrintN("") : Else : PrintN(" * ") : EndIf
ConsoleLocate(1, Algo + 2)
PrintN("Pass " + Str(iCount1) + " / " + Str(Count1))
sDone.s = Str(Count2 * iCount1 ) : Done.s = "" : j = 0 : For i = Len(sDone) To 1 Step -1 : Done = Mid(sDone, i, 1) + Done : j + 1 : If j % 3 = 0 And i <> 1 : Done = "." + Done : EndIf : Next
sToDo.s = Str(Count1 * Count2) : ToDo.s = "" : j = 0 : For i = Len(sToDo) To 1 Step - 1 : ToDo = Mid(sToDo, i, 1) + ToDo : j + 1 : If j % 3 = 0 And i <> 1 : ToDo = "." + ToDo : EndIf : Next
ConsoleLocate(1, Algo + 3)
PrintN("Done " + Done + " / " + ToDo + " operations for each algorithm")
If Inkey() <> "" : Break : EndIf
Next iCount1
Repeat : Until Inkey() <> "" : CloseConsole()