Richard Russell wrote:
> On 11 Apr, 08:41, Terje Mathisen <spamt...@[EMAIL PROTECTED]
> wrote:
>> What's wrong with the obvious approach?
>>
>> add al,dl ; Carry set if it overflows!
>> sbb al,al ; AL = 0xff if overflow
>> or dl,al ; Turns any overflow into 0xff
>
> Very neat. Now, what about the signed case (saturating at +127 or
> -128)? The best I've managed is:
>
> add al,dl ; Signed addition
> jno ok ; Jump if no overflow
> sbb al,al ; al is 0x00 or 0xff
> xor al,127 ; Saturate to -128 or +127
> ok:
That is pretty neat code, I like it!
The generic way to handle arbitrary clamping values is something like
this:
;; if ( x < MIN) x = MIN;
;; else if (x > MAX) x = MAX;
cmp eax,MIN ; Carry set if (eax < MIN)
sbb ebx,ebx ; EBX = -1 if underflow
cmp eax,MAX+1 ; Carry clear if (eax > MAX)
adc ebx,ebx ; Merge carry with previous result
At this point there are 4 possible combinations:
second 0 second 1
first 0 OVFL OK
first 1 impossible UNDFL
These four corresponds to EBX = 0, 1, -2, -1 which means that it is
possible to store the original value into a four-element table, then use
EBX to retrieve either the same value back or the clamped results:
cmp eax,MIN ; Carry set if (eax < MIN)
sbb ebx,ebx ; EBX = -1 if underflow
cmp eax,MAX+1 ; Carry clear if (eax > MAX)
adc ebx,ebx ; Merge carry with previous result
mov clamp_table[4], eax
mov eax,clamp_table[ebx*4+8]
This code will only be faster than the naive approach if clamped values
are both common and non-predictable, if this isn't true then it is much
better to simply use the generic C-style if/else if/else approach!
Terje
--
- <Terje.Mathisen@[EMAIL PROTECTED]
>
"almost all programming can be viewed as an exercise in caching"


|