flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
fasmnewbie 04 Sep 2014, 11:21
Just in case if u want to download and try it... (refer to the latest attachment below)
Last edited by fasmnewbie on 06 Sep 2014, 06:57; edited 1 time in total |
|||
![]() |
|
fasmnewbie 05 Sep 2014, 19:26
A slightly better prtflt version, with character printing is done towards the end, plus fixing a precision bug when entering data such as "33.99"
Code: proc prtflt,info,pt,nline locals s db 13 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 tst dd 1,1000000,100000,\ 10000,1000,100,10,1 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 .if [idx] ;if returning jmp .dnorm .endif test ecx,ecx js .small .if ecx > 22 ;> 30 mov [large],1 jmp .norm .endif ;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 ;answer in ST0 fld [mantissa] fmul st0,st1 fstp [num] mov eax,[num] ;FOR BIG EXPONENT------------ ;Find E and normalize to x.xxxxx .big: mov [num],eax .if [num] < 1000000 xor eax,eax jmp .frctn .endif .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] fcomp [y] fstsw ax sahf jae .k finit inc [idx] jmp .s .k: .if signed[idx] < 6 jmp .nexp .endif fld [y] fld [num2] fdiv st0,st1 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 ;.if [big] ;don't round large exp? ; jmp .w ;i don't know ;.endif ;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 xor edi,edi ;for string test eax,eax jns .print mov [s+edi],'-' inc edi ;DISPLAY & FORMATING----------------- .print: xor esi,esi .if [frac] mov eax,[num2] .else mov eax,[num] .endif .start: xor edx,edx div ecx push edx inc esi .if [frac] ;leading-zero padding cmp esi,7 je .a .else test eax,eax jz .prt .endif jmp .start .a: .if [pt] ;Trailing zero truncate mov ebx,dword[pt] .endif .prt: pop eax .if [frac] & [pt] ;if passed decimal point test ebx,ebx ;keeps popping stack jz .m ;don't print .endif add al,30h mov byte[s+edi],al inc edi dec ebx .m: dec esi test esi,esi jz .what jmp .prt .what: .if [both] ;if both done jmp .quit .endif .if ~ [frac] mov byte[s+edi],'.' inc edi mov [frac],1 jmp .print .endif ;Display Scientific E ------------ .if [big] | [large] | [small] mov [both],1 mov [frac],0 .if [small] mov word[s+edi],'e-' add edi,2 mov eax,[idx] .else mov word[s+edi],'e+' add edi,2 mov eax,[ndx] .endif jmp .start .endif ;--------------------------------- .quit: dec edi xor esi,esi .disp: mov al,byte[s+esi] cinvoke putchar,eax cmp esi,edi je .out inc esi jmp .disp .out: .if [nline] cinvoke putchar,0d0ah .endif popad ret endp |
|||
![]() |
|
fasmnewbie 05 Sep 2014, 19:42
The entire file... with corrected prtflt and unverified getflt...
Code: format pe console include 'win32axp.inc' mov ecx,8 xor esi,esi .go: stdcall prtflt,[v+esi*4],0,1 ;no precision stdcall prtflt,[v+esi*4],1,1 ;1 precision stdcall prtflt,[v+esi*4],3,1 ;3 precisions stdcall prtflt,[v+esi*4],5,1 ;5 precisions inc esi loop .go .done: invoke system,"pause>nul" invoke exit,0 ;Test Data v dd 4294967295.0 dd 33.99 dd -31.221336 dd 15.0356565 dd 1.18e-38 dd 0.002654 dd -0.00000000004567 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 s db 13 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 tst dd 1,1000000,100000,\ 10000,1000,100,10,1 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 .if [idx] ;if returning jmp .dnorm .endif test ecx,ecx js .small .if ecx > 22 ;> 30 mov [large],1 jmp .norm .endif ;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 ;answer in ST0 fld [mantissa] fmul st0,st1 fstp [num] mov eax,[num] ;FOR BIG EXPONENT------------ ;Find E and normalize to x.xxxxx .big: mov [num],eax .if [num] < 1000000 xor eax,eax jmp .frctn .endif .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] fcomp [y] fstsw ax sahf jae .k finit inc [idx] jmp .s .k: .if signed[idx] < 6 jmp .nexp .endif fld [y] fld [num2] fdiv st0,st1 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 ;.if [big] ;don't round large exp? ; jmp .w ;i don't know ;.endif ;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 xor edi,edi ;for string test eax,eax jns .print mov [s+edi],'-' inc edi ;DISPLAY & FORMATING----------------- .print: xor esi,esi .if [frac] mov eax,[num2] .else mov eax,[num] .endif .start: xor edx,edx div ecx push edx inc esi .if [frac] ;leading-zero padding cmp esi,7 je .a .else test eax,eax jz .prt .endif jmp .start .a: .if [pt] ;Trailing zero truncate mov ebx,dword[pt] .endif .prt: pop eax .if [frac] & [pt] ;if passed decimal point test ebx,ebx ;keeps popping stack jz .m ;don't print .endif add al,30h mov byte[s+edi],al inc edi dec ebx .m: dec esi test esi,esi jz .what jmp .prt .what: .if [both] ;if both done jmp .quit .endif .if ~ [frac] mov byte[s+edi],'.' inc edi mov [frac],1 jmp .print .endif ;Display Scientific E ------------ .if [big] | [large] | [small] mov [both],1 mov [frac],0 .if [small] mov word[s+edi],'e-' add edi,2 mov eax,[idx] .else mov word[s+edi],'e+' add edi,2 mov eax,[ndx] .endif jmp .start .endif ;--------------------------------- .quit: dec edi xor esi,esi .disp: mov al,byte[s+esi] cinvoke putchar,eax cmp esi,edi je .out inc esi 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 eax = '-' inc [sgn] 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 [eax],ecx ret endp data import library msvcrt,'msvcrt.dll' import msvcrt,\ system,'system',exit,'exit',\ putchar,'putchar',getchar,'getchar' end data With following output... Code: 4.2949665e+9 4.3e+9 4.295e+9 4.29497e+9 33.9900014 33.9 33.990 33.99000 -31.2213361 -31.2 -31.221 -31.22134 15.0356567 15.0 15.036 15.03566 1.1799995e-38 1.2e-38 1.180e-38 1.18000e-38 0.0026535 0.0 0.003 0.00265 -4.5669986e-11 -4.6e-11 -4.567e-11 -4.56700e-11 -0.0000000 -0.0 -0.000 -0.00000 Need advise whether these precision are within acceptable range and any other issues that I am not aware of. EDIT: download deleted. See below. Last edited by fasmnewbie on 11 Sep 2014, 16:57; edited 1 time in total |
|||
![]() |
|
fasmnewbie 06 Sep 2014, 20:51
A little correction to prtflt- Fixing incorrect display when data is 1000000.00.
Plus, a little optimization and code clean-up. Code: 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 ;answer in ST0 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 mov eax,[num2] 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 ;SAVE STRING TO STACK .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 ;CONVERT TO ASCII & SAVE TO STRING .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 ;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 ;DISPLAY ------------------------- .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 ;trailing 0s .endif .h: cinvoke putchar,eax inc edi jmp .disp .out: .if [nline] cinvoke putchar,0d0ah .endif popad ret endp With these output Code: 56.9900014 56.9900 56.9 1.1799995e-38 1.1800e-38 1.2e-38 1234567.0000000 1234567.0000 1234567.0 1.0000000e+7 1.0000e+7 1.0e+7 -36.8886984 -36.8887 -36.9 -4.5669986e-11 -4.5670e-11 -4.6e-11 |
|||
![]() |
|
fasmnewbie 07 Sep 2014, 07:56
Final update...hopefully. With minor fix to getflt
Below is a test when dealing with FSQRT. In this case, the value must be made absolute explicitly because the routines won't do it (I am not sure if ignoring absolute values is a good approach though). For other cases, it runs just fine so far. Code: 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 Output Code: -34.245 ;User input 5.8519228
|
|||||||||||
![]() |
|
fasmnewbie 11 Sep 2014, 16:54
After some light reading on Agner Fog's material, I found out that instruction F2XM1 has a large latency. You can change the NORMALIZE part from this;
Code: ;NORMALIZE ----------------- ;Get: values x 2^exp * mantissa .norm: fld1 ;2^ecx .x: f2xm1 fst st1 fadd st0,st1 loop .x ;answer in ST0 fld [mantissa] fmul st0,st1 fstp [num] mov eax,[num] mov [large],1 To this... Code: ;NORMALIZE ----------------- ;Get: mantissa * 2^exp .norm: mov [copy],ecx fild [copy] ;exp fld1 fscale fst [copy] fld [mantissa] fmul st0,st1 fstp [num] mov eax,[num] mov [large],1 Sorry for the naivity. I am a learner myself. |
|||
![]() |
|
fasmnewbie 11 Sep 2014, 17:52
This is a fully working, interactive and complete program and routines demonstrating FPU-based conversion (float-to-string and string-to-float), plus a prtstr as a bonus. No other external dependencies except putchar and getchar.
Code: format pe console include 'win32axp.inc' stdcall prtstr,"Hello folks. This is a test program.\n" stdcall prtstr,"Enter a radian in FP value and I'll\nconvert it to SINE" stdcall prtstr,"\n\nRADIAN? " stdcall getflt,rad finit fld [rad] fsin fstp [ans] stdcall prtstr,"SINE is: " stdcall prtflt,[ans],4,1 ;4 precision points,new line stdcall prtstr,"Done.\n" invoke system,"pause>0" invoke exit,0 rad dd 0.0 ans dd 0.0 Output: Code: Hello folks. This is a test program. Enter a radian in FP value and I'll convert it to SINE RADIAN? 34.5224 ;user input SINE is: 0.0351 Done. Hope this can bring benefits to newbies. New file download here. Further bug fixes and optimization is up to you. LOL EDIT: a little correction LOL. Just embracing pushad and popad around putchar.
|
|||||||||||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.