flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > New experiments in StdCall. Goto page 1, 2 Next |
Author |
|
JohnFound 05 Aug 2004, 15:41
As a next atempt to improve StdCall library, I made a little change to the sintax. With this variant the user can define local variables several times at the overlapping space in the stack.
As far as there is no need for local variables delimiter, the macro "begin" is no longer used. Little example: Code: proc testproc, arg1, arg2, arg3 locals .loc1 dd ? .loc2 dd ? .loc3 dd ? .locarray rb $1000 endl mov [.loc1], 1 push [.arg2] pop [.loc2] cmp [.loc2], 3 je .case1 return .case1: locals .loc4 dd ? ; at the address of loc1 .loc5 dw ? ; at the address of loc2 .loc6 dw ? ; at the address of loc2 .loc7 dd ? ; at the address of loc3 endl mov [.loc4], 2 mov [.loc5], 3 mov [.loc6], 4 return endp Here is the library with example project. Don't start executable, just see it in debugger. Regards.
|
|||||||||||
05 Aug 2004, 15:41 |
|
Tommy 06 Aug 2004, 08:22
Quote: Ah, and what if I move argument declaration at the place where are locals in present version: Yes, that would be nice! |
|||
06 Aug 2004, 08:22 |
|
decard 06 Aug 2004, 12:02
JohnFound wrote: Hm, no interest... I don't like this solution, as I'm used to arguments specified in the first line of function declaration. And your solution needs more typing But, OTOH, they have an advantage that you can create variables of any size. IMO it would be the best to specify argument size and name in first line of proc declaration... |
|||
06 Aug 2004, 12:02 |
|
vid 06 Aug 2004, 12:04
i don't like this too. I like FASM for it's straightforwardness and simplicity
|
|||
06 Aug 2004, 12:04 |
|
S.T.A.S. 06 Aug 2004, 12:07
Hmm.. Isn't it possible to do so with virtual:
Code: proc SomeProc, options \;like ccall, stdcall, use16, use32 etc .arg1 dd ?,\ .arg2 dw ? ; locals loc1 dd ? loc2 dd ? locarr rw 1000 virtual at loc1 loc3 dd ? ; at loc1 loc4 dd ? ; at loc2 loc5 dw ? ; at locarr[0] end virtual begin ; some code code code endp And IMHO declaring parameters of PROC this way might be a bit confusing, because original FASM uses this to declare locals. OTOH, actually arguments and locals have mostly the same meaning (from point of addressing), so may be something like this will be usable: Code: proc SomeProc, options ;like ccall, stdcall, use16, use32 etc .arg1 dd ? .arg2 dw ? ;begin locals loc1 dd ? loc2 dd ? locarr rw 1000 endl ; some code code code locals loc3 dd ? ; at loc1 loc4 dd ? ; at loc2 loc5 dw ? ; at locarr[0] endl ; some code code code endp BTW, as to me, the most confusing thing here is declaring (not all, just one half !!) labels withoun dot, but using them with dot. |
|||
06 Aug 2004, 12:07 |
|
JohnFound 06 Aug 2004, 15:05
S.T.A.S. wrote: Hmm.. Isn't it possible to do so with virtual Of course it is possible, but the problem is with the size of the stack frame. It have to be equal to the maximal size of all locals..endl block. Quote: And IMHO declaring parameters of PROC this way might be a bit confusing, because original FASM uses this to declare locals. Yea, I know this, but the way FASM make this allows creating only fixed size arguments, that is limiting in some cases. I have some desire to create one universal set of macroses that to work for 16bit/32bit, stdcall/ccall etc. Quote: BTW, as to me, the most confusing thing here is declaring (not all, just one half !!) labels withoun dot, but using them with dot. Yes, I don't like it too. But the previous solution is even worse. I want to keep both arguments and locals in the name space of the procedure, i.e. the arguments and local variables to be local labels of the main procedure label. Of course I can stop to add "." at the begining of the arguments and to let the user to write it explicitly, but this also will be confusing. About compatibility: To keep this set of macroses is not my goal, because Fresh is still in developement stage and there is no final versions released. But the time of final releases come near and near and now is the time when we have the chance to make big changes without harm for many projects and people. After Fresh is released as final version, it will be too late to make such big changes... At the end, I wrote some review of all variants of stdcall library in circulation and the last two variants. Here you can see the general structure of the procedures created with these macroses. Code: 1. Current StdCall of FASMW ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-+-proc ProcedureName, arg1, arg2 -+ | | | | Code block, between "proc" | | .loc1 dd ? | | and "endp" or optionally between | | .loc2 dd ? | | "enter" and "endp", depending | +-enter--------+ | of existing of locals block. | | | | Optional locals block, between | | "proc" and "enter". | | +---endp ---------------------------+ Three keywords, "proc", "enter" and "endp" - one is optional. The big disadvantage is the it is some kind of ambiguous. "enter" is instruction and end of the locals block. "proc" marks the begining of code block or begining of locals block. "endp" is paired with "proc", but sometimes with "enter". Fixed size of the arguments. Arguments are not local labels towards the name of the procedure, they looks like absolute labels, but are actually temporary, existing only inside the procedure. Locals on contrary, are all local labels with parent, the name of the procedure. 2. Curent StdCallEx of Fresh ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-proc ProcedureName, arg1, arg2 -+ | .loc1 dd ? | Locals block between "proc" and | .loc2 dd ? | "begin" - optional content +-begin---------------------------+ | | Code block between "begin" and | | "endp" - optional content | | +-endp----------------------------+ Three keywords "proc", "begin" and "endp" - all mandatory. Arguments and locals both are local labels with parent - the name of the procedure. Big disadvantage is that arguments have to be declared without dot, but to be used with dot. But in current declaration - as arguments of "proc" macro, to leave the user to write dots is even worse - there is no way to check whether he write them with or without dot. One more word for typing - "begin", but it is with purpose to make the code block more "stabble" and "unambiguous". 3. Proposed StdCallEx2 - first variant. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-proc ProcedureName, arg1, arg2 -+ | | | +-locals-------+ | Code block always between | | .loc1 dd ? | | "proc" and "endp". | | .loc2 dd ? | | | +-endl---------+ | Floating, optional locals | | blocks, always between | +-locals-------+ | "locals" and "endl". | | .loc3 dd ? | | | | .loc4 dd ? | | Every locals block | +-endl---------+ | overlaps the others in | | the stack memory. | | +-endp----------------------------+ Four keywords: "proc", "endp", "locals" end "endl" - 2 are optional. This variant removes the ambiguity from original FASM variant. Also, the plus is the minimization of the stack frame size with using overlapping declarations. Disadvantage is only that arguments are still fixed size and have to be used with "dot". 4. Proposed StdCallEx2 - second variant. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--proc ProcedureName, flags---+ | .arg1 dd ? | Arguments block between "proc" | .arg2 dd ? | and "begin" - optional content | .arg3 dd ? | +--begin-----------------------+ | | | +--locals -------+ | Code block between "begin" and | | .loc1 dd ? | | "endp" - optional content. | | .loc2 dw ? | | | +--endl ---------+ | Floating locals blocks inside the | | code, enclosed between "locals" | +--locals--------+ | and "endl" where every block | | .loc3 db ? | | overlaps the others in stack | | .loc4 db ? | | memory. | +--endl----------+ | | | +--endp------------------------+ Five keywords - "proc", "begin", "endp", "locals" and "endl" Two of them optional and three mandatory. Optional flags - there should be some "default" values. Free structure of the arguments and locals. Free format of the procedure call convention: stdcall, ccall etc. Disadvantages - Very incompatible syntax. More text for typing. |
|||
06 Aug 2004, 15:05 |
|
JohnFound 06 Aug 2004, 15:12
decard wrote: IMO it would be the best to specify argument size and name in first line of proc declaration... Some example? btw: What about overlapping locals blocks defined with "locals", "endl"? |
|||
06 Aug 2004, 15:12 |
|
decard 06 Aug 2004, 15:31
well, I meant something like this:
Code: proc papapa, arg1 DWORD, arg2 DWORD but I failed to write a macro that would do that. Is it possible to do so? I should learn more about FASM preprocessor |
|||
06 Aug 2004, 15:31 |
|
pelaillo 06 Aug 2004, 16:11
Proposed number 4 is about to convince me
I like that there is no ambiguities left. Time for a new poll |
|||
06 Aug 2004, 16:11 |
|
aaro 06 Aug 2004, 16:31
Something like this maybe:
Code: proc foobar, arg1, <arg2, word>, arg3, <arg4, byte> Default would be dword.. Don't know about multiple local blocks but option for ccall, stdcall, nofram(use esp for params/locals), frame, would be very nice. Without options stdcall+frame would be default. Hmm, maybe like this: Code: proc <foobar, ccall+noframe>, arg1, <arg2, word>, arg3, <arg4, byte> locals here begin return endp |
|||
06 Aug 2004, 16:31 |
|
JohnFound 06 Aug 2004, 17:25
decard wrote: well, I meant something like this: here is one simple solution (without local variables support): Code: BYTE equ rb 1 WORD equ rw 1 DWORD equ rd 1 struc proc [arg] { common local ..argsize virtual at ebp+8 ..arg: forward arg common ..argsize = $ - ..arg end virtual macro return _% leave retn ..argsize %_ } macro endp { purge return } _% fix { %_ fix } MyTestProc proc .arg1 DWORD, .arg2 WORD, .arg3 BYTE mov eax, [.arg1] mov ax, [.arg2] mov bh, [.arg3] return endp But actually you can use the trick with "equ" for above variant 4 and the result will be: Code: proc MainWinProc, stdcall .hwnd DWORD .wmsg DWORD .wparam DWORD begin push esi edi ebx cmp [.wmsg], WM_PAINT je .wmpaint cmp [.wmsg], WM_WINDOWPOSCHANGED je .wmwindowposchanged invoke DefWindowProc, [.hwnd], [.wmsg], [.wparam], [.lparam] pop ebx edi esi return .wmpaint: locals .ps PAINTSTRUCT endl lea esi, [.ps] invoke BeginPaint, [.hwnd], esi ;................... invoke EndPaint, [.hwnd], esi pop ebx edi esi return .wmwindowposchanged: locals .rect RECT endl lea eax, [.rect] invoke GetWindowRect, [.hwnd], eax ;....... pop ebx edi esi return endp |
|||
06 Aug 2004, 17:25 |
|
Tommy 06 Aug 2004, 17:34
Why not keep it plain?
Code: proc foo, arg1,arg2,arg3 .loc1 dd ? .loc2 db ? .loc3 dw ? begin ; code... endp |
|||
06 Aug 2004, 17:34 |
|
JohnFound 06 Aug 2004, 18:01
Tommy wrote: Why not keep it plain? There are several reasons related to different aspects or writing complex procedures: 1. Stack frame for local variables - the main reason is that in complex procedures, there are usually several independent blocks of code and every one of them uses different local variables, that are not related to that of the other blocks. So, at first you have to define all variables in single place, and the size of stack frame can become several times bigger than that you actually need. Another solution is to reuse already defined local variables in different blocks of code. But as a rule, the type and meaning of what you need is different of that in other blocks, so you have to use [.rect.left] as a simple dword or first two dwords of RECT as POINT etc. At second in big procedures, the begining of the procedure (where all locals are defined) is very far from the place where you want to use these locals. So you have to scroll up/down all the time to check what we were defined and what the exact name was. Also, very frequent case, after rewriting some parts of the procedure, you lost the track what variables are used and what not, so defined but not used local variables often happens to appear. Good example of such big procedures are window procedures of complex windows - see Fresh , for example 'sourceeditor.asm' or 'MainWindow.asm' |
|||
06 Aug 2004, 18:01 |
|
Tommy 06 Aug 2004, 20:34
Oh... Thanks for pointing that out... I follow you there...
|
|||
06 Aug 2004, 20:34 |
|
S.T.A.S. 07 Aug 2004, 02:55
aaro wrote: option for ccall, stdcall, nofram (use esp for params/locals), frame, would be very nice. About "nofram" threre's a problem - it's immpossible to use any of above locals declarations. That is, in case of ESP based stackframe ".loc1 dd ?" will not work, it should be something like "DWORD/VAR/WHATEVER_MACRO loc1" |
|||
07 Aug 2004, 02:55 |
|
vid 07 Aug 2004, 08:13
check this:
Code: proc DummyFooBar .loc1 dd 0 .loc2 dd 1 LocBuff rb TotalLocSize LocSize=0 enter <code here> virtual at LocBuff + LocSize .loc3 dd 2 .loc4 dd 3 LocSize = $ - LocBuff end virtual <code here> return endp TotalLocSize = LocSize why fixes? Isn't it simpler this way? You only have to add 2 lines to "enter" macro, one line to "endp" macro and create "locals" and "endl" macros. Same applies to Fresh's macro to define uninitialized data (can't remember name). |
|||
07 Aug 2004, 08:13 |
|
aaro 07 Aug 2004, 10:46
S.T.A.S:
Yes i know it's impossible, i have made my own proc macros too and i used syntax like this: Code: proc foobar, arg1, arg2 type noframe, cdecl var .loc1 ; dword sized local variable var .loc2, 2 ; word sized local variable begin return endp But i think there's too many different proc macros, so it would be nice if we could agree on standard syntax here. And i really would like it to include esp based locals/params too. Something like this? Code: proc <foobar, ccall+noframe>, arg1, <arg2, word>, arg3, <arg4, byte> locals ; You need to use var when using noframe as parameter var .loc1 ;dword var .loc2, 1 ;byte var .loc3, 4 ;dword endl begin return endp I think this would be nice syntax and you wouldn't need to modify existing procs very mutch: Code: proc foobar, arg1, arg2 .loc1 dd ? .loc2 db ? begin return endp Would come to: Code: proc foobar, arg1, arg2 locals .loc1 dd ? .loc2 db ? endl begin return endp |
|||
07 Aug 2004, 10:46 |
|
vid 07 Aug 2004, 10:53
oops, i miscomprehended JohnFound's macros, sorry. I thought "locals".."endl" defines another local data, not overdefines those already defined.
Now i like your idea, but there is one more thing - local data defined between "proc" and "enter" should be accesible from whole procedure, because sometimes you may need to pass data in variable between blocks created by "locals".."endl". For example: Code: proc a .hinst dd 0 enter invoke GetInstanceHandle,0 mov [.hinst],eax <branching code> ;branch1 locals .loc1 dd 0 endl mov eax,[.hinst] mov ebx,[.loc1] ;branch1 locals .loc2 dd 0 endl mov eax,[.hinst] mov ebx,[.loc2] |
|||
07 Aug 2004, 10:53 |
|
S.T.A.S. 07 Aug 2004, 12:07
aaro wrote: i think there's too many different proc macros, so it would be nice if we could agree on standard syntax here. aaro wrote: And i really would like it to include esp based locals/params too. One time I thinked to use "dot" macro instead of VAR one: Code: proc <foobar,noframe>, arg1, <arg2, dw ?>, arg3, <arg4, db ?> ;locals ; You need to use var when using noframe as parameter . loc1 ;dword . loc2, db ? ;byte . loc3, dd ? ;dword . loc4, RECT ; that's why I use "dd ?", not "4" in above line ;endl begin return endp Guys, do we really need 2 different set of macros for STDCALL & CDECL? The only difference is 'return' macro (I don't take into account 'ccall'). Woudn't it be nicer to use one macro to declare both kinds of procs? The purpose of CDECL is to have multiple argument allowed, and IMHO, it's posible to determine CDECL proc by special argument name, at the moment I use '...' for this (though really I don't like this C-way). So, if last argument is say, 'SOME_SPECIAL_SYMBOL' the prog is CDECL, otherwise STDCALL. (hmm.. it's offtopic, but why not?) PS Don't take my opinion too serious, it seems I'll completely stop to use old good standard macro library soon.. |
|||
07 Aug 2004, 12:07 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.