format pe console
include 'win32axp.inc'

;Sample run: Find square root
stdcall getflt,val
fld [val]
fabs  ;without this, HUGE headache
fsqrt ;if entered value is negative
fstp [ans]
stdcall prtflt,[ans],0,0

invoke system,"pause>nul"
invoke exit,0
val dd 0.0
ans dd 0.0

;--------------------------------------
;Float to string
;DISPLAY FP (REAL4)
;info : [dd] (initialize to 0.0)
;     : reg32,fp constant
;     : Takes and displays e format
;pt   : Decimal places (max=6) rounding
;     : 0 - no rounding
;nline: 0-no line
;--------------------------------------
proc prtflt,info,pt,nline
	locals
	   tst dd 1,1000000,100000,\
		  10000,1000,100,10
	   s db 14 dup (?)
	   frac db 0	;marker
	   both db 0	;marker
	   big db 0	;marker
	   small db 0	;marker
	   large db 0	;marker
	   num dd 0	;integral part
	   num2 dd 0	;fraction part
	   idx dd 0	;for small
	   ndx dd 1	;For big and large
	   exponent dd 0
	   mantissa dd 0.0
	   copy dd 0.0
	   y dd 10.0
	   one dd 1.0
	endl
	pushad
	mov eax,[info]
	.if eax=0 | eax=80000000h
	    jmp .w  ;case of signed 0.0
	.endif
.back:	finit
	mov [copy],eax
	fld [copy]
	test eax,80000000h
	     jns .p
	fchs
.p:	fxtract
	fstp [mantissa]
	fistp [exponent]
	mov ecx,[exponent]
	mov edi,[mantissa]
	and edi,7fffffh
	bts edi,23
	bsr esi,edi
	xor eax,eax
	cmp [idx],1   ;if returning
	    je .dnorm
	test ecx,ecx
	     js .small
	cmp ecx,22
	    ja .norm
;DENORMALIZE ----------------
;Get positional values (base-2)
.dnorm: bt edi,esi
	   jc .plus
.ok:	dec esi
	test ecx,ecx
	     jz .big
	dec ecx
	jmp .dnorm
.plus:	mov edx,1
	shl edx,cl
	add eax,edx
	jmp .ok
;NORMALIZE -----------------
;Get: values x 2^exp * mantissa
.norm:	fld1 ;2^ecx
.x:	f2xm1
	fst st1
	fadd st0,st1
	loop .x
	fld [mantissa]
	fmul st0,st1
	fstp [num]
	mov eax,[num]
	mov [large],1
;FOR BIG EXPONENT------------
;Find E and normalize to x.xxxxx
.big:	mov [num],eax
	xor eax,eax
	cmp [num],10000000
	    jb .frctn
.f:	fld [y]
	fld [num]
	fdiv st0,st1
	fst [num]
	fcomp [y]
	fstsw ax
	sahf
	   jb .g
	inc [ndx]
	finit
	jmp .f
.g:	mov eax,[num]
	mov [big],1  ;marker up
	jmp .back
;FOR SMALL NEGATIVE EXPONENT---------
;Find E- and normalize to x.xxxxx
.small: mov eax,[info]
	mov [num2],eax
	test eax,eax
	     jns .s
	fld [num2]
	fchs ;change sign
	fstp [num2]
.s:	fld [num2]
	fmul [y]
	fst [num2]
	inc [idx]
	fcomp [one]
	fstsw ax
	sahf
	jae .k
	finit
	jmp .s
.k:	cmp [idx],6
	    jl .nexp
	fld [num2]
	fstp [copy]
	mov eax,[copy]
	mov [small],1  ;marker up
	jmp .back
;NEGATIVE EXPONENT-------------------
.nexp:	neg ecx
	shr edi,cl
	bsr esi,edi
	dec ecx
	xor eax,eax
;FRACTION ---------------------------
.frctn: bt edi,esi
	   jc .pow1
.ko:	inc ecx
	test esi,esi
	     jz .round
	dec esi
	jmp .frctn
.pow1:	mov edx,5000000 ;negative pow of 2
	shr edx,cl	;at position CL
	add eax,edx
	jmp .ko
