format pe console
include 'win32axp.inc'

stdcall getflt,rad
stdcall prtflt,[rad],0,1  ;4 precision points,new line

invoke system,"pause>0"
invoke exit,0

rad 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
;Note : Avoid using 'raw' EBX as argument
;pt   : Decimal places (max=6) rounding
;     : 0 - no rounding
;nline: 0-no line
;--------------------------------------
proc prtflt,info,pt,nline   ;659 bytes
	locals
	   tst dd 1,1000000,100000,\
		  10000,1000,100,10
	   frac db 0	;marker
	   subn 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
	   expn dd 0
	   mant dd 0.0
	   copy dd 0.0
	   y dd 10.0
	   one dd 1.0
	endl
	pushad
	mov eax,[info]
	test eax,eax
	     jns .d
	pushad
	cinvoke putchar,dword '-'
	popad
.d:	test eax,eax	 ;
	     jz .print	 ;case: signed 0.0
	cmp eax,-1	 ;
	    je .print	 ;
.back:	finit
	mov [copy],eax
	fld [copy]
	fabs
.p:	fxtract
	fstp [mant]
	fistp [expn]
	mov ecx,[expn]
	mov edi,[mant]
	and edi,7fffffh
	bts edi,23
	bsr esi,edi
	xor eax,eax
	cmp [idx],1
	    je .dnorm
	test ecx,ecx
	     js .small
	mov edx,ecx
	cmp ecx,22
	    ja .norm
;DENORMALIZE ----------------
.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: mantissa * 2^exp
.norm:	mov [copy],ecx
	fild [copy] ;exp
	fld1
	fscale
	fst [copy]
	fld [mant]
	fmul st0,st1
	fstp [num]
	mov eax,[num]
;FOR BIG EXPONENT------------
.big:	mov [num],eax
	xor eax,eax
	cmp [num],10000000
	    jb .frctn
.f:	fld [num]
	fdiv [y]
	fst [num]
	fcomp [y]
	fstsw ax
	sahf
	jb .g
	inc [ndx]
	finit
	jmp .f
.g:	mov eax,[num]
	mov [subn],1  ;marker up
	jmp .back
;FOR SMALL NEGATIVE EXPONENT---------
.small: mov eax,[info]
	mov [num2],eax
.s:	fld [num2]
	fabs
	fmul [y]
	fst [num2]
	inc [idx]
	fcomp [one]
	fstsw ax
	sahf
	jae .k
	finit
	jmp .s
.k:	cmp [idx],6
	    jl .nexp
	mov eax,[num2]
	mov [subn],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
	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]
	cmp edi,1
	    jne .print
	cmp [num2],10000000
	    jb .print
	mov [num2],eax
;DISPLAY & FORMATING-----------------
.print: xor esi,esi
	mov ecx,[num]
	cmp [frac],1
	    jne .start
	mov ecx,[num2]
.start: mov eax,ecx
	mov edi,0cccccccdh
	mul edi
	shr edx,3
	mov eax,edx
	mov edi,edx
	mov edx,10
	mul edx
	sub ecx,eax
	push ecx
	mov ecx,edi
	inc esi
	.if [frac]=1 ;zero padding
	    .if esi = 7
		xor edi,edi
		jmp .prt
	    .endif
	.else
	    test edi,edi
	    jz .prt
	.endif
	jmp .start
.prt:	pop eax
	.if [frac]=1 & [pt]
	    inc edi	 ;keep popping off
	    cmp [pt],edi ;trailing-0
	    jb .m
	.endif
	add al,30h
	pushad
	cinvoke putchar,eax
	popad
.m:	dec esi
	test esi,esi
	     jz .what
	jmp .prt
.what:	cmp [frac],2 ;if both done
	    je .quit
	.if ~ [frac]
	    pushad
	    cinvoke putchar,dword '.'
	    popad
	mov [frac],1
	    jmp .print
	.endif
	;Scientific E -------
	.if [subn]
	    inc [frac]
	    pushad
	    cinvoke putchar,dword 'e'
	    popad
	    .if [idx]
		pushad
		cinvoke putchar,dword '-'
		popad
		mov ecx,[idx]
	    .else
		pushad
		cinvoke putchar,dword '+'
		popad
		mov ecx,[ndx]
	    .endif
	    jmp .start
	.endif
.quit:	.if [nline]
	    cinvoke putchar,dword 0dh
	    cinvoke putchar,dword 0ah
	.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
.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 [pow10]
	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
.d:	fld [pow10]
	fld [val]
	fdiv st0,st1
	fstp [val]
	finit
	loop .d
;----------------------
.quit:	mov eax,[info]
	mov ecx,[val]
	.if [sgn]
	    bts ecx,31
	.endif
	mov [eax],ecx
	ret
endp

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
	cinvoke putchar,dword[esi]
	inc esi
	jmp .prt
.ok:	cinvoke putchar,dword 0dh
	cinvoke putchar,dword 0ah
	add esi,2
	jmp .prt
.done:	popad
	ret
endp

data import
     library msvcrt,'msvcrt.dll'
     import msvcrt,\
	    system,'system',exit,'exit',\
	    putchar,'putchar',getchar,'getchar'
end data

;fasmnewbie / soffianabdulrasad @ gmail . com
;Sept 11th, 2014



