I needed a way to check if a value was even or odd. So, I looked in the forum and didn't notice anything. I looked around in the examples and didn't see anything. So, I tried some code. I messed around with memory stuff and strings. Got that to work okay. I then tried some stuff with Right(), Bin() and etc... that one worked faster. However, not so elegant. I thought... oooooohhhhh... nice time to learn a little ASM. Can't be *that* scary. ^_^ So, after reading the FASM tutorial on their website I managed to fumble my way through some stuff.
Here's the two procedures I came up with. One was the faster non-ASM code. The other is the much faster ASM code. Also, I got to learn about using "!" or inline ASM and I went with using "!" so you don't have to turn on inline asm.
Code: Select all
Procedure.b IsEven(inValue)
If Right(Bin(inValue),1) = "1" : bRet = #False : Else : bRet = #True : EndIf
ProcedureReturn bRet
EndProcedure
Procedure IsEvenASM(inValue)
; Test whether a value is Even (#TRUE) or Odd (#FALSE)
!MOV eax, [esp]
; Copy our parameter value into the eax register. inValue will be pushed onto the stack
; and is a LONG type. It's the only parameter passed so it's offset is 0. [esp + 0]
!MOV ebx, 0
; From what I can tell CMOVC copies from one dword to another so store this as my FALSE value.
!BT eax, 0
; Store the low order bit (the first bit starting from the right) to our CF (carry flag).
!MOV eax, 1
; By default, pass that it is TRUE. We will test if it's FALSE in the next CMOVC statement.
!CMOVC eax, ebx
; Now test to see if our CF (carry flag) is set (the 'C' at the end of CMOV). If so, copy
; ebx(0) to eax. Odd numbers have a 1 in their low order bit. In that case the CF is set.
; And when the CF flag thingie is set, we copy ebx to eax making our return value FALSE.
; If not, this won't copy anything since it's a conditional statement.
ProcedureReturn
; Now return the value of eax.
EndProcedure
Define iLoop, iCount, Start, Stop
iCount = 0
Start = GetTickCount_()
For iLoop = 0 To 2000000
If IsEvenASM(iLoop) = #True : iCount + 1 : EndIf
Next iLoop
Stop = GetTickCount_()
MessageRequester(Str(iCount), Str(Stop-Start)) ; 16 ms on my computer
;
iCount = 0
Start = GetTickCount_()
For iLoop = 0 To 2000000
If IsEven(iLoop) = #True : iCount + 1 : EndIf
Next iLoop
Stop = GetTickCount_()
MessageRequester(Str(iCount), Str(Stop-Start)) ; 219 ms on my computer


[Edit: Oh hey! Look at that! It must be fate. I learn a little ASM and now I'm an "Apprentice"!

[Edit 2: Duh, I didn't need two of the lines in the ASM version so I removed them. Didn't really notice a speed increase, though.]