format pe console
include 'win32axp.inc'

;Happy Coding ;D
;Test your codes here
;stdcall getflt,myfloat
;stdcall getdbl,mydouble
fld [myfloat]
fld [mydouble]
call fpu_env
stdcall prtflt,[myfloat],0,1
stdcall prtflt,[myfloat],3,1
stdcall prtdbl,mydouble,0,1
stdcall prtdbl,mydouble,3,1

invoke system,"pause>0"
invoke exit,0
myfloat dd 45.666768
mydouble dq 6787.342632

;--------------------------------------
;Double-Precision to string
;DISPLAY FP (REAL8)
;info : dq address (initialize as FP)
;     : Takes and displays e format
;Note : Avoid using 'raw' EBX as argument
;pt   : Decimal places (max=16) rounding
;     :   0 - no rounding
;nline: 0-no line,1-new line
;--------------------------------------
proc prtdbl,val,pt,nline
	locals
	     dat dq 1.0,10.0,100.0,1000.0,10000.0,\
		    1e5,1e6,1e7,1e8,1e9,1e10,1e11,\
		    1e12,1e13,1e14,1e15,1e16,1e17
	     control dw 0
	     marker db 0
	     subn db 0
	     nega db 0
	     small db 0
	     big db 0
	     temp dq 0.0
	     val1 dq 0
	     val2 dq 0.0
	     cpy dq 0.0
	     copy dq 0.0
	     m dq 0.0
	     tmp dd 0
	     e dd 0
	     ten dd 10.0
	     one dd 1.0
	     idx dd 0
	     save rb 108
	     mystr db 29 dup (' '),0
	endl
	pushad

	lea eax,[save]	;save FPU
	fsave [eax]
	push eax

	cld
	lea edi,[mystr]
	mov eax,[val]
	mov edx,dword[eax]
	mov dword[copy],edx
	mov edx,dword[eax+4]
	mov dword[copy+4],edx
	test edx,edx
	     jns .v
	mov al,'-'
	stosb
.v:	finit
	fld [copy]
	fst [cpy]
	xor eax,eax
	ftst
	fstsw ax
	.if eax=7800h
	    mov ax,'0.'
	    stosw
	    mov al,'0'
	    stosb
	    jmp .quit
	.endif
	fabs
	fst [copy]
.back:	fxtract
	fstp [m]     ;mantissa
	fistp [e]    ;exponent
	mov edx,dword[cpy+4]
	shr edx,20
	.if edx = 07ffh | edx = 0fffh
	    mov al,'#'
	    stosb
	    jmp .quit
	.endif
	xor edx,edx
	mov ecx,[e]
	mov dx,word[m+6]
	and edx,0fh	  ;clear higher bytes
	or edx,16	  ;+1.0
	mov word[m+6],dx  ;
	mov edx,dword[m+4];
	bsr esi,edx
	xor eax,eax
	test ecx,ecx
	     js .small
	cmp ecx,42
	    ja .big
;---------------------
;Extract integral part
.go:	bt edx,esi
	jc .pow
.ok:	test ecx,ecx
	     jz .half
	dec ecx
	.if ~esi & ~[marker]
	    mov edx,dword[m]
	    mov esi,31
	    mov [marker],1
	    jmp .go
	.endif
	dec esi
	jmp .go
.pow:	mov [tmp],ecx
	finit
	fild [tmp]
	fld1
	fscale
	fld [val1]
	fadd st0,st1
	fstp [val1]
	jmp .ok
;---------------------
;Transition
.half:	dec esi
	mov ecx,1
	jmp .go1
;---------------------
;Extract fraction part
.go1:	bt edx,esi
	jc .pow1
.ok1:	.if ~esi & ~[marker]
	    mov edx,dword[m]
	    mov esi,31
	    mov [marker],1
	    inc ecx
	    jmp .go1
	.endif
	test esi,esi
	     jz .DISP
	dec esi
	inc ecx
	jmp .go1
.pow1:	finit
	mov [tmp],ecx
	fild [tmp]
	fchs
	fld1
	fscale
	fadd [val2]
	fstp [val2]
	jmp .ok1
;---------------------------------------
;Process Fraction with negative exponent
;else, proceed normally
.small: push edi
	xor edi,edi
	finit
	fld [copy]
	fabs
