netmaestro wrote:There may be a more efficient way to do this but I'm not finding it... Although actually it's executing 10 million times in 124 ms here. That's pretty fast.
Nice division algorithm.
Even with the same algorithm you can speed things up.
You can first add the components and then divide (see the adapted PB routine).
It's also not required to use ebx (which officially should be preserved) and to allocate a variable for result.
Last change I made is using a local label instead of an anonymous label because anonymous asm labels aren't supported on OSX (nasm/yasm instead of fasm).
Code: Select all
Procedure Color_Mix_asm(color1.l, color2.l, percent.l)
; netmaestro May 2017
!xor ecx, ecx
!.loop:
!mov eax, 0x64
!sub eax, [p.v_percent]
!movzx edx, byte [p.v_color2 + ecx]
!imul edx, eax
!movzx eax, byte [p.v_color1 + ecx]
!imul eax, [p.v_percent]
!add eax, edx
!mov edx, eax
!shr edx, 5
!add edx, eax
!shl edx, 2
!add eax, edx
!shr eax, 9
!mov [p.v_color1 + ecx], al
!inc ecx
!cmp ecx, 0x2
!jle .loop
!mov eax, [p.v_color1]
ProcedureReturn
EndProcedure
Procedure Color_Mix_pb(color1.l, color2.l, percent.l)
r= (Red(color1)*percent + Red(color2)*(100-percent)) / 100
g= (Green(color1)*percent + Green(color2)*(100-percent)) / 100
b= (Blue(color1)*percent + Blue(color2)*(100-percent)) / 100
ProcedureReturn RGB(r,g,b)
EndProcedure
; Debug RSet(Hex(Color_Mix_pb(#Red, #Green, 80),#PB_Long), 6, "0")
; Debug RSet(Hex(Color_Mix_asm(#Red, #Green, 80),#PB_Long), 6, "0")
;
; End
CompilerIf #PB_Compiler_Debugger
MessageRequester("Notice:", "Please turn off the debugger for this test")
End
CompilerEndIf
s=ElapsedMilliseconds()
For i=1 To 10000000
Color_Mix_pb(#Green,#Blue, 50)
Next
e=ElapsedMilliseconds()-s
MessageRequester("PB Code Version", Str(ElapsedMilliseconds()-s))
s=ElapsedMilliseconds()
For i=1 To 10000000
Color_Mix_asm(#Green,#Blue, 50)
Next
MessageRequester("asm Version", Str(ElapsedMilliseconds()-s))
Using a multiply with a shift to divide seems to be a bit faster.
There might be rounding differences between the two approaches; haven't checked for that.
Code: Select all
Procedure Color_Mix_asm(color1.l, color2.l, percent.l)
; netmaestro May 2017
!xor ecx, ecx
!.loop:
!mov eax, 0x64
!sub eax, [p.v_percent]
!movzx edx, byte [p.v_color2 + ecx]
!imul edx, eax
!movzx eax, byte [p.v_color1 + ecx]
!imul eax, [p.v_percent]
!add eax, edx
!imul eax, 167773
!shr eax, 24
!mov [p.v_color1 + ecx], al
!inc ecx
!cmp ecx, 0x2
!jle .loop
!mov eax, [p.v_color1]
ProcedureReturn
EndProcedure
Procedure Color_Mix_pb(color1.l, color2.l, percent.l)
r= (Red(color1)*percent + Red(color2)*(100-percent)) / 100
g= (Green(color1)*percent + Green(color2)*(100-percent)) / 100
b= (Blue(color1)*percent + Blue(color2)*(100-percent)) / 100
ProcedureReturn RGB(r,g,b)
EndProcedure
; Debug RSet(Hex(Color_Mix_pb(#Red, #Green, 80),#PB_Long), 6, "0")
; Debug RSet(Hex(Color_Mix_asm(#Red, #Green, 80),#PB_Long), 6, "0")
;
; End
CompilerIf #PB_Compiler_Debugger
MessageRequester("Notice:", "Please turn off the debugger for this test")
End
CompilerEndIf
s=ElapsedMilliseconds()
For i=1 To 10000000
Color_Mix_pb(#Green,#Blue, 50)
Next
e=ElapsedMilliseconds()-s
MessageRequester("PB Code Version", Str(ElapsedMilliseconds()-s))
s=ElapsedMilliseconds()
For i=1 To 10000000
Color_Mix_asm(#Green,#Blue, 50)
Next
MessageRequester("asm Version", Str(ElapsedMilliseconds()-s))