;DONE & ROUNDING --------------------
.round: mov [num2],eax
	;cmp [big],1  ;don't round large exp?
	;    je .w ;i don't know
	;Rounding -------------------
	mov edx,[pt]
	.if edx > 6
	    xor edx,edx
	.endif
	fild [tst+edx*4]
	fild [num2]
	fdiv st0,st1
	frndint
	fist [num2]
	fild [tst+edx*4]
	fmul st0,st1
	fistp [num2]
	.if edx = 1 & [num2] >= 10000000
	    mov [num2],eax
	.endif
	;----------------------------
.w:	mov eax,[info]
	mov ecx,10
	lea edi,[s]
	test eax,eax
	     jns .print
	mov al,'-'
	stosb
;DISPLAY & FORMATING-----------------
.print: xor esi,esi
	mov eax,[num]
	cmp [frac],1
	    jne .start
	mov eax,[num2]
.start: xor edx,edx
	div ecx
	push edx
	inc esi
	.if [frac] ;zero padding
	    cmp esi,7
	    je .prt
	.else
	    test eax,eax
	    jz .prt
	.endif
	jmp .start
.prt:	pop eax
	add al,30h
	stosb
.m:	dec esi
	test esi,esi
	    jz .what
	jmp .prt
.what:	cmp [both],1
	    je .quit
	.if ~ [frac]
	    mov al,'.'
	    stosb
	    mov [frac],1
	    jmp .print
	.endif
	;Display Scientific E ------------
	.if [big] | [large] | [small]
	    mov [both],1
	    mov [frac],0
	    .if [small]
		mov ax,'e-'
		stosw
		mov eax,[idx]
	    .else
		mov ax,'e+'
		stosw
		mov eax,[ndx]
	    .endif
	    jmp .start
	.endif
	;-------------------------
.quit:	xor al,al  ;terminal byte
	stosb
	xor edi,edi
.disp:	mov al,[s+edi]
	test al,al
	     jz .out
	.if al='.' & [pt]
	    mov esi,7
	    sub esi,[pt]
	    mov ebx,[pt]
	    add ebx,edi
	.endif
	.if [pt] & ebx=edi
	    add edi,esi ;ignore trailing 0s
	.endif
.h:	cinvoke putchar,eax
	inc edi
	jmp .disp
.out:	.if [nline]
	    cinvoke putchar,0d0ah
	.endif
	popad
	ret
endp

;---------------------------------
;String to Float
;GET FP (REAL4) FROM KEYBOARD
;Convert and save to info
;info: dd (initialize to 0.0)
;    : Does not take e-format
;    : Must use FP format as input
;---------------------------------
proc getflt,info
	locals
	     m dd 0
	     x dd 0.0
	     pow10 dd 10.0
	     power dd 1.0
	     val dd 0.0
	     sgn db 0
	endl
	xor esi,esi
	xor edi,edi
.intg:	cinvoke getchar
	.if eax = 0ah
	    jmp .start
	.endif
	.if al = '-'
	    mov dword[sgn],1 ;DON'T increment
	    jmp .intg
	.endif
	.if ~ al = '.'
	    sub eax,30h
	.else
	    mov edi,esi
	    jmp .intg
	.endif
	push eax
	inc esi
	jmp .intg
;----------------------
.start: finit
	pop [m]
	fild [m]
	fstp [val]
	mov ecx,esi
	dec ecx
.rr:	finit
	fld [pow10] ;10^
	fld [power]
	fmul st0,st1
	fst [power]
	pop [m]
	fild [m]
	fmul st0,st1
	fld [val]
	fadd st0,st1
	fstp [val]
	loop .rr
;----------------------
	mov ecx,esi
	sub ecx,edi  ;Divide by decimal places
.d:	fld [pow10]  ;found in ecx
	fld [val]
	fdiv st0,st1
	fstp [val]
	finit
	loop .d
;----------------------
.quit:	mov eax,[info]
	mov ecx,[val]
	.if [sgn]
	    bts ecx,31
	.endif
	mov dword[eax],ecx
	ret
endp

data import
     library msvcrt,'msvcrt.dll'
     import msvcrt,\
	    system,'system',exit,'exit',\
	    putchar,'putchar',getchar,'getchar'
end data

;September 7th, 2014
;fasmnewbie / soffianabdulrasad @ gmail. com