.x:	fmul [ten]
	inc edi
	fcom [one]
	fstsw ax
	sahf
	jae .k
	jmp .x
.k:	mov [idx],edi
	fst [copy]
	.if edi < 15 & ~[pt]  ;normal display
	    pop edi
	    fldz
	    fstp [val2]
	    neg ecx
	    mov [nega],1
	    jmp .go1
	.endif
	mov [small],1
	pop edi
	jmp .back
;------------------------------
;Process large integral part
;That requires x.xxxxe+y format
.big:	finit
	xor esi,esi
	fld [copy]
.f:	fdiv [ten]
	inc esi
	fcom [ten]
	fstsw ax
	sahf
	jb .g
	jmp .f
.g:	mov [idx],esi
	mov [big],1
	jmp .back
;---------------------------------
;By now......
;val1 should contain integral part
;val2 should contain fraction part
.DISP:	.if [nega]  ;if 0.xxxxx
	    mov al,'0'
	    stosb
	    jmp .finish
	.endif
;----------------------------
;Display integral part
.DISP1: finit
	;---------------
	fstcw [control]
	bts [control],10	;Rounding: down
	fldcw [control] 	;for following DIVs
	;---------------
	xor edx,edx
	fld [val1]
	fstp [cpy]
	fld [cpy]		;single digit
	fcom [ten]
	fstsw ax
	sahf
	jb .w
.t:	fdiv [ten]		;Repeat DIV
	fcom [ten]		;to get the front digit
	fstsw ax
	sahf
	jb .s
	inc edx
	jmp .t
	;---------------
.s:	fst [temp]		;save digit
	frndint 		;round ST0 to x.000000
	fist [tmp]		;Display
	mov eax,[tmp]
	add eax,30h
	stosb
	inc edx 		;Adjust post. value
	fmul [dat+edx*8]	;Get positional value * digit
	fld [val1]
	fsub st0,st1		;Subtract from previous value
	.if edx=1		;Display last digit
	    fmul [one]
	    fistp [tmp]
	    mov eax,[tmp]
	    add eax,30h
	    stosb
	    jmp .finish
	.endif
	;--------------
	.if edx > 1		;case: mid 0s. Related to .w
	    push edx		;and leading 0. How?
	    dec edx
.q:	    fcom [dat+edx*8]
	    fstsw ax
	    sahf
	    jb .midz
	    pop edx
	.endif
	fstp [val1]
	jmp .DISP1
.midz:	mov al,'0'
	stosb
	.if edx=0
	    pop edx
	    jmp .finish
	.endif
	dec edx
	jmp .q
	;--------------
.w:	frndint
	fist [tmp]
	mov eax,[tmp]
	add eax,30h
	stosb
	jmp .finish
;------------------------------
;Transition
.finish:.if [subn]
	    jmp .quit
	.endif
	mov al,'.'
	stosb
;---------------------
;Display fraction part
.DISP2: xor edx,edx
	finit
	;---------------
	fstcw [control]
	bts [control],10   ;Rounding: down
	fldcw [control]    ;for next MULs
	;---------------
	fld [val2]
	fstp [cpy]
	fld [cpy]
.z:	fmul [ten]
	fst [temp]
	fld [temp]
	fist [tmp]
	frndint
	;Places Rounding ----------
	.if [pt]
	    inc edx
	    .if edx=[pt]      ;if final digit
		finit
		fld [temp]
		fistp [tmp]
		frndint
		mov eax,[tmp]
		add eax,30h
		stosb
		jmp .done
	    .endif
	    dec edx
	.endif
	;---------------------------
	mov eax,[tmp]
	add eax,30h
	stosb
	fxch
	fsub st0,st1
	ffree st1
	inc edx
	cmp edx,16
	    je .done
	jmp .z
;--------------------------
;Transition...
;Display exponential format
;If Big or Small numbers
.done:	.if [big] | [small]
	    .if [big]
		mov ax,'e+'
	    .else
		mov ax,'e-'
	    .endif
	    stosw
	    fild [idx]
	    fstp [val1] ;re-use
	    mov [subn],1
	    jmp .DISP1
	.endif
;--------------------------
.quit:	xor al,al      ;End of string
	stosb
	lea esi,[mystr]
.h:	lodsb
	test al,al
	     jz .out
	stdcall prtchr,eax
	jmp .h
