format elf64 executable 3
include 'import64.inc' 
interpreter '/lib64/ld-linux-x86-64.so.2' 
needed 'libc.so.6'
import 	exit,printf,scanf,\
	__errno_location,strerror

EOF = -1
segment executable 
entry start

start:
	mov rdi,fmtin
	mov rsi,var
	xor eax,eax
	call [scanf]
	cmp rax,EOF
	je .error_exit
	cmp rax,1
	jne .error_exit
	mov ecx , 10000
.L0:
	fld dword[var]
	mov rdi,buf
	push rcx
	call PrintFloat
	pop rcx
	loop .L0
	
	mov rsi,buf
	mov rdi,fmtout
	movss xmm0,[var]
	cvtss2sd xmm0,xmm0
	mov eax,1
	call [printf]
	
	xor edi,edi
	call [exit] 

.error_exit:
	call [__errno_location]
	mov edi,[rax]
	call [strerror]

	mov rdi,fmterr
	mov rsi,rax
	xor eax,eax
	call [printf]

	xor edi,edi
	call [exit]
	
; prints float in st0 to string at rdi 
PrintFloat: 
virtual at rsp 
.x       dq ?,?,?,? 
.d       dq ? 
.ex      dq ? 
.ii      dq ? 
.message dq ? 
.rsi     dq ? 
.rbp     dq ? 
.rbx     dq ? 
.r12     dq ? 
.r13     dq ? 
.s       dq ? 
end virtual 

                        sub  rsp,8*(65) 
                        mov  [.rsi],rsi 
                        mov  [.rbp],rbp 
                        mov  [.rbx],rbx 
                        mov  [.r12],r12 
                        mov  [.r13],r13 

                        fld  st0 
                       fstp  tword[.x] 
                      movzx  edx,word[.x+8] 
                        mov  ecx,edx 
                        and  ecx,0x08000 
                         jz  @f 
                       fchs 
                        mov  al,'-' 
                      stosb 
                      @@: 
                        and  edx,0x07FFF 
                         jz  .zero 
                        cmp  edx,0x07FFF 
                         je  .inf 
                        mov  [.message],rdi 

                       fld1 
                       fld1 
                       fadd  st0,st0 
                      fdivp  st1,st0 

                     fldlg2 
                       fild  qword[OutputBits] 
                      fmulp  st1,st0 
                      faddp  st1,st0 
                      fistp  qword[.d] 
                        mov  eax,1 
                        mov  qword[.ex],rax 
                     fldlg2 
                        fld  st1 
                      fyl2x 
                      fistp  qword[.ii] 
                        lea  rdi,[.x] 
                       call  CVT_f80_F192 
                        lea  rdi,[.s] 
                        lea  rsi,[.x] 
                        mov  rbx,[.ex] 
                        add  rbx,[.d] 
                        sub  rbx,[.ii] 
                       call  POWMUL_F192 
                        sub  rax,1 
                        sub  rax,rbx 
                        add  rdi,[.d] 
                 @@:    sub  rdi,1 
                        cmp  byte[rdi],'0' 
                         je  @b 
                        add  rdi,1 

                        mov  rcx,rdi 
                        lea  rsi,[.s] 
                        mov  rdi,[.message] 
                        sub  rcx,rsi 

                        cmp  rax,16 
                         jg  .print_w_exp 
                        cmp  rax,-8 
                         jl  .print_w_exp 
                       test  rax,rax 
                         jz  .print_no_exp 
                         js  .print_neg_exp 
                .print_pos_exp: 
                        cmp  eax,ecx 
                        lea  eax,[rax+1] 
                        jae  @f 
                       push  rax 
                       push  rcx 
                        mov  ecx,eax 
                  rep movsb 
                        mov  al,'.' 
                      stosb 
                        pop  rcx 
                        pop  rax 
                        sub  ecx,eax 
                  rep movsb 
                        jmp  .done 
             @@:        sub  eax,ecx 
                  rep movsb 
                        mov  ecx,eax 
                        mov  al,'0' 
                  rep stosb 
                        mov  al,'.' 
                      stosb 
                        jmp  .done 

                .print_neg_exp: 
                       push  rcx 
                       push  rax 
                        mov  ax,'0.' 
                      stosw 
                        pop  rcx 
                        not  rcx 
                        mov  al,'0' 
                  rep stosb 
                        pop  rcx 
                  rep movsb 
                        jmp  .done 

                .print_no_exp: 
                      movsb 
                        sub  ecx,1 
                        mov  al,'.' 
                      stosb 
                  rep movsb 
                        jmp  .done 

                .print_w_exp: 
                      movsb 
                        sub  ecx,1 
                       push  rax 
                        mov  al,'.' 
                      stosb 
                  rep movsb 
                        mov  al,'e' 
                      stosb 
                        pop  rax 
                       call  PrintInteger 
                       ; jmp  .done 

   .done: 
                        mov  rsi,[.rsi] 
                        mov  rbp,[.rbp] 
                        mov  rbx,[.rbx] 
                        mov  r12,[.r12] 
                        mov  r13,[.r13] 
                        add  rsp,8*65 
                        ret 


  .zero:                mov  ax,'0.' 
                       fstp  st0 
                      stosw 
                        jmp  .done 

 .inf:                  mov  rax,[.x] 
                       fstp  st0 
                       test  rax,rax 
                        jns  .Nan 
                        shl  rax,1 
                        jnz  .Nan 
                        mov  eax,'inf' 
                      stosd 
                        sub  rdi,1 
                        jmp  .done 

        .Nan: 
                        mov  eax,'NaN' 
                      stosd 
                        sub  rdi,1 
                        jmp  .done 



