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 |
|
vid 30 Nov 2005, 17:31
strlib almost done...
|
|||
30 Nov 2005, 17:31 |
|
decard 05 Dec 2005, 20:37
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 \{ ? |
|||
05 Dec 2005, 20:37 |
|
vid 05 Dec 2005, 21:59
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 \} } |
|||
05 Dec 2005, 21:59 |
|
vid 14 Dec 2005, 01:43
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. |
|||
14 Dec 2005, 01:43 |
|
vid 15 Dec 2005, 00:55
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 what do you think about it? |
|||
15 Dec 2005, 00:55 |
|
decard 15 Dec 2005, 09:01
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 (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! |
|||
15 Dec 2005, 09:01 |
|
vid 15 Dec 2005, 11:24
decard: that's just what i meant, (except that CF=1, [errno]!=0, not 1 )
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. |
|||
15 Dec 2005, 11:24 |
|
decard 15 Dec 2005, 12:19
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. |
|||
15 Dec 2005, 12:19 |
|
vid 15 Dec 2005, 12:34
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.
|
|||
15 Dec 2005, 12:34 |
|
decard 15 Dec 2005, 14:07
a few more letters don't mind. "err" sometimes can be used as local variable name, call it at least "flerror" or "fliberr".
|
|||
15 Dec 2005, 14:07 |
|
vid 15 Dec 2005, 22:10
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? |
|||
15 Dec 2005, 22:10 |
|
Crukko 15 Dec 2005, 22:38
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 |
|||
15 Dec 2005, 22:38 |
|
Reverend 22 Dec 2005, 19:56
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 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 ; 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 ; ; 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
|
|||||||||||
22 Dec 2005, 19:56 |
|
Garthower 08 Feb 2007, 21:35
Excellent source code Reverend! Now I really understand how to convert float number to string. Thanks!
|
|||
08 Feb 2007, 21:35 |
|
Vasilev Vjacheslav 09 Feb 2007, 10:29
sample 'test_ftoa.exe' have a bug? it crashed in itoa function (at 401128h)
|
|||
09 Feb 2007, 10:29 |
|
Garthower 09 Feb 2007, 13:46
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?
|
|||
09 Feb 2007, 13:46 |
|
vid 09 Feb 2007, 13:52
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. |
|||
09 Feb 2007, 13:52 |
|
Vasilev Vjacheslav 09 Feb 2007, 15:32
maybe setting FPU control word may help with proper rounding?
|
|||
09 Feb 2007, 15:32 |
|
Reverend 09 Feb 2007, 19:45
Dealing with control word won't change much as it only says to round up, down or to cut mantissa . 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. |
|||
09 Feb 2007, 19:45 |
|
Goto page Previous 1, 2, 3, 4, 5 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.