Is unsigned value in bounds (inclusive) without branching

  • Follow


Hi All,
my little snippet to check if unsigned value is in bounds
(inclusive), 8 instructions 3 registers. i have another version too,
8 instrs. *2 register* but it is not much compiler friendly.
Also, conditions:

1) EAX original value on ret
2) ZFlag or CFlag re/set on error
2) must return 0 not0 as info in a register,
    respectively for low/hi bound overflow
    or viceversa

ideas,improvements ?

..is_inbound:
  mov eax,value
  mov ecx,MAX_BOUND
  cmp eax,MIN_BOUND
  sbb edx,edx
  cmp ecx,eax
  not edx
  sbb ecx,ecx
  xor ecx,edx
  jz .err


Cheers

-- 

  .:hopcode[marc:rainer:kranz]:.
  x64 Assembly Lab
  http://sites.google.com/site/x64lab
0
Reply hopcode 3/24/2011 10:22:54 PM

On Mar 24, 5:22=A0pm, hopcode <hopc...@nospicedham.nullnichtsnada.com>
wrote:
> Hi All,
> my little snippet to check if unsigned value is in bounds
> (inclusive), 8 instructions 3 registers. i have another version too,
> 8 instrs. *2 register* but it is not much compiler friendly.
> Also, conditions:
>
> 1) EAX original value on ret
> 2) ZFlag or CFlag re/set on error
> 2) must return 0 not0 as info in a register,
> =A0 =A0 respectively for low/hi bound overflow
> =A0 =A0 or viceversa
>
> ideas,improvements ?
>
> .is_inbound:
> =A0 mov eax,value
> =A0 mov ecx,MAX_BOUND
> =A0 cmp eax,MIN_BOUND
> =A0 sbb edx,edx
> =A0 cmp ecx,eax
> =A0 not edx
> =A0 sbb ecx,ecx
> =A0 xor ecx,edx
> =A0 jz .err


How about:

 mov ebx,eax
 sub ebx,MIN_BOUND
 cmp ebx,(MAX_BOUND-MIN_BOUND+1)
 setae bl
 movzx ebx,bl

Shorter, although not necessarily faster (setcc is slow on some
processors).  Carry set if out of range, ebx set to 0/1 (in/out of
range).  And if you only need the carry returned, you can eliminate
the last two instructions.
0
Reply robertwessel2 3/24/2011 11:39:49 PM


Il 25.03.2011 00:39, robertwessel2@yahoo.com ha scritto:
> On Mar 24, 5:22 pm, hopcode<hopc...@nospicedham.nullnichtsnada.com>
> wrote:
>> Hi All,
>> my little snippet to check if unsigned value is in bounds
>> (inclusive), 8 instructions 3 registers. i have another version too,
>> 8 instrs. *2 register* but it is not much compiler friendly.
>> Also, conditions:
>>
>> 1) EAX original value on ret
>> 2) ZFlag or CFlag re/set on error
>> 2) must return 0 not0 as info in a register,
>>      respectively for low/hi bound overflow
>>      or viceversa
>>
>> ideas,improvements ?
>>
>> .is_inbound:
>>    mov eax,value
>>    mov ecx,MAX_BOUND
>>    cmp eax,MIN_BOUND
>>    sbb edx,edx
>>    cmp ecx,eax
>>    not edx
>>    sbb ecx,ecx
>>    xor ecx,edx
>>    jz .err
>
>
> How about:
>
>   mov ebx,eax
>   sub ebx,MIN_BOUND
>   cmp ebx,(MAX_BOUND-MIN_BOUND+1)
>   setae bl
>   movzx ebx,bl
>
> Shorter, although not necessarily faster (setcc is slow on some
> processors).  Carry set if out of range, ebx set to 0/1 (in/out of
> range).  And if you only need the carry returned, you can eliminate
> the last two instructions.

Hi robertwessel,
setae bl is necessary.it drives all the music.
I am testing a new version just in this minutes...

Cheers,

-- 

  .:hopcode[marc:rainer:kranz]:.
  x64 Assembly Lab
  http://sites.google.com/site/x64lab
0
Reply hopcode 3/25/2011 1:11:02 AM