CVT_f80_F192: ; pop fpu stack to rdi 
                        sub  rsp,8*5 
                       fstp  tword[rsp] 
                        xor  eax,eax 
                        mov  [rdi+8*0],rax 
                        mov  [rdi+8*1],rax 
                      movsx  ecx,word[rsp+8] 
                        and  ecx,0x7FFFF 
                        sub  rcx,16383 
                        mov  rax,qword[rsp+0] 
                        mov  [rdi+8*2],rax 
                        mov  [rdi+8*3],rcx 
                        add  rsp,8*5 
                        ret 






POWMUL_F192:    ;  [rdi] = string(round([rsi] * 10^rbx)) 

virtual at rsp 
  .base  dq ?,?,?,? 
  .unity dq ?,?,?,? 
  .rdi   dq ? 
  .rsi   dq ? 
  .rbx   dq ? 
end virtual 
                        sub  rsp,8*13 
                        mov  [.rdi],rdi 
                        mov  [.rbx],rbx 
                        mov  [.rsi],rsi 

                     movaps  xmm0,dqword[Bases+32*1+16*0] 
                     movaps  xmm1,dqword[Bases+32*1+16*1] 
                     movups  dqword[.unity+16*0],xmm0 
                     movups  dqword[.unity+16*1],xmm1 

                        mov  rax,qword[OutputBase] 
                       test  rbx,rbx 
                         jz  .zero 
                        jns  @f 
                        neg  rax 
                        neg  rbx 
                   @@: 
                        shl  rax,5 
                     movaps  xmm0,dqword[Bases+rax+16*0] 
                     movaps  xmm1,dqword[Bases+rax+16*1] 
                     movups  dqword[.base+16*0],xmm0 
                     movups  dqword[.base+16*1],xmm1 

                       test  rbx,rbx 
                         jz  .w3 
              .w1:      shr  rbx,1 
                        jnc  .w2 
                        lea  rdi,[.unity] 
                        lea  rsi,[.base] 
                       call  MUL_F192 
              .w2:     test  rbx,rbx 
                         jz  .w3 
                        lea  rdi,[.base] 
                        lea  rsi,[.base] 
                       call  MUL_F192 
                        jmp  .w1 
              .w3: 
        .zero:          lea  rdi,[.unity] 
                        mov  rsi,[.rsi] 
                       call  MUL_F192 

                        ; rax = sign bit 
                        ; ecx = exponent 

                        sub  rcx,2*64-1 
                        jns  .error 

                @@:     shr  r13,1 
                        rcr  r12,1 
                        rcr  r11,1 
                        add  rcx,1 
                        jnz  @b 

                        cmp  r11,rax 
                         jb  .store 
                         ja  .roundup 
                       test  r12,1 
                         jz  .store 
     .roundup:          add  r12,1 
                        adc  r13,0 
    .store: 
                        mov  rdi,[.rdi] 
                        mov  rbp,rsp 
        .ComputeDigits: xor  edx,edx 
                        mov  rax,r13 
                        div  qword[OutputBase] 
                        mov  r13,rax 
                        mov  rcx,rax 
                        mov  rax,r12 
                        div  qword[OutputBase] 
                        mov  r12,rax 
                         or  rcx,rax 
                       push  rdx 
                        jnz  .ComputeDigits 
        .PrintDigits:   pop  rax 
                        add  al,'0' 
                      stosb 
                        cmp  rsp,rbp 
                         jb  .PrintDigits 

                        mov  rax,rdi 
                        sub  rax,[.rdi] 
                        mov  rdi,[.rdi] 
                        mov  rsi,[.rsi] 
                        mov  rbx,[.rbx] 

                        add  rsp,8*13 
                        ret 

.error:                int3 