.out:	.if [nline]
	    call line
	.endif
	pop eax
	frstor [eax] ;restore FPU
	popad
	ret
endp

;--------------------------------------
;Float to String
;DISPLAY FP (REAL4)
;info : [dd] (initialize as FP)
;     : reg32,fp constant
;     : Takes and displays e format
;Note : Avoid using 'raw' EBX as argument
;pt   : Decimal places (max=6) rounding
;     : 0 - no rounding
;nline: 0-no line
;--------------------------------------
proc prtflt,val,pt,nline
	locals
	     dat dd 1.0,10.0,100.0,1000.0,10000.0,\
		    1e5,1e6,1e7,1e8,1e9,1e10,1e11
	     control dw 0
	     subn db 0
	     nega db 0
	     small db 0
	     big db 0
	     temp dd 0.0
	     val1 dd 0
	     val2 dd 0.0
	     cpy dd 0.0
	     copy dd 0.0
	     m dd 0.0
	     tmp dd 0
	     e dd 0
	     t dd 1.0
	     ten dd 10.0
	     one dd 1.0
	     idx dd 0
	     save rb 108
	     fltstr db 15 dup (' '),0
	endl
	pushad
	lea eax,[save]	;save FPU
	fsave [eax]
	push eax
	cld
	lea edi,[fltstr]
	mov eax,[val]
	mov [copy],eax
	test eax,eax
	     jns .v
	mov al,'-'
	stosb
.v:	finit
	fld [copy]
	fst [cpy]
	fabs
	fst [copy]
.back:	fxtract
	fstp [m]     ;mantissa
	fistp [e]    ;exponent
	mov ecx,[cpy]
	.if ecx=0 | ecx=80000000h
	    mov ax,'0.'
	    stosw
	    mov al,'0'
	    stosb
	    jmp .quit
	.endif
	xor edx,edx
	mov ecx,[e]
	mov edx,[m]
	and edx,7fffffh
	or edx,800000h	  ;set bit 23
	bsr esi,edx
	xor eax,eax
	test ecx,ecx
	     js .small
	cmp ecx,22
	    ja .big
;---------------------
;Extract integral part
.go:	bt edx,esi
	jc .pow
.ok:	test ecx,ecx
	     jz .half
	dec ecx
	dec esi
	jmp .go
.pow:	mov [tmp],ecx
	finit
	fild [tmp]
	fld1
	fscale
	fld [val1]
	fadd st0,st1
	fstp [val1]
	jmp .ok
;---------------------
;Transition
.half:	dec esi
	mov ecx,1
	jmp .go1
;---------------------
;Extract fraction part
.go1:	bt edx,esi
	jc .pow1
.ok1:	test esi,esi
	     jz .DISP
	dec esi
	inc ecx
	jmp .go1
.pow1:	finit
	mov [t],ecx
	fild [t]
	fchs
	fld1
	fscale
	fadd [val2]
	fstp [val2]
	jmp .ok1
;---------------------------------------
;Fraction with negative exponent
;And if ecx is too large (x.xxxxe-y format)
;else, proceed normally
.small: push edi
	xor edi,edi
	finit
	fld [copy]
	fabs
.x:	fmul [ten]
	inc edi
	fcom [one]
	fstsw ax
	sahf
	jae .k
	jmp .x
.k:	mov [idx],edi
	fst [copy]
	.if edi < 7 & ~[pt]
	    fldz
	    fstp [val2]
	    neg ecx
	    mov [nega],1
	    pop edi
	    jmp .go1
	.endif
	pop edi
	mov [small],1
	jmp .back
;------------------------------
;Process large integral part
;That requires x.xxxxe+y format
.big:	finit
	xor esi,esi
	fld [copy]
.f:	fdiv [ten]
	inc esi
	fcom [ten]
	fstsw ax
	sahf
	jb .g
	jmp .f
.g:	mov [idx],esi
	mov [big],1
	jmp .back
;---------------------------------
;By now......
;val1 should contain integral part
;val2 should contain fraction part
.DISP:	.if [nega]  ;if 0.xxxxx
	    mov al,'0'
	    stosb
	    jmp .finish
	.endif