Il 24.03.2011 23:22, hopcode ha scritto:
> Hi All,
> my little snippet to check if unsigned value is in bounds
> (inclusive), 8 instructions 3 registers. i have another version too,
> 8 instrs. *2 register* but it is not much compiler friendly.
> Also, conditions:
>
> 1) EAX original value on ret
> 2) ZFlag or CFlag re/set on error
> 2) must return 0 not0 as info in a register,
> respectively for low/hi bound overflow
> or viceversa
>
> ideas,improvements ?
>
> ..is_inbound:
> mov eax,value
> mov ecx,MAX_BOUND
> cmp eax,MIN_BOUND
> sbb edx,edx
> cmp ecx,eax
> not edx
> sbb ecx,ecx
> xor ecx,edx
> jz .err
>

Coming from the bottomless dark space...of my brain
a new version, 5 instructions 2 register

ZF=0 ok
ZF=1 not in range

if ZF=1  not in range
  CF=1 low bound error
  CF=0 hi bound error

..is_inbound:
   mov eax,value
   cmp eax,MIN_BOUND
   sbb ecx,ecx
   cmp eax,MAX_BOUND+1
   adc ecx,0
   ret 0

Cheers

-- 

  .:hopcode[marc:rainer:kranz]:.
  x64 Assembly Lab
  http://sites.google.com/site/x64lab
0
Reply hopcode 3/25/2011 1:26:47 AM

"robertwessel2@yahoo.com" <robertwessel2@nospicedham.yahoo.com> writes:

> On Mar 24, 5:22=A0pm, hopcode <hopc...@nospicedham.nullnichtsnada.com>
> wrote:
>> Hi All,
>> my little snippet to check if unsigned value is in bounds
>> (inclusive), 8 instructions 3 registers. i have another version too,
>> 8 instrs. *2 register* but it is not much compiler friendly.
>> Also, conditions:
>>
>> 1) EAX original value on ret
>> 2) ZFlag or CFlag re/set on error
>> 2) must return 0 not0 as info in a register,
>> =A0 =A0 respectively for low/hi bound overflow
>> =A0 =A0 or viceversa

Do you really need the third point?
If so, are your values signed or unsigned (i.e., is -7/0xfffffff8 a bound
underflow for the range [3..5], or an overflow)?

It's so much easier without that requirement :)

>>
>> ideas,improvements ?
>>
>> .is_inbound:
>> =A0 mov eax,value
>> =A0 mov ecx,MAX_BOUND
>> =A0 cmp eax,MIN_BOUND
>> =A0 sbb edx,edx
>> =A0 cmp ecx,eax
>> =A0 not edx
>> =A0 sbb ecx,ecx
>> =A0 xor ecx,edx
>> =A0 jz .err
>
>
> How about:
>
>  mov ebx,eax
>  sub ebx,MIN_BOUND
>  cmp ebx,(MAX_BOUND-MIN_BOUND+1)
>  setae bl
>  movzx ebx,bl

Or equivalently:
   lea ebx,[eax - MIN_BOUND]
   cmp ebx,(MAX_BOUND - MIN_BOUND)
   sbb ebx, ebx

However, now that I reread the specification, that's not what's asked for
in the returned register. It should say whether the value is below or abo=
ve
the range (if outside).


For that (assuming unsigned values), how about:
  cmp eax, MIN_BOUND
  sbb ebx, ebx           // ebx =3D 0 if MIN_BOUND <=3D eax, -1 if eax < =
MIN_BOUND
  cmp eax, MAX_BOUND + 1
  adc ebx, ebx           // ebx =3D 0 if MAX_BOUND < eax
                         //       -1 if MIN_BOUND <=3D eax <=3D MAX_BOUND
                         //       -2 if eax < MIN_BOUND
  cmp ebx, -1            // Z flag set if inside range.
                         // ebx =3D=3D 0 (and C flag set) if above range
                         // ebx =3D=3D -2 (and C flag clear) if below ran=
ge.

Now, the latency of sbb and adc aren't exactly stellar (2 cycles each on =
a
Core 2) and they won't parallelize. Using setae instead of sbb might=20
be faster, i.e.,

  cmp eax, MIN_BOUND
  setae ebx              // bl =3D 1 if MIN_BOUND <=3D eax, 0 if eax < MI=
N_BOUND
  cmp eax, MAX_BOUND + 1
  adc bl, bl             // bl =3D 0 if MAX_BOUND < eax
                         //      2 if MIN_BOUND <=3D eax <=3D MAX_BOUND
                         //      1 if eax < MIN_BOUND
  cmp bl, 2              // Z flag set if inside range.
                         // ebx =3D=3D 0 if above range
                         // ebx =3D=3D 1 if below range.


Best of luck
/L =20
--=20
Lasse Reichstein Holst Nielsen
 DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.ht=
