News:

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

a shift (shl shr) on a 64 bits constants

Started by ToutEnMasm, June 11, 2009, 06:13:05 AM

Previous topic - Next topic

sinsi

Light travels faster than sound, that's why some people seem bright until you hear them.

dedndave

change the exponent by 1 - don't need an FPU for that

raymond

Quote from: ToutEnMasm on June 13, 2009, 04:57:30 AM
Hello,
Is it possible to made a shift right with the FPU ?

Simple. One additional opcode. However, the stored integer would be rounded according to the setting of the rounding control of the FPU (if not modified, the default is to round to the nearest integer). For example, 0A2345Dh shifted right by 4 with the FPU would return 0A2346h, as compared to shifting with the shr instruction which would return 0A2345h.

finit    ;should be done once at start of program
         ;to insure the full 64 bits for the mantissa

fild count    ;should obviously be less than 63
fchs          ;make the count negative
fild aqword   ;declared as a qword
fscale
fistp aqword  ;replaces the previous value by the shifted one
fstp st       ;cleanup
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

jj2007

Of course - I had not thought of that. Thanks, Raymond. Here are the correct macros using the FPU:

COMMENT @ Usage:
.data
MyQw4 dq 12345678h
MyCt = 8
.code
shl64f MyQw4, MyCt
print xqword$(MyQw4), 13, 10 ; immediate
shr64f MyQw4, MyCt
print xqword$(MyQw4), 13, 10

mov ecx, MyCt
shl64f MyQw4, ecx ; passed as dword
print xqword$(MyQw4), 13, 10
mov ecx, MyCt
shr64f MyQw4, cl ; passed as byte
print xqword$(MyQw4), 13, 10, 10

@
shl64f MACRO aqword, count
LOCAL oa, tmp$
  oa = (opattr count) AND 127
  if oa eq 36 ;; immediate
push count
  else
tmp$ SUBSTR <count>, 2
ifidni tmp$, <L>
movzx eax, count
push eax
else
push count
endif
  endif
  fild dword ptr [esp] ; should obviously be less than 63
  fild aqword ; declared as a qword
  fscale
  fistp qword ptr aqword ; replaces the previous value by the shifted one
  fstp st       ;cleanup
  pop eax
ENDM

shr64f MACRO aqword, count
LOCAL oa, tmp$
  oa = (opattr count) AND 127
  if oa eq 36 ;; immediate
push -count
  else
tmp$ SUBSTR <count>, 2
ifidni tmp$, <L>
movzx eax, count
neg eax
push eax
else
neg count
push count
endif
  endif
  fild dword ptr [esp] ;; should obviously be less than 63
  fild aqword ;; declared as a qword
  fscale
  fistp qword ptr aqword ;; replaces the previous value by the shifted one
  fstp st      ;; cleanup
  pop eax
ENDM


Nonetheless, it seems faster and easier without the FPU.

ToutEnMasm

Hello,
With the fpu , a shift need to be a division (right) or a multiply (left) by a power of 2.

Divider = 1 * 2(POWER of nshift)
then
result = Number /divider

the first work is to transform the number of shift in an operator ( divider or a multiplicater).
With two shift    operator = 4 that is 1 shif 2
Those give the formula for the operator .operator = 2 shift (number of shift)
This need to be verify.


jj2007

#35
Quote from: ToutEnMasm on June 14, 2009, 07:42:25 AM
With the fpu , a shift need to be a division (right) or a multiply (left) by a power of 2.

FSCALE

Scales by powers of 2 by calculating the function Y = Y * 2^X. X is the scaling factor taken from ST(1), and Y is the value to be scaled from ST. The scaled result replaces the value in ST; the scaling factor remains in ST(1). If the scaling factor is not an integer, it will be truncated toward zero before the scaling.

Nonetheless, a 64 bit shift should be done with shld, not with the FPU - full code attached.


; simplest version:
shl64 MyQw3, 24 ; pass qword and immediate shift count
print xqword$(MyQw3), 9, "shl64 24", 13, 10
shr64 MyQw3, 24 ; back to original value
print xqword$(MyQw3), 9, 9, "shr64 24", 13, 10, 10, "Shift 40 tests:", 13, 10

shiftLeft = 40
shiftRight = 40
print "Original value: ", 13, 10
print xqword$(MyQw1), 13, 10

mov eax, offset MyQw1 ; pass ptr to qword in a register
shl64 eax, shiftLeft
print xqword$(MyQw1), 13, 10
mov eax, offset MyQw1
shr64 eax, shiftRight
print xqword$(MyQw1), 13, 10

mov ecx, shiftLeft
shl64 MyQw2, cl ; pass qword directly, shiftcount in byte register
print xqword$(MyQw2), 13, 10
mov ecx, shiftRight
shr64 MyQw2, cl
print xqword$(MyQw2), 13, 10

shl64 offset MyQw3, shiftLeft ; pass offset qword, shiftcount as immediate
print xqword$(MyQw3), 13, 10
shr64 offset MyQw3, shiftRight
print xqword$(MyQw3), 13, 10, 10



[attachment deleted by admin]

ToutEnMasm

Hello,
This one is without problem
shift 0 to 63