;----------------------------
;Display integral part
.DISP1: finit
	;---------------
	fstcw [control]
	bts [control],10	;Rounding: down
	fldcw [control] 	;for following DIVs
	;---------------
	xor edx,edx
	fld [val1]
	fstp [cpy]
	fld [cpy]		;single digit
	fcom [ten]
	fstsw ax
	sahf
	jb .w
.t:	fdiv [ten]		;Repeat DIV
	fcom [ten]		;to get the front digit
	fstsw ax
	sahf
	jb .s
	inc edx
	jmp .t
	;---------------
.s:	fst [temp]		;save digit
	frndint 		;round ST0 to x.000000
	fist [tmp]		;Display
	mov eax,[tmp]
	add al,30h
	stosb
	inc edx 		;Adjust post. value
	fmul [dat+edx*4]	;Get positional value * digit
	fld [val1]
	fsub st0,st1		;Subtract from previous value
	.if edx=1		;Display last digit
	    fmul [one]
	    fistp [tmp]
	    mov eax,[tmp]
	    add al,30h
	    stosb
	    jmp .finish
	.endif
	.if edx > 1
	    push edx
	    dec edx
.q:	    fcom [dat+edx*4]
	    fstsw ax
	    sahf
	    jb .midz
	    pop edx
	.endif
	fstp [val1]
	jmp .DISP1
	;--------------
.midz:	mov al,'0'
	stosb
	.if edx=0
	    pop edx
	    jmp .finish
	.endif
	dec edx
	jmp .q
.w:	frndint
	fist [tmp]
	mov eax,[tmp]
	add al,30h
	stosb
	jmp .finish
;------------------------------
;Transition
.finish:.if [subn]
	    jmp .quit
	.endif
	mov al,'.'
	stosb
;---------------------
;Display fraction part
.DISP2: xor edx,edx
	finit
	;---------------
	fstcw [control]
	bts [control],10   ;Rounding: down
	fldcw [control]    ;for next MULs
	;---------------
	fld [val2]
	fstp [cpy]
	fld [cpy]
.z:	fmul [ten]
	fst [cpy]
	fld [cpy]
	.if edx=6	   ;if final digit
	    jmp .trans
	.endif
	frndint
	.if [pt] & ~[pt] > 6
	    inc edx
	    .if edx=[pt]
		jmp .trans
	    .endif
	    dec edx
	.endif
	fist [tmp]
	mov eax,[tmp]
	add al,30h
	stosb
	fxch
	fsub st0,st1
	ffree st1
	inc edx
	cmp edx,7
	    je .done
	jmp .z
.trans: finit
	fld [cpy]
	fistp [tmp]
	mov eax,[tmp]
	.if eax >= 10
	    mov eax,9
	.endif
	add eax,30h
	stosb
;--------------------------
;Transition...
;Display exponential format
;If Big or Small numbers
.done:	.if [big] | [small]
	    .if [big]
		mov ax,'e+'
	    .else
		mov ax,'e-'
	    .endif
	    stosw
	    fild [idx]
	    fstp [val1] ;re-use
	    mov [subn],1
	    jmp .DISP1
	.endif
;--------------------------
.quit:	xor al,al
	stosb
	lea esi,[fltstr]
	stdcall prtstr,esi
	.if [nline]
	    call line
	.endif
	pop eax
	frstor [eax] ;restore FPU
	popad
	ret
endp


;---------------------------------
;String to float
;GET FP (REAL4) FROM KEYBOARD
;Convert and save to info
;info: dd (initialize as FP)
;    : Does not take e-format
;    : Must use FP format as input
;---------------------------------
proc getflt,info
	locals
	     m dd 0
	     pow10 dd 10.0
	     power dd 1.0
	     val dd 0.0
	     sgn db 0
	endl
	xor esi,esi
	xor edi,edi
.get:	cinvoke getchar
	.if al = '-'
	    mov [sgn],1
	    jmp .get
	.endif
	cmp al,0ah
	    je .start
	.if al = '.'
	    mov edi,esi
	    jmp .get
	.endif
	sub eax,30h
	push eax
	inc esi
	jmp .get
;----------------------
.start: finit
	pop [m]
	fild [m]
	fstp [val]
	mov ecx,esi
	dec ecx
.rr:	finit
	fld [power]
	fmul [pow10]
	fst [power]
	pop [m]
	fild [m]
	fmul st0,st1
	fld [val]
	fadd st0,st1
	fstp [val]
	loop .rr
