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
; [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
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.
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
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
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
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
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.