News:

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

Main Menu

output 80-bits number from the FPU to the console

Started by Mikl__, March 19, 2013, 10:15:12 PM

Previous topic - Next topic

dedndave

google translate does a funny job of converting it to English
convert it to English, then convert that back to Russian, and let me know what is says   :biggrin:

bomz

I think the simplest and quickest
Quotefbstp CReg
   lea esi,CReg
   lea edi,FString+32
   mov ecx, 9
@@:
   xor eax, eax
   lodsb
   shl ax, 4
   shr al, 4
   add ax, 3030h
   mov byte ptr[edi], al
   sub edi, 2
   mov byte ptr[edi], ah
   sub edi, 2
   loop @B
   ;invoke MessageBoxW,0,ADDR FString,ADDR mestitle,MB_ICONASTERISK
   mov ecx, 18
   lea edi, FString
   mov ax, "0"
   repe scasw
   sub edi, 2
   invoke wsprintfW,ADDR buffer,addr form,ecx
   invoke MessageBoxW,0,ADDR buffer,ADDR mestitle,MB_ICONASTERISK
   invoke MessageBoxW,0,edi,0,MB_OK + MB_ICONASTERISK
When you talking through google translation you need use "special easy language" each native speaker feel it and know how to say

dedndave

i guess, if i wanted to write a calculator program, i would limit it to 18 decimal digits (or less)   :P
real-world calculations rarely need more precision

RuiLoureiro

Hi Mikl__
                I did my "The calculator" with 18 digits of precision
                We dont need more. You can search this forum and
                you can find it. The windows calculator gives 18/19 digits
                plus something else we dont know what ...
                15 digits is very good !

                Try to search Math10 too and read what we did there

Mikl__

Hi, bomz!
I think your decision on a conversion BCD to text is wonderful!; masm windows gui #
.686P
.model flat
include \masm32\include\windows.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
;--------------------------------------------------
.data
result dt ?
szBuffer db 100 dup(0)
ten dq 10.0e+15
compressdecimaltable dw "00","10","20","30","40","50","60","70","80","90",6 dup (0)
                     dw "01","11","21","31","41","51","61","71","81","91",6 dup (0)
                     dw "02","12","22","32","42","52","62","72","82","92",6 dup (0)
                     dw "03","13","23","33","43","53","63","73","83","93",6 dup (0)
                     dw "04","14","24","34","44","54","64","74","84","94",6 dup (0)
                     dw "05","15","25","35","45","55","65","75","85","95",6 dup (0)
                     dw "06","16","26","36","46","56","66","76","86","96",6 dup (0)
                     dw "07","17","27","37","47","57","67","77","87","97",6 dup (0)
                     dw "08","18","28","38","48","58","68","78","88","98",6 dup (0)
                     dw "09","19","29","39","49","59","69","79","89","99"
.code
start: finit
fldpi
fmul ten
fbstp result
lea esi,result
lea edi,szBuffer+16
mov ecx, 9
next:   xor eax, eax
lodsb
mov eax,dword ptr compressdecimaltable[eax*2]
mov word ptr[edi],ax
sub edi,2
loop next
        invoke MessageBox, NULL, addr szBuffer, 0, MB_OK
    retn
end start

bomz

It's original (oddball). but not optimal. two sh* x 4 operation much faster even old processors than table reading from memory

bomz

Quote.386

.model flat, stdcall
option casemap :none

   include \MASM32\INCLUDE\windows.inc
   include \MASM32\INCLUDE\user32.inc
   include \MASM32\INCLUDE\kernel32.inc
   includelib \MASM32\LIB\user32.lib
   includelib \MASM32\LIB\kernel32.lib

.data
mestitle      db "Bomz",0
realform      db "%u.%010hu", 0
decimalplaces      INT64 10000000000
;value         REAL8 0.00001
value         REAL10 1.00001

.data?
buffer         db 512 dup(?)
realint         dd ?
realfract      dd ?

.code
start:
   finit
   fldpi
   ;fld value
   fist realint
   fisub realint
   fild decimalplaces
   fmul
   fistp realfract
   invoke wsprintf,addr buffer,addr realform,realint,realfract
   invoke MessageBox,0,addr buffer,addr mestitle,MB_ICONASTERISK
   invoke ExitProcess,0
end start

qWord

bomz,
wrong suggestions won't get correct by repeating them.
MREAL macros - when you need floating point arithmetic while assembling!

bomz

prove it

Quote.386

.model flat, stdcall
option casemap :none

