I remember someone, I think it was Erine, asked a question before on a qiuck way to see if a number lay inside a paticular range. While working on someting else this solution occured to me. Below is some code for both integer and real numbers. Both cases are for signed numbers. Basically it works on the fact that if A lies between B and C the B - A & C- A will have different signs. Otherwise the signs will be the same, either both positive or negative. A quick xor or multiplication will test this. Note for the below code it is not necessary to know the smaller and the larger of the two extreems. In this way for arbitary numbers you actually avoid three conditional jumps. Integers
And for Real values
; Test if eax is inside range edx <-> ecx. ; Does not include eax = edx / ecx sub edx, eax sub ecx, eax xor edx, ecx test edx, 80000000h jz @F ; <- here if eax is inside range @@: ; <- here if eax is outside range
All I really what to explain here is the method, my translation of the maths to assembly may not be the best, plus my assumption on the order of values in the FPU may not suit your coding. I hope however that you understand the theory, then you should have no problem translating it to suit your needs Good Luck. Zadkiel
; Test to see if st(0) lies inside the range st(1) <-> st(2) ; For jb then st(1) & st(2) included in range. Not for jbe fsub st(2), st fsub fmul fldz fcompp fstsw ax sahf jb @F ; Set to jbe to exclude st(1) & st(2) from range. ; <- here if st is inside range @@: ; <- here if st is outside range
You don't need the "test edx, 80000000h" as xor sets the sign flag, and so you can jump using that (saves an instruction).
sub edx, eax sub ecx, eax xor edx, ecx jns @F ; <- here if eax is inside range @@: ; <- here if eax is outside range
I never actually knew there was a
, thats a nice optimisation.
Nice work Zadkiel. I've never seen this xor'ing of sign bits before. With a couple more instructions you can distinguish all five cases when (e.g.) ecx