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
; 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
And for Real values
; 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
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.
ZadkielYou 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
MirnoI never actually knew there was a
jns
, 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