include \MASM32\INCLUDE\windows.inc
include \MASM32\INCLUDE\user32.inc
include \MASM32\INCLUDE\kernel32.inc
include \MASM32\INCLUDE\ntdll.inc
include \masm32\macros\Strings.mac

.data
TW0         "Bomz",mestitle
TW0         "%u.", realform
decimalplaces      INT64 1000000000000000000
value         REAL10 0.000000000000000001

.data?
String         db 512 dup(?)
Buffer         db 512 dup(?)
CompressDec      dt ?
realint         dd ?
;;;;TABFLAG      dd ?

.code
start:
   finit
   fldpi
   ;;;;fld value
   fist realint
   invoke wsprintfW,addr Buffer,addr realform,realint
   fisub realint
   fild decimalplaces
   fmul
   call compressdecimal2string
   invoke MessageBoxW,0,addr Buffer,ADDR mestitle,MB_ICONASTERISK
   invoke ExitProcess,0
         ;===================================
         compressdecimal2string:
                  mov edx, esi
                  fbstp CompressDec
                  lea esi,CompressDec
                  lea edi,String+34
                  mov dword ptr [edi], 0
                  mov ecx, 9
               @@:
                  xor eax, eax
                  lodsb
                  shl ax, 4
                  shr al, 4
                  add ax, 3030h
                  mov byte ptr[edi], al
                  sub edi, 2
                  mov byte ptr[edi], ah
                  sub edi, 2
                  loop @B
                  mov esi, edx
                  invoke wcscat, addr Buffer, addr String
                  ret
                  ; ==
end start

Quote3,1415926535897932384626433832795

dedndave

the range for intel 80-bit extended reals is approx:

normal
-1.1897E+4932 to -3.3621E-4932, 0, +3.3621E-4932 to +1.1897E+4932

denormal
-1.1897E+4932 to -1.8225E-4951, 0, +1.8225E-4951 to +1.1897E+4932

you can't plug 1 value in, pi, and call that a test   :P

bomz

For my purpose I need only 2 sign after , to convert volume size in bytes (from 1 mb to 2 terabyte) to gigabyte.




qWord

Quote from: bomz on March 26, 2013, 01:53:05 PM
For my purpose I need only 2 sign after
that's funny - so bomz and Mikl__ are the same person?
MREAL macros - when you need floating point arithmetic while assembling!

bomz

thats funny conducted online psychiatric clinics

In russian says: "2 sign after ," I don't know hot it's say in english because i learn mathematics in russian

Mikl__

Quote from: qWordthat's funny - so bomz and Mikl__ are the same person?
qWord,
You are mistaken .... bomz is on this forum for a long time, and I asked only one question

Mikl__

; masm windows gui #
.686
.model flat
.mmx
include windows.inc
includelib user32.lib
includelib kernel32.lib
extern _imp__MessageBoxA@16:dword
extern _imp__ExitProcess@4:dword
.code
start: finit
mov edi,offset buffer
fld x
fxam
fstsw ax ;stores the current value of the FPU control word at AX
        and eax,4700h ;extract bits c3, c2, c1, c0 of the FPU control word
shr eax,3
shr ah,3
shr eax,3
jmp table[eax]
a2: fabs
mov al,'-'
stosb
a1:; get the size of the number
        fldlg2  ;st(0)=lg(2)
fld st(1);copy Src
fyl2x ;st(0)=lg(x)
fldcw truncw    ;insure rounding code of FPU to truncating     
fist esize      ;store characteristic of logarithm
fldcw oldcw     ;load back the former control word
ftst            ;test logarithm for its sign
fstsw ax        ;get result
sahf            ;transfer to CPU flags
sbb esize,0     ;decrement esize if log is negative
fstp st(0)      ;get rid of the logarithm
        mov eax,15 ;a maximum of 15 decimals is allowed
        sub eax,esize
        mov tempdw,eax
;----------------------------------------
; multiply the number by the power of 10 to generate required
; integer and store it as BCD
;-------------------------------------------------------------
test eax,eax
jz @f;if tempdw != 0
fild  tempdw
      fld ten
      fyl2x ;log2(10)*tempdw
;the FPU can compute the antilog only with the mantissa
;the characteristic of the logarithm must thus be removed     
fld st ;copy the logarithm
frndint ;keep only the characteristic
fsub st(1),st;keeps only the mantissa
fxch ;st(0) <--> st(1)
f2xm1   ;st(0)=2^(mantissa)-1
fld1
fadd
;the number must now be readjusted for the characteristic of the logarithm
fscale  ;scale it with the characteristic
fstp st(1);get rid of the characteristic of the log
fmul                   
;------------------------------------------------
@@: push edi
mov edi,offset unpacked
fld st
fbstp bcdstr    ;->TBYTE containing the packed digits
        fbld bcdstr
