flat assembler
Message board for the users of flat assembler.

Index > Main > FASMLIB (FASM Standard Library Project)

Goto page Previous  1, 2, 3, 4, 5  Next
Author
Thread Post new topic Reply to topic
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
strlib almost done...
Post 30 Nov 2005, 17:31
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
strlib done

1. I have been butchering on privalov's stdcall macros and i added nice macro "libcall" to call library routines. It supports nested calls with error handling, so you can do things like:
Code:
libcall <str.cat <libcall str.catchar <libcall str.dup "SEGMENT">,dword ':'>,"OFFSET"
jc .error ;tests error for all three calls    

It has more modifications, like it declares string arguments with "idata" block, and it doesn't destroy any register on "addr" operator. This causes slower compilation and execution, but is much nicer to use. And we need our own call macro to make FASMLIB portable

2. I found problem with current idata/endg macros. If they are used inside macro, you have to escape "endg" which is very confusing and "unsyntactical":
Code:
macro a {
  idata
    db 0
  \endg 
}    

Also opening "{" is never escaped (not really a problem, but it isn't nice). I think this would cause lot of problems, so i decided to let user manually enclose block in {}s, like:
Code:
idata {db 0} ;one-line definitions weren't possible with old macros
macro a { 
  udata \{         ;escaping here looks more natural IMO
    mydata db 0
  \}
}    

It is more syntactical, more FASMy, more clear to use etc. etc. It's only disadvantabe is that it is breaking standard, but i think it is better to break standard soon than to stick with worser one. You can change code easily:
"idata" -> "idata {"
"udata" -> "udata {"
"endg" -> "}"

I will post code after few additional tests, maybe today at evening.
Post 05 Dec 2005, 11:18
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard
1. nice macro.
What about static variables in function declaration? Maybe you could improve 'proc' macro to add this feature?

2. What about
endg fix \{

?
Post 05 Dec 2005, 20:37
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
1. i plan to rewrite proc macro, but it can wait until we start support for other OSes which doesn't have procs. Anyway, i more like declaring it in "idata" block before procedure, remember fasm ideology - lot of power with SMALL SET OF RULES (in this case small set of preprocessor features). You don't have to learn so much things to be able to read code.

2. And what about (this is case under which i found this problem):
Code:
macro a { 
  macro b \{
    idata
      ..
    endg
  \}
}    
You can make "eng fix \\}", but what should be the maximal size to allow then? And second thing: why should we trick the solution, if we have clear one? Do you think that backward compatiblity is THAT important?
Post 05 Dec 2005, 21:59
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
sorry, forgot to upload new version. there you are...

note that there is drawback with new "libcall" macro. It pushes string arguments with idata block. But idata block is macro feature and determining if argument is string can be only done during assembling (please let me know if no). So i had to enclose all arguments (eg. strings and pushable) in idata and test them while assembling. code looks like this:
Code:
  libcall module.proc, 10, "aaaa"

  ... becomes ...

  ;second argument "aaaa"
  local ..string?00000001
  idata { 
    if "aaaa" eqtype ""
      ..string?00000001 db "aaaa",0
    end if }
  if "aaaa" eqtype ""
    push ..string?00000001
  else
    pushd "aaaa"
  end if

  ;first argument - 10
  local ..string?00000001
  ;idata block has to be defined for non-strings too. It won't declare
  ;any data but preprocess-time and assembly-time slowdown stays there
  idata {                          
    if 10 eqtype ""
      ..string?00000001 db "aaaa",0
    end if }
  if 10 eqtype ""
    push ..string?00000001
  else
    pushd 10
  end if
  call module.proc    


This could be solved if there was some way to determine if macro-argument is string, maybe something like match ='anything, arg {}, but i am lazy to try now.
Post 14 Dec 2005, 01:43
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
Error Numbers - breaking standards again

i was thinking about error numbers when libproc returns with CF=1. Of course it is easiest to make some global variable to hold last error number (like "err"). But problem is what will be the number. Two solutions i originally saw were these:

1. constant numbers (like in win32). They are simple, but problem is that if someone adds another module to library, he chooses these numbers himself, and if more such modules are used then these numbers can conflict.

2. numbers will be assigned by macro during assembling. This is nice, but it disallows using precompiled FASMLIB, you always need to recompile it to know numbers. Bad too.

I came up with another solution, very unusual, but it seems to me as best. Error number will be pointer to string holding error description. Like this:
Code:
 idata{ err_out_of_memory db "Out of memory",0 }
...
call [MemAlloc]
or eax,eax
jnc .noerror
stc
mov [err],err_out_of_memory
ret    
This ensures numbers are unique, unlike in 1., allows more modularity than 2. (err_ labels can be exported), and also removes need for additional call to some strerr().

what do you think about it?
Post 15 Dec 2005, 00:55
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard
very nice. So let's declare "errno" variable (name doesn't matter, errno is used by C library), and after calling a library function:

CF=0, [errno]=0 on success
CF=1, [errno]!=1 on failure

Then you check which error occured:

cmp [errno],err_out_of_memory
je (...)
cmp [errno],err_user_is_blonde
je (...)

etc.

Did you mean this? It is actually the same as 1), because in such situation error string addresses are constants Wink (only they will have to be relocated sometimes). You can even declare string names in uppercase, so user would feel that he deals with "usual" constants. I like this idea!
Post 15 Dec 2005, 09:01
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
decard: that's just what i meant, (except that CF=1, [errno]!=0, not 1 Wink )

