flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > handling local variables offsets

Author
Thread Post new topic Reply to topic
daluca



Joined: 05 Nov 2005
Posts: 86
daluca 21 Aug 2006, 01:48
Hi I was translating the simple window example of the
iczelion tutorials to assemble it wiht FASM .
in this example the window class structure is declared as local
and everything was ok but wen i get to the invoke CreateWindowEx
i could not pass simply the wc as parameter,so i change it to [wc]
and the file was successfully assembled but it didn't actually push the
offset of the winclass structure so i compare this code generated and the one
assembled with masm and I saw a lea eax,[ebp-50] and push eax
so i change the code to lea eax,[wc] and it worked so my question or
request is: can the macros be modified in order to generate this sequence
automatically an have access to the offsets of local variables directly
just like:
mov eax,wc
Post 21 Aug 2006, 01:48
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 21 Aug 2006, 01:54
invoke function, addr localVar, ...

[edit]
http://flatassembler.net/docs.php?article=win32 wrote:
2.1 Procedure parameters

With the extended headers the macroinstructions for calling procedures allow more types of parameters than just the double word values as with basic headers. First of all, when the quoted string is passes as a parameter to procedure, it is used to define string data placed among the code, and passes to procedure the double word pointer to this string. This allows to easily define the strings that don't have to be re-used, just in the line calling the procedure that requires pointers to those strings, like:

invoke MessageBox,HWND_DESKTOP,"Message","Caption",MB_OK

If the parameter is the group containing some values separated with commas, it is treated in the same way as simple quoted string parameter.

If the parameter is preceded by the addr word, it means that this value is a double word address and this address should be passed to procedure, even if it cannot be done directly - like in the case of local variables, which have addresses relative to EBP register, in such case the EDX register is used temporarily to calculate the value of address and pass it to the procedure. For example:

invoke RegisterClass,addr wc

in case when the wc is the local variable with address EBP-100h, will generate this sequence of instructions:

lea edx,[ebp-100h]
push edx
call [RegisterClass]

However when the given address is not relative to any register, it is stored directly.
[/edit]
Post 21 Aug 2006, 01:54
View user's profile Send private message Reply with quote
daluca



Joined: 05 Nov 2005
Posts: 86
daluca 21 Aug 2006, 19:56
thanks: i don't know how could I miss that part of the documentation.
Post 21 Aug 2006, 19:56
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 21 Aug 2006, 20:11
when we got to this, i have currently implemented saving of such used register in FASMLIB "libcall" macro:
Code:
mov [eaxsave], eax
lea eax, [ebp-100h]
push eax
mov eax, [eaxsave]
call [RegisterClass]    


so you can use something like this:
Code:
libcall proc, eax, edx, addr something    


but now i find it somewhat superstitious, and too much slowing when almost never needed. i think i could change behavior to stop compilation with error, when EAX is used after being modified with "addr". Same behavior is already implemented with nested calls, which return value in eax. For example this code throws error:
Code:
libcall 1, eax, <libcall something, 1, 2>, 3    


Or maybe i could optimize eax-saving code to something like this, even with nested calls:
Code:
push eax
lea eax, [ebp+100h]
xchg eax, [esp]    

seems a fairly good idea, what do you think?
Post 21 Aug 2006, 20:11
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8390
Location: Kraków, Poland
Tomasz Grysztar 21 Aug 2006, 20:13
It's a good one.
Post 21 Aug 2006, 20:13
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 21 Aug 2006, 20:20
or best possibility, to use this code only when needed... but this becomes quite hard to code with nested calls, and also it will slow down preprocessing, noticeably, i afraid.

[edit]as thinking about it, the stress could be moved to assembly stage, with some forward-referencing. I think this possiblity could be better
Post 21 Aug 2006, 20:20
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
dead_body



Joined: 21 Sep 2005
Posts: 187
Location: Ukraine,Kharkov
dead_body 22 Aug 2006, 07:01
the idea is very interesting.
Post 22 Aug 2006, 07:01
View user's profile Send private message Reply with quote
MazeGen



Joined: 06 Oct 2003
Posts: 977
Location: Czechoslovakia
MazeGen 22 Aug 2006, 09:24
Code:
xchg reg, mem    
is very slow (has huuuge latency) because of default LOCK prefix. The only replacement which comes to my mind is
Code:
xor eax, [esp]
xor [esp], eax
xor eax, [esp]
    

but it would obfuscate the code too much I think.

