Hi, just a quick question: does anyone know how to saturate a numeric value in a register, to the range 0-255? I don't want to use MMX or SSE stuff. Thanks in advance! :U
Quote from: QvasiModo on May 17, 2005, 08:21:13 PM
Hi, just a quick question: does anyone know how to saturate a numeric value in a register, to the range 0-255? I don't want to use MMX or SSE stuff. Thanks in advance! :U
add al, someValue
jnc noSaturate
or al, $ff
noSaturate:
Okay, it's ugly...
In the dim recesses of my mind, I seem to recall that there was some tricky code to replicate the carry flag through all the bits of a register. But for the life of me I can't remember it now. Maybe someone else can share?
Cheers,
Randy Hyde
I use
add eax, someValue
mov ebx,-1
cmovc eax,ebx
WHat is cmovc?
It is the same like MOV, but Conditional. CMOVC means MOV if CARRY, CMOVA means MOV if ABOVE etc.
For more, check for instance
http://www.x86.org/secrets/opcodes/cmov.htm
BTW, you have to use .686 directive in your header.
Thanks for the link MazeGen. I actually had it in my older links but I had completely forgotten it.
So perhaps Randall was trying to remember SBB AL,AL or perhaps SALC.
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.686 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\kernel32.lib
include \masm32\macros\macros.asm
; Sets AL=FFh if CF=1, or AL=00 if CF=0
; Unlike SBB AL,AL does not affect the flags
; All Intel processors, AMD ??
salc MACRO
db 0D6h
ENDM
SALC EQU salc
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
.code
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
xor eax,eax
clc
salc
print uhex$(eax)
print chr$(13,10)
xor eax,eax
stc
salc
print uhex$(eax)
print chr$(13,10)
xor ebx,ebx
mov eax,1
clc
cmovc ebx,eax
print uhex$(ebx)
print chr$(13,10)
xor ebx,ebx
mov eax,1
stc
cmovc ebx,eax
print uhex$(ebx)
print chr$(13,10)
mov eax,1
xor ebx,ebx
cmovnz ebx,eax
print uhex$(ebx)
print chr$(13,10)
mov eax,1
xor ebx,ebx
cmovz ebx,eax
print uhex$(ebx)
print chr$(13,10)
fcmovb st(0),st(1) ; Just to see if supported by MASM
mov eax,input(13,10,"Press enter to exit...")
exit
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Result on P3:
00000000
000000FF
00000000
00000001
00000000
00000001
My AMD K5 supports SALC but chokes on the CMOV_.
Quote from: MazeGen on May 18, 2005, 06:12:06 AM
I use
add eax, someValue
mov ebx,-1
cmovc eax,ebx
The cmovx and setxx instructions are very handy for saving short jumps.
You could even save an instruction in this code (and keep ebx free) by having a variable that's set to 0xffffffff (e.g. -1). Call it neg_one. Then the code looks like
add eax,someValue
cmovc eax,neg_one
Quote from: MichaelW on May 18, 2005, 08:41:49 AM
My AMD K5 supports SALC but chokes on the CMOV_.
Do you mean it does not recognize the opcode?
Sorry, 'choked' was not a good choice for an international forum. I meant it faulted. I am assuming it was an invalid op-code fault, but I didn't actually check.
If you don't mind the flags being affected, these should work:
mov al,somevalue
sbb al,al
mov eax,somevalue
sbb eax,eax
Michael your code is almost there, but it'll result in either 0 or 0xFF, not a saturated value.
add al, someValue
sbb ah, ah
or al, ah
Mirno
So cmovx is like the second bit of cmpxchg? (emphasise like)?
Aero, it's a conditional move. In other words the move only occurs if the condition is met.
Mirno
Aero:
cmovc eax,ebx
is equal to
jnc @f
mov eax,ebx
@@:
and also equal to
.IF CARRY?
mov eax,ebx
.ENDIF
MichaelW: the site is long time dead unfortunately :(
;on entry eax= the value to saturate
test eax,&hffffff00 ;check range
setz bh ;create saturation masks
sets bl
dec bh
dec bl
or al,bh ;apply masks to range limit al to 0-FF
and al,bl
;al now = the 0-255 saturated value.
Paul.
Quote from: MichaelW on May 18, 2005, 08:41:49 AM
Thanks for the link MazeGen. I actually had it in my older links but I had completely forgotten it.
So perhaps Randall was trying to remember SBB AL,AL or perhaps SALC.
Definitely not SALC, as this is an undocumented opcode that isn't available on all processors.
There was a trick with SBB, it was something along the lines of
mov ah, 0
add al, somevalue
sbb ah, ah
or al, ah
But I don't remember if this was the exact sequence.
It is worth pointing out that this trick only works for unsigned values. If you want to clip at -128 and +127, this isn't the code for you. In such a case, the conditional move instructions are the best bet (but only valid on PPro's and later, and a few other processors; though I suspect that we're finally to the point we can assume we can use these instructions, even though I personally stick to 486/Pentium instruction sets for most of my coding).
Cheers,
Randy Hyde