but I don't want to use "errno" on purpose, in libc project C's error variable must be named somehow too. I could use other name for C's variable, but caller may want to call some libc procs too, and he need access to this variable, and i believe he won't like other name.

There is slight problem with relocation, in that case you would have pointers to error constants, so you can't do "cmp [errno],[err_out_of_memory]", and also this means some errors will have to be addressed and some (declared by caller) not. But i don't think anyone will use FASMLIB as external binary, there's no reason to do it. Code is small, compiling fast, and statically it's much faster too.
Post 15 Dec 2005, 11:24
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard
if some one would like to use FASMLIB as an external library, he can always use
mov eax,[errno]
cmp [err_out_of_memory],eax
or whatever. But this is only applies to DLLs. With COFF format (or any format that is linked before executing) "cmp [errno],err_out_of_memory" linker should relocate it for you.

You can name your variable "fliberr", or "flib_error", or something similar that indicates that this variable is part of FASMLIB.
Post 15 Dec 2005, 12:19
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
I was thinking about it, but why not just "err"? It will be probably very-often-used thing, and what else should be called "err" if not this? I think there won't be anything releated to error handling, that will be used more often than this variable, so let's give it the shortest name.
Post 15 Dec 2005, 12:34
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard
a few more letters don't mind. "err" sometimes can be used as local variable name, call it at least "flerror" or "fliberr".
Post 15 Dec 2005, 14:07
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
for local names you should use "." prefix. But you are right there should be something saying that this is FASMLIB's error, it isn't only interface caller is going to use. But if i imagine how often will i type it, i really dislike longer name like systematic one - (fasmlib.err). How about "flerr", or "errfl". Problem is it looks bad, when you see "err" you immediately know what it is, but with "flerr" you have to read it :]. I will let this rest in my head for a while, maybe i will come with something better.

btw. basic console routines will be done soon. Then i wil ltry to make port for other OSes. The ones that i could done are DOS-realmode, DOS-dpmi, DOS-unreal, BSD. Which one do you think would be most efficient?
Post 15 Dec 2005, 22:10
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Crukko



Joined: 26 Nov 2005
Posts: 118
Crukko
Hi all!
Hi,
I think that LIB is a great thing!!!!
I'm writting my own LIB too...but I don't like restrictions puts in this case (es:name of calls too short!).

Here I post commands I wrote...but they have bug I think I'm going to solve Wink

sometimes I put comments....ASK ME if a function is not clear, ok?


Utility Functions
String Functions
Memory Functions
File Functions
Screen / Output Functions

_BankAlloc, Punt, Len, Name, Flags
_BankAppend, Punt, Sorg, Type, Len, Incr
_BankFree, Punt
_BankIndexedAlloc, Punt
_BankIndexedDatoPunt, Punt, NumElem
_BankIndexedFree, Punt
_BankIndexedGet, Punt, NumElem, Dest, Tipo, Len
_BankIndexedIndicePunt, Punt, NumElem
_BankIndexedPut, Punt, NumElem, Sorg, Tipo, Len
_BankName, Punt, Tipo, Rif
_BankPeek, Punt, Pos, Dest, Tipo, Len
_BankPoke, Punt, Pos, Sorg, Tipo, Len, Incremento
_BankPos, Punt, Tipo, Val
_BankRedim, Punt, Incremento
_Checkmenu hMenu, IdVoceMenu
_CopyMemory, Sorg, Dest, Lungh, Back
_Diverso, A, B, Len, Case
_EoF, Punt
_FileClose, Punt
_FileExist, FileName
_FileLineInput, Punt, Dest, Maxbyte
_FileMapBase, Punt
_FileMapClose, Punt
_FileMapOpen, Punt, FNBuff
_FileOpen, Punt, FNBuff, Tipo
_FileOpenName, Punt, Dati
_FileOut Punt, Src, Dascrivere
_Instr MemSrc, MemEnd, Elem, LenElem, PosStart, Case, Direzione
_Len, Sorg
_ListViewInsertColoumn hWind, NumeroColonna, Allineamento, Testo, XDim
_ListViewInsertItem hWin, NumeroElemento, Pos, Testo
_Maggiore, A, B, Len, Case
_MaggioreUguale, A, B, Len, Case
_Match Punt, Sorg, Inizio, Fine, Case, Tipo
_Mids, Sorg, Dest, StartPos, Len
_MidWord, Sorg, Dest, Num
_MidWordCount, Sorg
_MidWordPosParola, Sorg, Num
_Minore, A, B, Len, Case
_MinoreUguale, A, B, Len, Case
_Repeat, Val, Dest, Volte
_RepeatCount, MemSrc, MemEnd, Elem, LenElem, PosStart, Case, Direzione
_SelectFile Punt, Win, Inst, Filtro, FNBuff
_SelectFileFree Punt
_SelectFileNamePath Punt, Dati, Tipo
_Sort, Punt, First, Last, Case
_Strs, Val, Base, Dest
_Uguale, A, B, Len, Case
_Uncheckmenu hMenu, IdVoceMenu
_Val, Sorg
_ValoreEspressione, Sorg, Indice, Routine

_WindowClose Punt
_WindowOpen Punt, Tipo, Class, Titolo, x, y, dimx, dimy, hOwner, hInst, hMenu
_Print Punt, Src, len
_Text hWin, Src, len, x, y

sorry for my English Wink
Post 15 Dec 2005, 22:38
View user's profile Send private message Reply with quote
Reverend



Joined: 24 Aug 2004
Posts: 408
Location: Poland
Reverend
Hello all
I haven't been on board for some time. Sorry guys, I promised to create the conversion procedures and was unreachable. I really had lack of time Crying or Very sad

But I have written it. Don't worry, routines are ready and heavily tested.
ITOA
Code:
;===============================================================================
;       integer to ASCII conversion procedure
;
;       input:
;       number - number to convert Smile
;       radix - base system like 10 for decimal, 16 for hexadecimal, etc.
;       result_buffer - pointer to memory where output will be saved
;       signed - bool value, if number is signed (-2147483646...2147483647)
;                or unsigned (0...4294967295)
;
;       output:
;       no immediate output
;
;       possible errors:
;       radix exceeds 16
;
;       coded by Reverend // HTB + RAG
;===============================================================================
proc    itoa                    number, radix, result_buffer, signed
locals
  temp_buffer                   rb 32+1
endl
        pushad
        mov     esi, [radix]
        lea     edi, [temp_buffer+32]
        mov     ebx, itoa.digits
        cmp     esi, 16
        ja      .error
        std
        xor     al, al
        stosb
        mov     eax, [number]
        cmp     [signed], TRUE
        jnz     @F
        test    eax, 80000000h
        jz      @F
        neg     eax
    @@:
        xor     edx, edx
        idiv    esi
        xchg    eax, edx
        xlatb
        stosb
        xchg    eax, edx
        test    eax, eax
        jnz     @B
        lea     esi, [edi+1]
        mov     edi, [result_buffer]
        cld
        cmp     [signed], TRUE
        jnz     @F
        test    [number], 80000000h
        jz      @F
        mov     al, '-'
        stosb
    @@:
        lodsb
        stosb
        test    al, al
        jnz     @B
        sub     edi, [result_buffer]
        lea     eax, [edi-1]
        stc
  .theend:
        cld
        popad
        ret
  .error:
        clc
        jmp     .theend
endp

idata
  itoa.digits                   db '0123456789ABCDEF', 0
endg    

FTOA
Code:
;===============================================================================
;       float to ASCII conversion procedure
;
;       input:
;       buffer - pointer to memory where output will be saved
;       precision - number of digits after dot
;
;       output:
;       no immediate output
;
;       notes:
;       separate integer and mantisa part with dot '.'
;       so GOOD   123.456
;          WRONG  123,456
;
;       coded by Reverend // HTB + RAG
;===============================================================================
proc    ftoa                    buffer, precision
locals
  status_original             dw ?
  status_changed              dw ?
  integer                     dd ?
  mantisa                     dd ?
  signed                      dd ?
endl
        push    eax edi ecx
;       --------------------------------
;       set correct precision
        mov     eax, [precision]
        cmp     eax, 51
        jb      @F
        mov     eax, 51
    @@:
        mov     [precision], eax
;       --------------------------------
;       change control wortd of fpu to prevent rounding
        fnstcw  [status_original]
        mov     ax, [status_original]
        or      ax, 0000110000000000b
        mov     [status_changed], ax
        fldcw   [status_changed]
;       --------------------------------
;       check if signed
        xor     eax, eax
        fst     [signed]
        test    [signed], 80000000h
        setnz   al
        mov     [signed], eax
;       --------------------------------
;       cut integer and mantisa separately
        fld     st0
        fld     st0                     ; st0 = x, st1 = x
        frndint
        fist    [integer]               ; st0 = x, st1 = x
        fabs
        fsubp   st1, st0                ; st0 = mantisa(x)
;       --------------------------------
;       save integer part in buffer
        mov     edi, [buffer]
        push    [signed]
        push    edi
        push    10
        push    [integer]
        call    itoa
        add     edi, eax
        mov     al, '.'
        stosb
;       --------------------------------
;       save mantisa part in buffer
        mov     ecx, [precision]
        dec     ecx
    .loop:
        fimul   [ftoa.ten]
        fld     st0
        frndint
        fist    [mantisa]
        fsubp   st1, st0
        push    0
        push    edi
        push    10
        push    [mantisa]
        call    itoa
        add     edi, eax
        ftst
        fnstsw  ax
        test    ax, 0100000000000000b
        jz      @F
        test    ax, 0000010100000000b
        jz      .finish
    @@:
        loop    .loop
        fldcw   [status_original]
        fimul   [ftoa.ten]
        fist    [mantisa]
        push    0
        push    edi
        push    10
        push    [mantisa]
        call    itoa
;       --------------------------------
;       restore previous values
    .finish:
        fstp    st0
        stc
        pop     ecx edi eax
        ret
endp

idata
  ftoa.ten                      dd 10
endg    

ATOI
Code:
;===============================================================================
;       ASCII to integer conversion procedure
;
;       input:
;       string - pointer to string
;       radix - base system like 10 for decimal, 16 for hexadecimal, etc.
;
;       output:
;       eax - number
;
;       possible errors:
;       radix exceeds 16
;       number is bigger than dword can store
;       digit is not 0...9 or A...F
;
;       if error occurs the value of eax is indefinable Wink
;
;       coded by Reverend // HTB + RAG
;===============================================================================
proc    atoi                    string, radix
        push    ebx ecx edx esi edi
        xor     ebx, ebx
        mov     ecx, [radix]
        mov     esi, [string]
        mov     edi, 1
        dec     [string]
        cld
        cmp     ecx, 16
        ja      .error
    @@:
        lodsb
        test    al, al
        jnz     @B
        sub     esi, 2
        std
  .loop:
        xor     eax, eax
        lodsb
        sub     al, '0'
        cmp     al, 9
        jbe     @F
        sub     al, 'A' - '9' - 1
    @@:
        cmp     al, 0Fh
        ja      .error
        imul    edi
        imul    edi, ecx
        add     ebx, eax
        cmp     edi, 10000000h
        ja      .error
        cmp     esi, [string]
        jnz     .loop
        mov     esi, [string]
        cmp     byte [esi], '-'
        jnz     @F
        neg     eax
    @@:
        mov     eax, ebx
        stc
  .theend:
        cld
        pop     edi esi edx ecx ebx
        ret
  .error:
        clc
        jmp     .theend