I prefer raising an error in my macros so the user has to pass the parameter in another register.
Post 22 Aug 2006, 09:24
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8390
Location: Kraków, Poland
Tomasz Grysztar 22 Aug 2006, 10:02
Any API call is anyway most probably slow enough that this wouldn't do much difference - while it is clear and safe solution. If you want it to be fast, you shouldn't use macros in the first place. Wink
OK, just my personal opinion.
Post 22 Aug 2006, 10:02
View user's profile Send private message Visit poster's website Reply with quote
MazeGen



Joined: 06 Oct 2003
Posts: 977
Location: Czechoslovakia
MazeGen 22 Aug 2006, 10:10
I was rather hinting at the fact that vid says this code
Code:
mov [eaxsave], eax
lea eax, [ebp-100h]
push eax
mov eax, [eaxsave]
call [RegisterClass]
    

is "too much slowing" and this code
Code:
push eax
lea eax, [ebp+100h]
xchg eax, [esp]
    

is its optimized version.
Post 22 Aug 2006, 10:10
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 22 Aug 2006, 10:26
and i am not going to use this only for api calls Wink
Post 22 Aug 2006, 10:26
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8390
Location: Kraków, Poland
Tomasz Grysztar 22 Aug 2006, 10:50
Nevertheless I feel tempted to make it this way in fasm's extended headers. It's really nice and clear way of avoiding problems with register conflicts for "addr" prefix and nested calls (which are still the "extended" features to be used to have clear and easy code rather than the fast one).
Post 22 Aug 2006, 10:50
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 22 Aug 2006, 11:11
you want to do it always this way, or only when it is nescesary? because finding out when it is nescessary will produce quite heavy load on either preprocessor (this way also the macros become much uglier), or on assembler (macros remain nice, but there will be some forward referencing and conditioning for each such argument)

or maybe there is way i didn't find out
Post 22 Aug 2006, 11:11
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8390
Location: Kraków, Poland
Tomasz Grysztar 22 Aug 2006, 11:14
Always - I think it's just nice. Wink
Post 22 Aug 2006, 11:14
View user's profile Send private message Visit poster's website Reply with quote
daluca



Joined: 05 Nov 2005
Posts: 86
daluca 22 Aug 2006, 22:01
How about this:
Code:
lea ebp,[ebp-100h]
;mov reg,ebp
;push ebp
lea ebp,[ebp+100h]
    


or maybe just:
Code:
sub ebp,100h
;mov reg,ebp
;push ebp
add ebp,100h
    
Post 22 Aug 2006, 22:01
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 22 Aug 2006, 22:44
daluca: Question
i believe you got something wrong
Post 22 Aug 2006, 22:44
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
UCM



Joined: 25 Feb 2005
Posts: 285
Location: Canada
UCM 23 Aug 2006, 00:13
daluca: That would work (in fact nicer solution:
Code:
push ebp
sub [esp],100h
    
) but the problem is it requires extra logic to handle and does not work for more complex scenarios (i.e. addr 5*2+1000 for example.)
Post 23 Aug 2006, 00:13
View user's profile Send private message Reply with quote
daluca



Joined: 05 Nov 2005
Posts: 86
daluca 23 Aug 2006, 05:32
yes i got it wrong:
Code:
lea ebp,[ebp-100h]
mov eax,ebp
lea ebp,[ebp+100h]

     is a redundance of:

lea eax,[ebp-100h] 
    

I just thought addr could be use like:
Code:
mov eax,addr wc
    

and about:

Code:
lea ebp,[ebp-100h]
push ebp
lea ebp,[ebp+100h]
    

well is just a way to push the offset of a local variable
without the use of any other register and the diference
between the two leas is just the sign, i thought maybe
this fact could be usefull in the macro implementation.

sorry: macros are realy not my field

although the UCM solution is indeed nicer.
but I only have one doubt:

Code:
addr 5*2+1000 
    


why would you refer to the offset of a local variable in that way?
Post 23 Aug 2006, 05:32
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8390
Location: Kraków, Poland
Tomasz Grysztar 23 Aug 2006, 08:32
First: you cannot assume that EBP is the stack frame pointer, in fact you cannot assume it has any given value (myself I often use EBP for different purposes - with so few registers in x86 it's sometimes inavoidable).
Second: you cannot assume "addr" is used just for local variables and procedure arguments. This may be even "ebx+ecx*2+100h" address.
Post 23 Aug 2006, 08:32
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:  


< 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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.