;----------------------
	mov ecx,esi
	sub ecx,edi
	finit
	fld [val]
.d:	fdiv [pow10]
	loop .d
;----------------------
.quit:	fstp [val]
	mov eax,[info]
	mov ecx,[val]
	.if [sgn]
	    or ecx,80000000h
	.endif
	mov [eax],ecx
	ret
endp

;---------------------------------
;String to double
;GET FP (REAL8) FROM KEYBOARD
;Convert and save to info
;info: dq (initialize as FP)
;    : Does not take e-format
;    : Must use FP format as input
;---------------------------------
proc getdbl,info
	locals
	     m dd 0
	     pow10 dd 10.0
	     power dq 1.0
	     val dq 0.0
	     sgn db 0
	endl
	xor esi,esi
	xor edi,edi
.get:	cinvoke getchar
	.if al = '-'
	    mov [sgn],1
	    jmp .get
	.endif
	cmp al,0ah
	    je .start
	.if al = '.'
	    mov edi,esi
	    jmp .get
	.endif
	sub eax,30h
	push eax
	inc esi
	jmp .get
;----------------------
.start: finit
	pop [m]
	fild [m]
	fstp [val]
	mov ecx,esi
	dec ecx
.rr:	finit
	fld [power]
	fmul [pow10]
	fst [power]
	pop [m]
	fild [m]
	fmul st0,st1
	fld [val]
	fadd st0,st1
	fstp [val]
	loop .rr
;----------------------
	mov ecx,esi
	sub ecx,edi
	finit
	fld [val]
.d:	fdiv [pow10]
	loop .d
;----------------------
.quit:	fstp [val]
	mov eax,[info]
	mov ecx,dword[val+4]
	mov edx,dword[val]
	.if [sgn]
	    or ecx,80000000h
	.endif
	mov dword[eax+4],ecx
	mov dword[eax],edx
	ret
endp

;-------------------------
;DISPLAY FPU CONTROL FLAGS
;-------------------------
proc fpu_cflag
	locals
	    controls dw 0
	endl
	push eax ecx
	fstcw [controls]
	;stdcall prtstr,"F  E  D  C  B	A  9  8  7  6  5  4  3	2  1  0"
.done:	stdcall prtstr,"\n---------------------------------------CONTROL"
	stdcall prtstr,"\n        IC RC RC PC PC IEM   PM UM OM ZM DM IM\n"
	stdcall prtstr,"----------------------------------------------\n"
	mov ecx,15
	xor eax,eax
	movzx eax,[controls]
.go1:	bt eax,ecx
	   jc .one
	stdcall prtchr,dword '0'
.y:	test ecx,ecx
	     jz .out
	dec ecx
	stdcall prtchr,dword ' '
	stdcall prtchr,dword ' '
	jmp .go1
.one:	stdcall prtchr,dword '1'
	jmp .y
.out:	stdcall prtchr,dword '='
	stdcall prthex,eax,0
	call line
	;fldcw [controls]  ;restore control flag
	pop ecx eax
	ret
endp

;------------------------------------------
;DISPLAY FPU STATUS FLAGS
;Flags are 'sticky'. Use fclex where needed
;------------------------------------------
proc fpu_sflag
	push eax ecx
	xor eax,eax
	fstsw ax
	fwait
	push eax
	;stdcall prtstr,"F  E  D  C  B	A  9  8  7  6  5  4  3	2  1  0"
.done:	stdcall prtstr,"\n----------------------------------------STATUS"
	stdcall prtstr,"\nB C3 TP TP TP C2 C1 C0 IR SF  P  U  O  Z  D  I\n"
	stdcall prtstr,"----------------------------------------------\n"
	mov ecx,15
	pop eax
.go1:	bt eax,ecx
	   jc .one
	stdcall prtchr,dword '0'
.y:	test ecx,ecx
	     jz .out
	dec ecx
	stdcall prtchr,dword ' '
	stdcall prtchr,dword ' '
	jmp .go1
.one:	stdcall prtchr,dword '1'
	jmp .y
.out:	stdcall prtchr,dword '='
	stdcall prthex,eax,0
	call line
	pop ecx eax
	ret
endp

;-------------------------------
;COPY ENTIRE FPU STACK TO AN ARRAY
;val   :dq array's address. Save here
;-------------------------------
proc fpu_scopy,val
	push ecx eax
	xor ecx,ecx
	mov eax,[val]
