Hi Lenin,
The last bit (the most significant bit) in a floating point number determines the number's sign (bit 31 for single-precision and bit 63 for double-precision). It is set if the number is negative and clear if the number is positive. to get absolute value of a given operand we need to perfrom a logocal AND on the number to clear its most significant bit.

something like:

``mov eax, 0x7FFFFFFFmovd xmm2, eaxpand xmm1, xmm2``

pand operates on MMX registers and on XMM1 and XMM2 registers (no other XMM registers are supported). the above assumes that the number to AND is held inside the xmm1 register.

Hi roticv,
Where? :| If it's helpful to anyone then you're free to use it wherever you wish :) This is a 'community' after all ;)
Posted on 2005-12-06 15:05:25 by ti_mo_n
Hey, there's no need to clear the bit in the xmm0 register, since it's already stored in ecx, so is the sign bit the same in 32bit regiters (bit 31)?

I tried doing:
``    cvttss2si ecx, xmm1    and       ecx, 7FFFFFFEh``

But got -1.2146493648 instead of -1.99
Posted on 2005-12-06 16:18:18 by Lenin
well yes - if you have a FP-value in a GP register, so you can simply AND it.

as for your problem: you're trying to AND an integer. integers are stored in 2's-complement arithmetic. use a "neg eax" instruction to make a negative value positive and a positive value negative. you can first check the value's most significant bit to see if it's negative

``or eax, eaxjns notnegneg eaxnotneg:``

no need for SSE here, but you can avoid using branches if you AND it while it's still FP inside a XMM reg ;)

the above changes a negative value to positive and does nothing with a positive one. ask if you don't know how it works ;)
Posted on 2005-12-06 16:30:33 by ti_mo_n
Thanks :)
Posted on 2005-12-06 16:53:20 by Lenin
I spent almost an hour thinking on how to solve that problem (1.900000) without having to convert the number into a string, but just then I realised "hey, I'm already converting the number into a string :P", then it got a lot easyer... I came up with this:

``FloatToAscii proc float:DWORD, lpOut:DWORD.data    format  db "%d.%d",0    million REAL4 1000000.0.code    movss     xmm0, float   ;xmm0 = float    cvttss2si eax, float    ;eax = integral part of 'float' stored as integer    cvtsi2ss  xmm1, eax     ;xmm1 = integral part of float stored as 'float'    subss     xmm0, xmm1    ;xmm1 = fractional part of 'float'        mulss     xmm0, million    cvttss2si ecx, xmm0    or        ecx, ecx    jns       @F    neg       ecx@@: invoke    wsprintf, lpOut, addr format, eax, ecx    add       eax, offset buffer - 1@@: cmp       byte ptr , "." ; to avoid numbers like 1.    jz        @F    cmp       byte ptr , "0"    jnz       @F    mov       byte ptr , 0    dec eax    jmp @B@@:    mov       eax, lpOut    retFloatToAscii endp``

Most results are pretty sactisfatory (sp?) but with numbers like 1.01 I get some weird results... 1.01 returns me 1.9999
Posted on 2005-12-06 20:25:39 by Lenin
wsprintf returns the number of copied characters NOT including the terminating NULL, so try

``add       eax, offset buffer``

``add       eax, offset buffer - 1``
Posted on 2005-12-06 20:34:16 by ti_mo_n
Now that part of the function seems to not be working anymore...

I enter 1.99 and get 1.990000
-1.1 - 1.100000
1.0123 - 1.12300
Posted on 2005-12-06 20:42:58 by Lenin
``    add       eax, offset buffer - 1@@: cmp       byte ptr , "."    jz        @F    cmp       byte ptr , "0"    jnz       label2    mov       byte ptr , 0    dec eax    jmp @B@@:    mov byte ptr , 0label2:``

It's 3:55 now, so my brain is in shutdown for 2 hours already :P if this diesn't work, then I can think of something after getting  some sleep :)
Posted on 2005-12-06 21:02:52 by ti_mo_n
Hey Ti_mo_n,

It's here. http://win.asmcommunity.net/x86book/ It is better you add it for the good of the community.  ;)
Posted on 2005-12-06 21:57:42 by roticv
It works :) I beleive the function is complete now so I'll just leave it here for future reference:

``ftoa proc float:DWORD, lpOut:DWORD.data    format  db "%d.%d",0    million REAL4 1000000.0.code    movss     xmm0, float   ;xmm0 = float    cvttss2si eax, float    ;eax = integral part of 'float' stored as integer    cvtsi2ss  xmm1, eax     ;xmm1 = integral part of float stored as 'float'    subss     xmm0, xmm1    ;xmm0 = fractional part of 'float'    mulss     xmm0, million    cvttss2si ecx, xmm0    or        ecx, ecx    jns       @F    neg       ecx@@: invoke    wsprintf, lpOut, addr format, eax, ecx    add       eax, lpOut    dec       eax@@: cmp       byte ptr , "."    jz        @F    cmp       byte ptr , "0"    jnz       label2    mov       byte ptr , 0    dec eax    jmp @B@@:    mov byte ptr , 0label2:    mov       eax, lpOut    retftoa endp``

Thanks ti_mo_n :)
Posted on 2005-12-07 09:32:09 by Lenin
Hi Lenin,
No problem ;)

Hi roticv,
I'll learn the wikiwiki and then add the MMX, SSE, SSE2 stuff :)

/edit
Done :) I've added few things to the 'glossary'.
Posted on 2005-12-07 09:41:17 by ti_mo_n
That's very nice of you.  ;)
Posted on 2005-12-07 12:51:16 by roticv
thanx roticv ;)

Lenin,

Oh  :P Still I don't know how to link to msvcrt.dl ... I searched trough masm32's include and lib folders but couldn't find anything....

``libhandle dd ?sprintf_ dd ?buffer db 64 dup (?)fmt db "%f",0funcname db "sprintf", 0libname1 db "msvcrt70.dll", 0libname2 db "msvcrt.dll", 0call LoadLibrary, offset libname1or eax, eaxjnz continuecall LoadLibrary, offset libname2or eax, eaxjz errorcontinue:mov , eaxcall GetProcAddress, eax, offset funcnameor eax, eaxjnz noerrorcall FreeLibrary, jmp errornoerror:``
``call , offset buffer, offset fmt, add esp, 3 * 4  ; you have to balance the stack because sprintf uses _cdecl``