fsubp st(1),st
fmul thousand
fldcw tmp ;round up
frndint
fmul ten
        fbstp y;fractional part
;------- BCD -> ASCII-string --------------------
mov al,byte ptr bcdstr+8
or al,'0'
stosb          ;BCD -> ASCII-string 1 decimal digit
        movq mm0,qword ptr bcdstr
movq mm1,mm0
push 0F0F0F0Fh
push 0F0F0F0Fh
pand mm0,qword ptr [esp]
movq mm2,mm0
push 0
push 4
psrlq mm1,qword ptr [esp]
pand mm1,qword ptr [esp+8]
punpckhbw mm0,mm1
por mm0,mask2
movq [esp],mm0
pop ecx
pop eax
bswap eax
add esp,8
bswap ecx
stosd ;BCD -> ASCII-string 4 decimal digits
mov eax,ecx
stosd ;BCD -> ASCII-string 4 decimal digits
punpcklbw mm2,mm1
por mm2,mask2
movq qword ptr bcdstr,mm2
        mov eax,dword ptr bcdstr+4
bswap eax
stosd ;BCD -> ASCII-string 4 decimal digits
mov eax,dword ptr bcdstr
bswap eax
stosd ;BCD -> ASCII-string 4 decimal digits
call routine ;BCD -> ASCII-string 4 decimal digits
pop edi
;------------------------------------------------
mov esi,offset unpacked+1
cmp byte ptr[esi-1],"1"
jnz @f
lea esi,[esi-1]
@@: lodsb               
mov ah,"."
stosw              ;copy the integer and pointer
movq mm0,[esi]
movq [edi],mm0
        movq mm0,[esi+8]
movq [edi+8],mm0
lea edi,[edi+16]
lea esi,[esi+16]
movsw             ;copy 18 decimal digits
jnz @f                ;no extra "1"
inc esize               ;adjust exponent
@@:     mov edx,esize
mov eax,"+E" ;"E+" -> ASCII-string
sar edx,31
and edx,200h
add eax,edx ;"E-" -> ASCII-string
stosw                   ;insert proper sign
;Note: the absolute value of the size could not exceed 4931
finit
fild esize
fabs                   ;make number positive
fbstp y
call routine
xor   eax,eax
stosb ;0-terminator -> ASCII-string
        mov edi,offset buffer
jmp @f
a0: mov edi,tablemsg[eax]
@@: push MB_OK
push offset wTitle
push edi;offset buffer
push 0
call _imp__MessageBoxA@16
push 0
call _imp__ExitProcess@4
;---------------------------------------
routine proc
        movq mm0,qword ptr y
movq mm1,mm0
push 0F0F0F0Fh
push 0F0F0F0Fh
pand mm0,qword ptr [esp];mask1
push 0
push 4
psrlq mm1,qword ptr [esp]
pand mm1,qword ptr [esp+8];mask=0F0F0F0F0F0F0F0F
punpcklbw mm0,mm1
por mm0,mask2
movq [esp],mm0
pop eax
bswap eax
stosd ;BCD -> ASCII-string 4 decimal digits
add esp,12
ret
routine endp
;--------------------------------------
.data
tmp dw 0FBFFh
mask2 dq 3030303030303030h
oldcw   dw 037Fh
truncw  dw 0F7Fh
bcdstr  dt ?
esize dd ?
tempdw dd ?
y dt ?
x dt 0.69314718055994530941;723212145818
thousand dq 1000.0
ten dq 10.0
unpacked db 30 dup(0)   
wTitle db '0,69314718055994530941723212145818',0
buffer db 40 dup(0)
pinf db "+ INFINITY",0
ninf db "- INFINITY",0
empty db "Empty",0
pnan db "+ NaN",0
nnan db "- NaN",0
pzero db "+ 0.0",0
nzero db "- 0.0",0
pdnnum db "+ Denormal number",0
ndnnum db "- Denormal number",0
pnnnum db "+ Unsupported",0
nnnnum db "- Unsupported",0
table dd a0,a0,a0,a0,a1,a0,a2,a0,a0,a0,a0,a0,a0,a0,a0,a0
tablemsg dd pnnnum,pnan,nnnnum,nnan,0,pinf,0,ninf,pzero,empty,nzero,\
empty,pdnnum,empty,ndnnum,empty
end start
Please, test it!