.go:	fst qword[eax]
	fincstp
	inc ecx
	add eax,8
	cmp ecx,8
	    je .done
	jmp .go
.done:	pop eax ecx
	ret
endp

;-------------------------------
;COPY FPU REGISTER
;info  :Index (0-7). e,g. 0 for ST0
;val   :dq address. Save to here
;-------------------------------
proc fpu_copy,info,val
	locals
	    st dq 0.0
	endl
	push ecx eax edx
	xor ecx,ecx
.go:	.if ecx=[info]
	    fst [st]
	.endif
	fincstp
	inc ecx
	cmp ecx,8    ;complete rotation
	    je .done
	jmp .go
.done:	mov eax,[val]
	mov edx,dword[st+4]
	mov dword[eax+4],edx
	mov edx,dword[st]
	mov dword[eax],edx
	pop edx eax ecx
	ret
endp

;--------------------------------
;VIEW FPU REGISTER
;info  :index (0-7). e,g. 0 for ST0
;--------------------------------
proc fpu_reg,info
	locals
	    st dq 0.0
	endl
	push ecx edx
	xor ecx,ecx
	lea edx,[st]
.go:	.if ecx=[info]
	    fst [st]
	    stdcall prtdbl,edx,0,1
	.endif
	fincstp
	inc ecx
	cmp ecx,8
	    je .done
	jmp .go
.done:	pop edx ecx
	ret
endp

;-----------------------
;DISPLAY FPU ENVIRONMENT
;-----------------------
proc fpu_env
	call fpu_stack
	call fpu_sflag
	call fpu_cflag
	ret
endp

;--------------------
;Save FPU Environment
;info :rb 108
;--------------------
proc fpu_save,info
	mov eax,[info]
	fsave [eax]
	fwait
	ret
endp 

;--------------------------
;Restore FPU Environment
;info :rb 108 from fpu_save
;--------------------------
proc fpu_restore,info
	mov eax,[info]
	fwait
	frstor [eax]
	ret
endp

;---------------------------------
;DISPLAY FPU STACK
;Note: Use fclex where appropriate
;---------------------------------
proc fpu_stack
	locals
	   st dq 0.0
	endl
	pushad
	xor ecx,ecx
	lea edx,[st]
	stdcall prtstr,'-----------STACK----------\n'
.again: stdcall prtstr,'ST'
	add ecx,30h
	stdcall prtchr,ecx
	stdcall prtstr,': '
	sub ecx,30h
	;----------------------
	xor eax,eax
	fxam		 ;Read status flag
	fstsw ax	 ;Store status flag to AX
	and eax,4500h	 ;..for C3,C2 and C0
	.if eax=4100h	 ;
	    stdcall prtstr,"...\n"  ;empty
	    jmp .go
	;.elseif eax=4000h
	;    stdcall prtstr,"<0>\n"
	;    jmp .go
	.elseif eax=500h
	    stdcall prtstr,"<inf>\n"
	    jmp .go
	.elseif eax=100h
	    stdcall prtstr,"<NaN>\n"
	    jmp .go
	.elseif eax=0
	    stdcall prtstr,"<bad>\n"
	    jmp .go
	.endif
	fclex
	;----------------------
	fst [st]
	stdcall prtdbl,edx,0,1
.go:	cmp ecx,7
	    je .out
	fincstp    ;rotate stack
	inc ecx
	jmp .again
.out:	stdcall prtstr,'--------------------------\n'
	fincstp
	popad
	ret
endp

;-----------------
;ROUNDING CONTROL
;info : 0 - default
;     : 1 - Round down (to -inf)
;     : 2 - Round up (to +inf)
;     : 3 - Truncate to 0
;Note : Any FINIT will reset to default
;     : basically used with FRNDINT
;----------------
proc fpu_roundto,info
	locals
	   control dw 0
	endl
	push eax ecx
	mov ecx,[info]
	fstcw [control]
	.if ecx=1	      ;to -inf
	    btr [control],11  ;0
	    bts [control],10  ;1
	.elseif ecx=2	      ;to +inf
	    bts [control],11
	    btr [control],10
	.elseif ecx=3	      ;trunc. to 0
	    bts [control],11
	    bts [control],10
	.else		      ;default
	    btr [control],10
	    btr [control],11
	.endif
	fldcw [control]
	pop ecx eax
	ret