ml>
  'Faith without judgement merely degrades the spirit divine.'
0
Reply Lasse 3/25/2011 5:42:36 PM

Il 25.03.2011 18:42, Lasse Reichstein Nielsen ha scritto:
> "robertwessel2@yahoo.com"<robertwessel2@nospicedham.yahoo.com>  writes:
>
>> On Mar 24, 5:22 pm, hopcode<hopc...@nospicedham.nullnichtsnada.com>
>> wrote:
>>> Hi All,
>>> my little snippet to check if unsigned value is in bounds
>>> (inclusive), 8 instructions 3 registers. i have another version too,
>>> 8 instrs. *2 register* but it is not much compiler friendly.
>>> Also, conditions:
>>>
>>> 1) EAX original value on ret
>>> 2) ZFlag or CFlag re/set on error
>>> 2) must return 0 not0 as info in a register,
>>>      respectively for low/hi bound overflow
>>>      or viceversa
>
> Do you really need the third point?
> If so, are your values signed or unsigned (i.e., is -7/0xfffffff8 a bound
> underflow for the range [3..5], or an overflow)?
>
> It's so much easier without that requirement :)
>
>>>
>>> ideas,improvements ?
>>>
>>> .is_inbound:
>>>    mov eax,value
>>>    mov ecx,MAX_BOUND
>>>    cmp eax,MIN_BOUND
>>>    sbb edx,edx
>>>    cmp ecx,eax
>>>    not edx
>>>    sbb ecx,ecx
>>>    xor ecx,edx
>>>    jz .err
>>
>>
>> How about:
>>
>>   mov ebx,eax
>>   sub ebx,MIN_BOUND
>>   cmp ebx,(MAX_BOUND-MIN_BOUND+1)
>>   setae bl
>>   movzx ebx,bl
>
> Or equivalently:
>     lea ebx,[eax - MIN_BOUND]
>     cmp ebx,(MAX_BOUND - MIN_BOUND)
>     sbb ebx, ebx
>

Hi Lasse,
very nice. it's a pity it doesnt return the hi/low
trenspassed bound on error.


> However, now that I reread the specification, that's not what's asked for
> in the returned register. It should say whether the value is below or above
> the range (if outside).
>
>
> For that (assuming unsigned values), how about:
>    cmp eax, MIN_BOUND
>    sbb ebx, ebx           // ebx = 0 if MIN_BOUND<= eax, -1 if eax<  MIN_BOUND
>    cmp eax, MAX_BOUND + 1
>    adc ebx, ebx           // ebx = 0 if MAX_BOUND<  eax
>                           //       -1 if MIN_BOUND<= eax<= MAX_BOUND
>                           //       -2 if eax<  MIN_BOUND
>    cmp ebx, -1            // Z flag set if inside range.
>                           // ebx == 0 (and C flag set) if above range
>                           // ebx == -2 (and C flag clear) if below range.
>
> Now, the latency of sbb and adc aren't exactly stellar (2 cycles each on a
> Core 2) and they won't parallelize. Using setae instead of sbb might
> be faster, i.e.,

Yes, according latency table SETCC is on my 45nm Core faster
than sbb/adc.

>
>    cmp eax, MIN_BOUND
>    setae ebx              // bl = 1 if MIN_BOUND<= eax, 0 if eax<  MIN_BOUND
>    cmp eax, MAX_BOUND + 1
>    adc bl, bl             // bl = 0 if MAX_BOUND<  eax
>                           //      2 if MIN_BOUND<= eax<= MAX_BOUND
>                           //      1 if eax<  MIN_BOUND
>    cmp bl, 2              // Z flag set if inside range.
>                           // ebx == 0 if above range
>                           // ebx == 1 if below range.
>

Yesterday i posted something similiar (see post below):

..is_inbound:
   mov eax,value
   cmp eax,MIN_BOUND
   setae cl
   cmp eax,MAX_BOUND+1
   sbb cl,0

but the reason i prefer sbb/adc rather than
setcc, is a merely logic one; here we have
a redundancy on infos. CL has the error bound
as like as from the Carry.

Cheers,

-- 

  .:hopcode[marc:rainer:kranz]:.
  x64 Assembly Lab
  http://sites.google.com/site/x64lab
0
Reply hopcode 3/26/2011 12:24:03 AM

5 Replies
233 Views

(page loaded in 0.082 seconds)

5/4/2013 2:27:23 PM


Reply: