flat assembler
Message board for the users of flat assembler.

flat assembler > Macroinstructions > New experiments in StdCall.

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
JohnFound



Joined: 16 Jun 2003
Posts: 3500
Location: Bulgaria
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.


Description:
Download
Filename: locals.zip
Filesize: 2.52 KB
Downloaded: 196 Time(s)

Post 05 Aug 2004, 15:41
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3500
Location: Bulgaria
Hm, no interest...
Any opinions?

Ah, and what if I move argument declaration at the place where are locals in present version:
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
    






Regards
Post 06 Aug 2004, 07:49
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
Tommy



Joined: 17 Jun 2003
Posts: 492
Location: Norway
Quote:
Ah, and what if I move argument declaration at the place where are locals in present version:

Yes, that would be nice! Wink
Post 06 Aug 2004, 08:22
View user's profile Send private message Visit poster's website Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1095
Location: Poland
JohnFound wrote:
Hm, no interest...
Ah, and what if I move argument declaration at the place where are locals in present version:


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 Wink 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...
Post 06 Aug 2004, 12:02
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7108
Location: Slovakia
i don't like this too. I like FASM for it's straightforwardness and simplicity
Post 06 Aug 2004, 12:04
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
S.T.A.S.



Joined: 09 Jan 2004
Posts: 173
Location: Ru#27
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     
Of cource, locals/endl seem to be more flexible.
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.
Post 06 Aug 2004, 12:07
View user's profile Send private message Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3500
Location: Bulgaria
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.
    
Post 06 Aug 2004, 15:05
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3500
Location: Bulgaria
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"?
Post 06 Aug 2004, 15:12
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1095
Location: Poland
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 Confused
Post 06 Aug 2004, 15:31
View user's profile Send private message Visit poster's website Reply with quote
pelaillo
Missing in inaction


Joined: 19 Jun 2003
Posts: 874
Location: Colombia
Proposed number 4 is about to convince me Smile
I like that there is no ambiguities left.

Time for a new poll Wink
Post 06 Aug 2004, 16:11
View user's profile Send private message Yahoo Messenger Reply with quote
aaro



Joined: 21 Jun 2003
Posts: 107
Location: hel.fi
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
    
Post 06 Aug 2004, 16:31
View user's profile Send private message Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3500
Location: Bulgaria
decard wrote:
well, I meant something like this:
Code:
proc papapa, arg1 DWORD, arg2 DWORD    



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    
Post 06 Aug 2004, 17:25
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
Tommy



Joined: 17 Jun 2003
Posts: 492
Location: Norway
Why not keep it plain?
Code:
proc foo, arg1,arg2,arg3
  .loc1 dd ?
  .loc2 db ?
  .loc3 dw ?
begin
  ; code...
endp    
Post 06 Aug 2004, 17:34
View user's profile Send private message Visit poster's website Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3500
Location: Bulgaria
Tommy wrote:
Why not keep it plain?
Code:
proc foo, arg1,arg2,arg3
  .loc1 dd ?
  .loc2 db ?
  .loc3 dw ?
begin
  ; code...
endp    


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'
Post 06 Aug 2004, 18:01
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
Tommy



Joined: 17 Jun 2003
Posts: 492
Location: Norway
Oh... Thanks for pointing that out... Cool I follow you there...
Post 06 Aug 2004, 20:34
View user's profile Send private message Visit poster's website Reply with quote
S.T.A.S.



Joined: 09 Jan 2004
Posts: 173
Location: Ru#27
aaro wrote:
option for ccall, stdcall, nofram (use esp for params/locals), frame, would be very nice.
IHMO there's no need to use special option. For example my "PROC" macro supports CDECL/STDCAL & even FASTCALL conventions. Though in this case one have to use RET to return from STDCAL&FASTCALL and CRET to return from CDECL PROC.

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"
Post 07 Aug 2004, 02:55
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7108
Location: Slovakia
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).
Post 07 Aug 2004, 08:13
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
aaro



Joined: 21 Jun 2003
Posts: 107
Location: hel.fi
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
    
Post 07 Aug 2004, 10:46
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7108
Location: Slovakia
Embarassed 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]
    
Post 07 Aug 2004, 10:53
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
S.T.A.S.



Joined: 09 Jan 2004
Posts: 173
Location: Ru#27
aaro wrote:
i think there's too many different proc macros, so it would be nice if we could agree on standard syntax here.
Yes, indeed. That's the main reason, why I'm using uppercase names for macro, it's to differ them from standard ones, so I can mix them in the source.

aaro wrote:
And i really would like it to include esp based locals/params too.
I just curious, why this nice idea isn't so popular, as it could be Wink

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..
Post 07 Aug 2004, 12:07
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  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-2019, Tomasz Grysztar.

Powered by rwasa.