News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

How to convert signed dword or qword value to negative float value?

Started by fearless, August 21, 2024, 10:01:19 PM

Previous topic - Next topic

fearless

I'm looking for a way to convert a value to a float. The float value ranges I require are from -1.0 to 1.0. If i have a dword value that represents it as -100 to 100, how to convert the value to a float?

For example if I have the positive value like 63, i know i can check if its positive with .IF sdword ptr eax > 0
then i can load that into fpu with something like:

LOCAL dw100:DWORD
LOCAL fValue:REAL4

mov dw100, 100
finit
fwait
fild dwValue ; 63
fild dw100
fdiv
fstp fValue ; value is 0.63


I thought about negating the dwValue with neg, and then loading and dividing but i dont think that would work. Maybe multiplying the fValue by -1.0 would work? if < 0, then fld FP4(-1.0), fmul perhaps?

Maybe someone who has more experience with fpu instructions will know a way to achieve what im looking for. Thanks.

C3

Quote from: fearless on August 21, 2024, 10:01:19 PMI'm looking for a way to convert a value to a float. The float value ranges I require are from -1.0 to 1.0. If i have a dword value that represents it as -100 to 100, how to convert the value to a float?

For example if I have the positive value like 63, i know i can check if its positive with .IF sdword ptr eax > 0
then i can load that into fpu with something like:

LOCAL dw100:DWORD
LOCAL fValue:REAL4

mov dw100, 100
finit
fwait
fild dwValue ; 63
fild dw100
fdiv
fstp fValue ; value is 0.63


I thought about negating the dwValue with neg, and then loading and dividing but i dont think that would work. Maybe multiplying the fValue by -1.0 would work? if < 0, then fld FP4(-1.0), fmul perhaps?

Maybe someone who has more experience with fpu instructions will know a way to achieve what im looking for. Thanks.


Are you sure you need to do it with the FPU? I searched Intel Architecture manual and found this: CVTSI2SS—Convert Doubleword Integer to Scalar Single Precision Floating-Point Value. Would this be possible to use? Supports SSE and AVX instruction set. I'll try to do code that does what you are looking for.

Cheers, Petter

HSE

Hi fearless,
    mov dw100, 100
    finit
    fwait
    .if dwValue == 0
        fldz
    .else
        fild dwValue ; 63
        fidiv dw100
    .endif
    fstp fValue ; value is 0.63

I don't know magic  :biggrin:  :biggrin:
Equations in Assembly: SmplMath

daydreamer

I suggest you check raymonds fpu tutorial and stick to fpu opcodes for change sign of float instead of Neg
Fmul by 0.01 better than fdiv no divide by zero and faster
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

HSE

Equations in Assembly: SmplMath

fearless

Thanks to all.

    mov dw100, 100
    finit
    fwait
    mov eax, dwValue
    .if eax == 0
        fldz
    .elseif sdword ptr eax > 0 ; positive
        fild dwValue ; 63
        fidiv dw100
        ; or this instead
        fild dwValue
        fld 0.01
        fmul
    .else ; negative
        ; will this give a dwValue of -63 as -0.63?
        fild dwValue
        fld 0.01
        fmul
        fld -1.0
        fmul
    .endif
    fstp fValue ; value is 0.63

Will the above work with a value of -63 resulting in a float value of -0.63?

HSE

There is no need to check sign if you want -0.63.

FPU dont' load inmediate values nor registers.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc
    .data
        dwValue sdword -63

    .code

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

start proc
    LOCAL dw100:DWORD
    LOCAL fValue  : REAL8
    LOCAL finv100 : real8 

    finit
    fwait

; Not frequent

    mov dw100, 100
    .if dwValue == 0
        fldz
    .else
        fild dwValue ; 63
        fidiv dw100
    .endif   
    fstp fValue ; value is 0.63
    print real8$(fValue),13,10,13,10

; Frequent

    ; at begining

    ;---------------------------------

    fld1                ; in case you want a different base
    fidiv dw100     
    fstp finv100

    ; repeated

    fild dwValue
    fmul finv100
    fstp fValue ; value is 0.63

    print real8$(fValue),13,10,13,10

    ;---------------------------------

    fild dwValue        ; just or 1/100 
    fmul FP8(0.01)     
    fstp fValue ; value is 0.63

    print real8$(fValue),13,10,13,10

    inkey

    invoke ExitProcess,0

    ret
start endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Equations in Assembly: SmplMath

jj2007

include \masm32\include\masm32rt.inc

.data
dwValue    dd 63
div100    REAL4 0.01
fValue        REAL8 ?

.code
start:
  finit        ; not really needed
  fwait        ; not really needed
  int 3
  fild dwValue ; 63
  fmul div100        ; much faster than div
  fstp fValue    ; value is 0.63
  exit

end start

P.S., the branch is not needed:
    .if eax == 0
        fldz
    .elseif sdword ptr eax > 0 ; positive
        fild dwValue ; 63

InfiniteLoop

Too difficult to redo from scratch without reading my old notes:

S_52 REAL8 1.5 * 2^52
F_52 REAL8 1.0 * 2^52
S_84_63 REAL8 1.0 * 2^84 + 1.0 * 2^63
S_84_63_52 REAL8 2^84 + 2^63 + 2^52

;X [-2^51,2^51]
;if X +VE -> no effect, if x -VE, carry 1 into sign bit
ConvertInt52ToDouble proc
vmovq xmm0,rcx
vmovsd xmm1,real8 ptr [S_52]
vpaddq xmm0,xmm0,xmm1
vsubsd xmm0,xmm0,xmm1
ret
ConvertInt52ToDouble endp

;X [-2^63-1,2^63-1]
;if X +VE, high part * 2^84 + 2^63 - 2^84+2^63+2^52 + low part * 2^52
;if X -VE, 1:000000000 xor 1:111111xxxxxx => 0:111111111xxxxxxx - 1:0000000000000000 => - 2^84*0:0000000000000001
ConvInt64ToDouble proc
vmovq xmm0,rcx
vmovsd xmm2,real8 ptr [F52]
vmovsd xmm3, real8 ptr [S_84_63]
vmovsd xmm4,real8 ptr [S_84_63_52]
vpblendd xmm2,xmm0,xmm2,10101010b  ;low part * 2^52
vpsrlq xmm1,xmm0,32  ;high part
vpxor xmm1,xmm1,xmm3
vpsubsd xmm1,xmm1,xmm4
vpaddsd xmm0,xmm1,xmm2
ret
ConvInte64ToDouble endp

NoCforMe

Scratching my head here; if you want to convert a (signed integer) value to a float, then why not just do
    fild <integer value>
    fstp <float value>
?

Your integer value can be either positive or negative, right?
Then the resulting floating-point value will also be positive or negative.
I don't see what the problem is here.

Or do you want to result to always be negative, which is what your question implies?
Assembly language programming should be fun. That's why I do it.