News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

maxium/minimum value with wrap around

Started by kwadrofonik, March 15, 2007, 05:14:51 PM

Previous topic - Next topic

kwadrofonik

How are the fine folks at masmforum today? I have a question which I'm sure you brainiacs have an answer for ;)

I know MMX allows you to define a maximum and minimum result causing a wraparound. Just wondering if anyone as a solution to this with general purpose registers without conditional jumps?

psuedocode:

1. add value2 to value1. if value1 is greater than 6291456 (110 0000 0000 0000 0000 0000), then value1 = value1 - 6291456
2. subtract value2 from value1. if value1 is less then 0, then value1 = 6291456 - value1




ramguru


; [a,b] - register; returns [edx = min]
min MACRO a, b
mov    edx, a
sub    edx, b
sar    edx, 31
and    a, edx
xor    edx, -1
and    edx, b
or     edx, a
ENDM
; [a,b] - register; returns [edx = max]
;max MACRO a, b
mov    edx, b
sub    edx, a
sar    edx, 31
and    a, edx
xor    edx, -1
and    edx, a
or     edx, b
ENDM


kwadrofonik

Thanks ramguru. I'm sorry but I don't understand what your code does...

a = 5
b = 7

mov      edx, a     ;edx = 5
sub      edx, b     ;edx = -2
sar      edx, 31    ;edx = 1
and      a, edx     ;a = 0001
xor      edx, -1    ;edx = 11111111111111111111111111111110
and      edx, b     ;edx = 110
or       edx, a     ;edx = 111

edx = 7?

mov        edx, b   ;edx = 7
sub        edx, a   ;edx = 2
sar        edx, 31  ;edx = 0
and        a, edx   ;a = 0
xor        edx, -1  ;edx = -1
and        edx, a   ;edx = 0
or         edx, b   ;edx = 7

edx = 7


Tell me, do you see any problem with doing this?



;Addition
mov        eax, a
mov        edx, b

add        eax, edx

cmp        eax, 6291457     ;if eax <= 6291456 then CF = 1
cmc                         ;invert flag
sbb        ecx, ecx         ;                    if CF = 1, ecx = -1 else ecx = 0
and        ecx, 6291456     ;apply mask,         if CF = 1, ecx = 6291456 else ecx = 0
sub        eax, ecx

;subtraction
mov        eax, a
mov        edx, b

sub        eax, edx         ;if eax < edx then CF = 1

sbb        ecx, ecx         ;                  if CF = 1, ecx = -1 else ecx = 0
and        ecx, 6291456     ;apply mask,       if CF = 1, ecx = 6291456 else ecx = 0
add        eax, ecx


Thanks.

ramguru

Sorry that I misled you, it's not my fault, not my code, those fu**ing books lie!! And I thought I had a valuable snippet, the author of that assembly book should suffer!!!!
Regarding your code, sorry I'm not the right person to help with this thing  :green

Mirno

For the general case:
((val - min) % (max - min)) + min

Use div for the modulo (remainder in edx).

For specific cases you may be able to work out some optimised version.

Mirno

TNick

To obtain the minimum:
a = min (c, b) <=> a = eax, c = ecx, b = ebx
mov  edx,  -1
cmp  ecx,  ebx
sbb  eax,  eax
adc  edx,  0
and  eax,  ecx
and  edx,  ebx
or   eax,  edx

eax now has the minimum value between ecx and ebx

Nick

dsouza123

There is a problem with the original psuedocode.

The second step

Subtract value2 from value1
If value1 is less than 0
then value1 = 6291456 - value1

It will cause value1 to exceed the max value
when the result of the subtraction is a negative value.

value1 = 2
value2 = 5

value1 = -3 = 2 - 5
it is negative so do value1 = 6291456 - value1

value1 6291459 = 6291456 - -3
so value1 exceeds the max value


What would work is

2. subtract value2 from value1.    if value1 is less then 0,   then value1 = value1 + 6291456



Tedd

Quoteadd value2 to value1. if value1 is greater than 6291456 (110 0000 0000 0000 0000 0000), then value1 = value1 - 6291456

WRAP equ 600000h  ;6291456

mov eax,value1  ;a
mov edx,value2  ;b

add eax,edx     ;eax = a+b
cmp eax,WRAP    ;CF = (a+b > WRAP) ? 0 : 1
sbb ecx,ecx     ;ecx = (a+b > WRAP) ? 0 : -1
not ecx         ;ecx = (a+b > WRAP) ? -1 : 0
and ecx,WRAP    ;ecx = (a+b > WRAP) ? WRAP : 0

sub eax,ecx     ;eax = a+b - 0      } if not wrap
                ;    = a+b - WRAP   } if wrap




Quotesubtract value2 from value1. if value1 is less then 0, then value1 = 6291456 - value1
not quite an accurate description (as dsouza pointed out), but I know what you meant..

mov eax,value1  ;a
mov edx,value2  ;b

sub eax,edx     ;eax = a-b
sbb ecx,ecx     ;ecx = (a-b < 0) ? 0 : -1
and ecx,WRAP    ;ecx = (a-b < 0) ? 0 : WRAP

add eax,ecx     ;eax = (a-b) + 0    } if (a-b < 0)
                ;    = (a-b) + WRAP } if (a-b >= 0)



in both cases: eax is value1, edx is value2, and the result is provided in eax at the end of each code fragment.
No snowflake in an avalanche feels responsible.