MUL_F192:               mov  rcx,[rsi+8*3] 
                        add  rcx,[rdi+8*3] 

                        mov  rax,[rsi+8*0] 
                        mul  qword[rdi+8*0] 
                        mov  r8,rax 
                        mov  r9,rdx 
                        xor  r10,r10 
                        xor  r11,r11 
                        xor  r12,r12 
                        xor  r13,r13 

                        mov  rax,[rsi+8*1] 
                        mul  qword[rdi+8*0] 
                        add  r9,rax 
                        adc  r10,rdx 
                        adc  r11,0 
                        mov  rax,[rsi+8*0] 
                        mul  qword[rdi+8*1] 
                        add  r9,rax 
                        adc  r10,rdx 
                        adc  r11,0 

                        mov  rax,[rsi+8*2] 
                        mul  qword[rdi+8*0] 
                        add  r10,rax 
                        adc  r11,rdx 
                        adc  r12,0 
                        mov  rax,[rsi+8*1] 
                        mul  qword[rdi+8*1] 
                        add  r10,rax 
                        adc  r11,rdx 
                        adc  r12,0 
                        mov  rax,[rsi+8*2] 
                        mul  qword[rdi+8*0] 
                        add  r10,rax 
                        adc  r11,rdx 
                        adc  r12,0 

                        mov  rax,[rsi+8*2] 
                        mul  qword[rdi+8*1] 
                        add  r11,rax 
                        adc  r12,rdx 
                        adc  r13,0 
                        mov  rax,[rsi+8*1] 
                        mul  qword[rdi+8*2] 
                        add  r11,rax 
                        adc  r12,rdx 
                        adc  r13,0 

                        mov  rax,[rsi+8*2] 
                        mul  qword[rdi+8*2] 

                        add  r12,rax 
                        adc  r13,rdx 


                         js  @f 
                        shl  r8,1 
                        rcl  r9,1 
                        rcl  r10,1 
                        rcl  r11,1 
                        rcl  r12,1 
                        rcl  r13,1 
                        jmp  .round 
                  @@:   add  rcx,1 

    .round:             xor  eax,eax 
                        bts  rax,63 
                        cmp  r10,rax 
                         jb  .store 
                         ja  .roundup 
                       test  r11,1 
                         jz  .store 
     .roundup:          add  r11,1 
                        adc  r12,0 
                        adc  r13,0 
                        jnc  .store 
                        rcr  r13,1 
                        rcr  r12,1 
                        rcr  r11,1 
                        add  rcx,1 

    .store:             mov  [rdi+8*0],r11 
                        mov  [rdi+8*1],r12 
                        mov  [rdi+8*2],r13 
                        mov  [rdi+8*3],rcx 
                        ret 


align 32 
dq 0xcccccccccccccccc, 0xcccccccccccccccc, 0xcccccccccccccccc, -4 
dq 0x8e38e38e38e38e38, 0x38e38e38e38e38e3, 0xe38e38e38e38e38e, -4 
dq 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, -3 
dq 0x4924924924924924, 0x2492492492492492, 0x9249249249249249, -3 
dq 0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa, -3 
dq 0xcccccccccccccccc, 0xcccccccccccccccc, 0xcccccccccccccccc, -3 
dq 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, -2 
dq 0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa, -2 
dq 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, -1 
dq 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, 0 
Bases: dq ?,?,?,? 
dq 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, 0 
dq 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, 1 
dq 0x0000000000000000, 0x0000000000000000, 0xc000000000000000, 1 
dq 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, 2 
dq 0x0000000000000000, 0x0000000000000000, 0xa000000000000000, 2 
dq 0x0000000000000000, 0x0000000000000000, 0xc000000000000000, 2 
dq 0x0000000000000000, 0x0000000000000000, 0xe000000000000000, 2 
dq 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, 3 
dq 0x0000000000000000, 0x0000000000000000, 0x9000000000000000, 3 
dq 0x0000000000000000, 0x0000000000000000, 0xa000000000000000, 3 


PrintInteger:       ; rax: number 
                       push  rbp rcx rdx 
                        mov  rbp,rsp 
                       test  rax,rax 
                        jns  .l1 
                        mov  byte[rdi],'-' 
                        add  rdi,1 
                        neg  rax 
                .l1:    xor  edx,edx 
                        div  qword[OutputBase] 
                       push  rdx 
                       test  rax,rax 
                        jnz  .l1 
                .l2:    pop  rax 
                        add  al,'0' 
                      stosb 
                        cmp  rsp,rbp 
                         jb  .l2 
                        pop  rdx rcx rbp 
                        ret
	
segment writeable
fmtin db '%f',0
fmtout db '%s %f',0xa,0
fmterr db '%s',0xa,0
align 4
var rd 1
align 8
OutputBits dq 64
OutputBase dq 10
buf rb 256