endp

;-----------------
;PRECISION CONTROL
;info : 4  - 24 bits
;     : 8  - REAL8 (53 bits)
;     : 10 - Default (REAL10,64bits)
;Note : Any FINIT will reset to default
;     : Probably you'd never need this
;----------------
proc fpu_precision,info
	locals
	   control dw 0
	endl
	push eax ecx
	mov ecx,[info]
	fstcw [control]
	.if ecx=4
	    btr [control],9 ;REAL4
	    btr [control],8
	.elseif ecx=8	    ;REAL8
	    bts [control],9
	    btr [control],8
	.else
	    bts [control],9 ;default
	    bts [control],8
	.endif
	fldcw [control]
	pop ecx eax
	ret
endp

;---------------------------
;DISPLAY FP (REAL4) BINARY
;info  : r32,[dd],real4
;nline : 1 - newline, 0-none
;---------------------------
proc fpbin,info,nline
	pushad
	pushfd
	mov edx,[info]
	mov ecx,32
.go:	shl edx,1
	    jc .one
	stdcall prtchr,dword '0'
	jmp .ok
.one:	stdcall prtchr,dword '1'
.ok:	.if ecx=24 | ecx=32
	    stdcall prtchr,dword '.'
	.endif
	loop .go
.done:	.if [nline]
	   call line
	.endif
	popfd
	popad
	ret
endp

;-------------------------------
;DISPLAY DOUBLE PRECISION BINARY
;info	 :dq address only
;nline	 :1-new line. 0-no line
;-------------------------------
proc fpbinq,info,nline
	pushad
	mov ecx,[info]
	mov edx,[ecx+4]
	mov eax,63
.start: shl edx,1
	jc .one
	stdcall prtchr,dword '0'
.ok:	.if eax=63 | eax=52
	    stdcall prtchr,dword '.'
	.endif
	dec eax
	cmp eax,31
	    je .next
	test eax,eax
	     js .done
	jmp .start
.one:	stdcall prtchr,dword '1'
	jmp .ok
.next:	stdcall prtchr,dword '-'
	mov edx,[ecx]
	jmp .start
.done:	.if [nline]
	    call line
	.endif
	popad
	ret
endp

;----------------------------
;CONVERT & DISPLAY HEX STRING
;info = reg32,imm32,[dd]
;nline = 1-newline,0-no line
;----------------------------
proc prthex,info,nline
	pushad
	mov eax,[info]
	xor esi,esi
	mov ecx,16
.start: xor edx,edx
	div ecx
	push edx
	inc esi
	test eax,eax
	    jz .conv
	jmp .start
.conv:	dec esi
	pop eax
	add al,30h
	cmp al,39h
	    jbe .prt
	add al,7
.prt:	stdcall prtchr,eax
	test esi,esi
	    jz .done
	jmp .conv
.done:	cmp [nline],0
	    je .quit
	call line
.quit:	popad
	ret
endp

;----------------------------------
;Display a character
;info: char in reg32,dword[db],[dd]
;      for constant, use dword
;----------------------------------
proc prtchr,info
	pushad
	cinvoke putchar,dword[info]
	popad
	ret
endp

;-----------------------------
;DISPLAY STRING
;Takes string buffer with dup
;Takes 0-ended string buffers
;takes #-ended string constant
;-----------------------------
proc prtstr,info
	pushad
	mov esi,[info]
.prt:	;cmp byte[esi],'$'
	;    je .done
	cmp byte[esi],0ah
	    je .done
	cmp byte[esi],0
	    je .done
	cmp word[esi],'\n'
	    je .ok
	stdcall prtchr,dword[esi]
	inc esi
	jmp .prt
.ok:	call line
	add esi,2
	jmp .prt
.done:	popad
	ret
endp

;--------
proc line
;--------
	stdcall prtchr,0dh
	stdcall prtchr,0ah
	ret
endp

;IMPORT SECTION
data import
     library msvcrt,'msvcrt.dll'
	import msvcrt,\
	   system,'system',exit,'exit',\
	   putchar,'putchar',getchar,'getchar'
end data

;fasmnewbie / soffianabdulrasad @ gmail . com
;Last updated: October 6th, 2014