endp    

ATOF
Code:
;===============================================================================
;       ASCII to float conversion procedure
;
;       input:
;       string - pointer to string
;
;       output:
;       st0 - number changed into float
;
;       coded by Reverend // HTB + RAG
;===============================================================================
proc    atof                    string
        push    eax ecx esi
        fninit
        fild    [atof.ten]
        fldz
        fldz
        mov     esi, [string]
        cmp     byte [esi], '-'
        jnz     @F
        inc     esi
    @@:
        xor     eax, eax
        align   4
  .loop.integer_part:
        lodsb
        cmp     al, '.'
        jz      .mantisa
        test    al, al
        jz      .exit
        fmul    st0, st2
        sub     al, '0'
        cmp     al, 9
        jbe     @F
        sub     al, 'A' - '9' - 1
    @@:
        push    eax
        fiadd   dword [esp]
        add     esp, 4
        jmp     .loop.integer_part
  .mantisa:
        xor     ecx, ecx
    @@:
        inc     ecx
        lodsb
        test    al, al
        jnz     @B
        cmp     ecx, 10                 ; max 10 digits in mantisa
        jbe     @F
        mov     ecx, 10
    @@:
        std
        dec     esi
        fxch    st1
        align   4
  .loop.mantisa_part:
        lodsb
        cmp     al, '.'
        jz      .exit
        sub     al, '0'
        cmp     al, 9
        jbe     @F
        sub     al, 'A' - '9' - 1
    @@:
        push    eax
        fiadd   dword [esp]
        add     esp, 4
        fdiv    st0, st2
        jmp     .loop.mantisa_part
  .exit:
        cld
        faddp   st1, st0
        ffree   st1
        mov     eax, [string]
        cmp     byte [eax], '-'
        jnz     @F
        fchs
    @@:
        stc                             ; always returns no error
        pop     esi ecx eax
        ret
endp

idata
  atof.ten                      dd 10
endg    


Description: Included zip contains the code above and also test programs
Download
Filename: fasmlib_conversion.ZIP
Filesize: 6.52 KB
Downloaded: 630 Time(s)

Post 22 Dec 2005, 19:56
View user's profile Send private message Visit poster's website Reply with quote
Garthower



Joined: 21 Apr 2006
Posts: 158
Location: Ukraine
Garthower
Excellent source code Reverend! Now I really understand how to convert float number to string. Thanks!
Post 08 Feb 2007, 21:35
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number Reply with quote
Vasilev Vjacheslav



Joined: 11 Aug 2004
Posts: 392
Vasilev Vjacheslav
sample 'test_ftoa.exe' have a bug? it crashed in itoa function (at 401128h)
Post 09 Feb 2007, 10:29
View user's profile Send private message Reply with quote
Garthower



Joined: 21 Apr 2006
Posts: 158
Location: Ukraine
Garthower
The given code of ftoa function generates not exact data. For example, if to try to convert number 3.1415926535 it is received 3.141592653499999... It's need to try to play with a rounding and accuracy of operations. Besides, how to be with numbers with the big degree? For example 1.12345678e+125?
Post 09 Feb 2007, 13:46
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
Grthower: it cannot be 100% accurate as long as it uses FPU code.

But in this case, it is problem of FP numbers as such. There is no binary FP number representation for exactly 3.1415926535, so FASM (not that procedure) translated it to nearest possible number.
Post 09 Feb 2007, 13:52
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Vasilev Vjacheslav



Joined: 11 Aug 2004
Posts: 392
Vasilev Vjacheslav
maybe setting FPU control word may help with proper rounding?
Post 09 Feb 2007, 15:32
View user's profile Send private message Reply with quote
Reverend



Joined: 24 Aug 2004
Posts: 408
Location: Poland
Reverend
Dealing with control word won't change much as it only says to round up, down or to cut mantissa Smile. As for the bug you mentioned, it crashes on my computer too now (I guess it didn't when I posted it). Quick analysis tells me it's buffer overflow problem. I may look deeper in code later.

Now I know a bit more how are float values stored (from my university classes) and so maybe I'll create another non-FPU version of FTOA.
Post 09 Feb 2007, 19:45
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2, 3, 4, 5  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar.

Powered by rwasa.