here 48 shift return 1 , if greater return 0

Quote
MyQw   qword  0000FFFFFFFF0000h
NumberOfShit equ 48   

   mov eax,NumberOfShit
   push eax
   fild dword ptr [esp]   
   pop eax
   fld1   
   fscale
   fild qword ptr MyQw
   fdiv st(0),st(1)
   fistp qword ptr MyQw
   finit      

dedndave

QuoteNumberOfShit equ 48   

   mov eax,NumberOfShit
i found a problem Yves
where's the "f" ?

jj2007

Quote from: dedndave on June 15, 2009, 08:06:09 AM
QuoteNumberOfShit equ 48   

   mov eax,NumberOfShit
i found a problem Yves
where's the "f" ?

Oh Shift!!

(but it's not the only problem...)

ToutEnMasm


If you want,you can change it by NombreDeDecalages.
              :P

dedndave

that's ok - lol
i knew what you meant - good thing the thread title is right, though
i used to live in a small desert town named Bouse, Arizona - lol - Yves will get that

jj2007

#41
Quote from: ToutEnMasm on June 15, 2009, 07:46:50 AM
Hello,
This one is without problem
shift 0 to 63

I have tested it with other numbers and get strange results:

1234567812345678  original value
3456781234567800  shl64 MyQw1, 8
0012345678123456  fpu, ToutEnMasm

1234567812345678  original value
5678123456780000  shl64 MyQw1, 16
0000123456781234  fpu, ToutEnMasm

1234567812345678  original value
7812345678000000  shl64 MyQw1, 24
0000001234567812  fpu, ToutEnMasm

1234567812345678  original value
1234567800000000  shl64 MyQw1, 32
8000000000000000  fpu, ToutEnMasm

1234567812345678  original value
3456780000000000  shl64 MyQw1, 40
8000000000000000  fpu, ToutEnMasm

1234567812345678  original value
5678000000000000  shl64 MyQw1, 48
8000000000000000  fpu, ToutEnMasm

1234567812345678  original value
7800000000000000  shl64 MyQw1, 56
8000000000000000  fpu, ToutEnMasm


Initially, the algo does a right shift, then it gets stuck...  :(

Testbed attached, including a significant change to the shl64 and shr64 macros: You can now optionally supply a destination qword.

Quoteshl64 MyQw1, 3      ; qword, immediate counter

   mov ecx, 3
   shl64 MyQw1, cl      ; qword, reg8 counter

   mov edx, offset MyQw1   ; ptr to src in edx
   shl64 edx, 3      ; ptr, imm8 counter

   mov eax, offset MyQw1   ; ptr to src in eax
   mov ecx, 3
   shl64 eax, cl      ; ptr, reg8 counter

   shl64 MyQw1, 3, MyQwRes   ; result to MyQwRes

   mov eax, offset MyQw1   ; ptr to src in eax
   mov ecx, 3
   shl64 eax, cl, MyQwRes   ; result to MyQwRes


EDIT: shl in example replaced with shr, fpu stack saved - see new attachment

[attachment deleted by admin]

ToutEnMasm


Bad test.
The method couldn't failed ecxept if the FPU isn't in a normal state.Perhaps  a finit missing before or other thing like bad print.
I have not the same results as you.
Try also to compare a right shift with a right shift,this will be more clear.

jj2007

Quote from: ToutEnMasm on June 15, 2009, 03:16:51 PM

Bad test.
The method couldn't failed ecxept if the FPU isn't in a normal state.Perhaps  a finit missing before or other thing like bad print.
I have not the same results as you.
Try also to compare a right shift with a right shift,this will be more clear.

OK, I replaced shl64 with shr64, see attachment above. Your code still fails, simply because it trashes the FPU. You have to clean up:
   fistp qword ptr MyQwRes
   fstp st
   fstp st


With this little change, it works correctly, but it needs 32 instead of 25 bytes and is a lot slower, too.

Testing qword shift macros:

1234567812345678  original value
0012345678123456  shr64 MyQw1, 8, MyQwRes
0012345678123456  fpu, ToutEnMasm

1234567812345678  original value
0000123456781234  shr64 MyQw1, 16, MyQwRes
0000123456781234  fpu, ToutEnMasm

1234567812345678  original value
0000001234567812  shr64 MyQw1, 24, MyQwRes
0000001234567812  fpu, ToutEnMasm

1234567812345678  original value
0000000012345678  shr64 MyQw1, 32, MyQwRes
0000000012345678  fpu, ToutEnMasm

1234567812345678  original value
0000000000123456  shr64 MyQw1, 40, MyQwRes
0000000000123456  fpu, ToutEnMasm

1234567812345678  original value
0000000000001234  shr64 MyQw1, 48, MyQwRes
0000000000001234  fpu, ToutEnMasm

1234567812345678  original value
0000000000000012  shr64 MyQw1, 56, MyQwRes
0000000000000012  fpu, ToutEnMasm

Code sizes:
fpu     32
alu     25

ToutEnMasm

Sorry , it is your code who is responsible .He leave the fpu in an undeterminate state.Add FINIT before the call of my routine,and all wil be ok,except for yours.The end of my routine is a finit,could'nt trashes anyting,surely a bad copy.