how to format a number with 1 digit after the point?
ex : I get 0.5666458 in the stack of fpu
and I wish to display '0.5' only
how make it?
Posted on 2004-02-23 13:23:11 by franlou
; Top of FPU stack is converted to 12345.9 style number
sub esp, 8
fimul TEN
fistp QWORD PTR
pop eax
pop edx
div TEN
invoke wsprintf, OFFSET __buffer, _T("%lu.%lu"), eax, edx

Sorry for such lazy code.
Posted on 2004-02-23 19:50:50 by bitRAKE
I assume that your primary objective is to truncate all the decimals except the first one. I also assume that you already have some preferred procedure to display the content of the FPU and there is no need to cover that subject. The following code also assumes that the target value is already in the FPU's top register and you are programming in 32-bit.
pushd 10

fimul dword ptr[esp] ;multiply it by 10
push eax ;reserves space on the stack
fstcw word ptr[esp] ;get the current control word in that space
mov eax,[esp] ;get it into eax (only AX will have the CW)
and ah,0ch ;set the precision control bits for truncating
push eax ;store the modified control word on the stack
fldcw word ptr[esp] ;load the modified control word
frndint ;discard all other 'decimals'
fldcw word ptr[esp+4] ;restore the original control word
fidiv dword ptr[esp+8];get the number with one decimal place
add esp,12 ;restore the stack
Raymond
Posted on 2004-02-24 00:01:41 by Raymond
thanks raymond but
I don't understand your code...

there is mine:
finit
fld ;=QWORD
fdiv
invoke FloatToStr, , ADDR NumberBuffer
fst
invoke FloatToStr, , ADDR NumberBuffer

I got result either in CaloQW (floatnumber), either in NumberBuffer (string)
and ,indeed ,my objective is to truncate all the decimals except the first one.
I wish display this result into an editbox.

How I apply your code to my example?
Posted on 2004-02-25 13:04:54 by franlou
One of the internal 16-bit FPU registers is the Control Word. The RC field (bits 11 and 10) or Rounding Control determines how the FPU will round results in one of four ways:

00 = Round to nearest, or to even if equidistant (this is the initialized state)
01 = Round down (toward -infinity)
10 = Round up (toward +infinity)
11 = Truncate (toward 0)

If you are not familiar with the FPU's internals, I would refer you to Chap.1 of the following tutorial:

http://www.masmforum.com/website/tutorials/fptute/index.html

To explain my code a little more using the example which you used as the subject, if the value already in the FPU top data register is 0.56668974, multiplying it by 10, would give 5.6668974.

You would then want to convert that to an integer with the frndint instruction, truncating all the decimals. However, that instruction uses the directive of the Rounding Control field of the Control Word. The preceeding instructions were to retrieve the current Control Word, save it, modify it for truncating, and load the modified Control Word into the FPU. In this example, the truncated integer would be 5.

After the truncation, the former Control word is restored and the integer is divided by 10 to give you back the original value but with only 1 decimal place (i.e. 0.5 in this example).

The very last instruction was simply to clean up the stack which had been used for storing the multiplier and the Control Words.

The final value is still in the FPU top data register and none of the other data registers have been modified. You can then save the result as a floating point value or convert it to a string with whichever procedure you prefer.

Using the Fpu.lib which is part of the MASM32v8 package, it also could be as simple as the following (again assuming that the value to be 'truncated' is already in the FPU top data register):
invoke FpuMul,0,10,0,SRC1_FPU or SRC2_DIMM or DEST_FPU

invoke FpuTrunc,0,0,SRC1_FPU or DEST_FPU
invoke FpuDiv,0,10,0,SRC1_FPU or SRC2_DIMM or DEST_FPU
You could then follow it with the following to convert it to a null-terminated string with 1 decimal place:
invoke FpuFLtoA,0,1,ADDR YourBuffer,SRC1_FPU or SRC2_DIMM
Raymond
Posted on 2004-02-25 22:16:39 by Raymond