flat assembler
Message board for the users of flat assembler.

Index > Windows > Stack Frames and Calling Conventions...

Author
Thread Post new topic Reply to topic
Nameless



Joined: 30 Apr 2010
Posts: 95
Nameless 25 Sep 2010, 19:34
since my last topic its been a confusion to me, either "enter" and "leave" or "push, mov, add"

this time i used pencil and paper to draw the stack and how will it look like, and i got to some part that still confuses me
here is the code:

Code:
format pe gui 4.0

include 'C:\fasm\include\win32ax.inc'

.data
 lpBuf rb 1024

.code
 Start:
  jmp   .caller
  .function:
   push         ebp
   mov          ebp, esp
   add          ebp, 8
   mov          eax, [ebp]
   invoke       wsprintf, lpBuf, "x1 = %d", eax
   invoke       MessageBox, 0, lpBuf, "test", 0

   mov          eax, [ebp+4]
   invoke       wsprintf, lpBuf, "x2 = %d", eax
   invoke       MessageBox, 0, lpBuf, "test", 0

   mov          eax, [ebp+8]
   invoke       wsprintf, lpBuf, "x3 = %d", eax
   invoke       MessageBox, 0, lpBuf, "test", 0

   sub          ebp, 8
   mov         esp, ebp
   pop          ebp
   ret

 .caller:
   push         17         ;x3
   push         16         ;x2
   push         15         ;x1
   call         .function
   ;this is equal to "invoke        .function, 15, 16, 17" right?
   invoke       MessageBox, 0, "ret Success", "Back", 0
   invoke       ExitProcess, 0

.end Start
    


so is this the best way to do it? and what calling convention will it work for? cdecl and stdcall or pascal? (i think stdcall and cdecl)
also when should i use "ret x" insted of just "ret" ?

ty, i know im a pain Very Happy
Post 25 Sep 2010, 19:34
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 25 Sep 2010, 20:19
Nameless,

add ebp, 8 is quite an unusual way to adjust the stack frame pointer.

wsprintf() is still cdecl, use cinvoke.

mov esp, ebp is unnecessary if the stack is balanced (cf. cinvoke).

sub ebp, 8 is unnecessary too (provided stack is balanced), because of pop ebp.

Since your .function appears to use cdecl calling conventions, those push 17 16 15 / call .function can be replaced with ccall .function, 17, 16, 15
Post 25 Sep 2010, 20:19
View user's profile Send private message Reply with quote
Nameless



Joined: 30 Apr 2010
Posts: 95
Nameless 25 Sep 2010, 20:24
can u show me a sample of a balanced stack frame?
u kinda removed all the lines Very Happy lol

EDIT:
Code:
format pe gui 4.0

include 'C:\fasm\include\win32ax.inc'

.data
 lpBuf rb 1024

.code
 Start:
  jmp   .caller
  .function:
   push         ebp
   mov          ebp, esp
   ;add          ebp, 8
   mov          eax, [ebp+8]
   cinvoke       wsprintf, lpBuf, "x1 = %d", eax
   invoke       MessageBox, 0, lpBuf, "test", 0

   mov          eax, [ebp+12]
   cinvoke       wsprintf, lpBuf, "x2 = %d", eax
   invoke       MessageBox, 0, lpBuf, "test", 0

   mov          eax, [ebp+16]
   cinvoke       wsprintf, lpBuf, "x3 = %d", eax
   invoke       MessageBox, 0, lpBuf, "test", 0

   ;sub          ebp, 8
   ;mov          esp, ebp
   pop          ebp
   ret

 .caller:
   ;push         17         ;x3
   ;push         16         ;x2
   ;push         15         ;x1
   ;call         .function
   ccall .function, 15, 16, 17
   invoke       MessageBox, 0, "ret Success", "Back", 0
   invoke       ExitProcess, 0

.end Start
    


better?

EDIT2: y would the stack be unbalanced? for using call insted of ccall? cause as far as i know they are the same in this sample, no diffrence !
Post 25 Sep 2010, 20:24
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1405
Location: Piraeus, Greece
Picnic 25 Sep 2010, 23:45
Nameless wrote:
when should i use "ret x" insted of just "ret" ?


Hi,

I'll try to explain with simple code.

Code:
;example of __cdecl

push arg1
push arg2
push arg3
call function
add  esp, 0Ch        ; effectively "pop; pop; pop"
    

Code:
;example of __stdcall

push arg1
push arg2
push arg3
call function
;no stack cleanup - callee does this
    



A C function in stdcall convention
Code:
; void __stdcall MyFunction(int x, int y, int z)
; {
;  ...
;  return;
; }
    

In Fasm..
Code:
        push [x]
        push [y]
        push [z]
        call MyFunction


MyFunction:
        push ebp                ; save the value of ebp
        mov ebp, esp            ; ebp now points to the top of the stack
        sub esp, 0Ch            ; space allocated on the stack for the local variables

        ;   DWORD [ebp+08h]     ; z
        ;   DWORD [ebp+0Ch]     ; y
        ;   DWORD [ebp+10h]     ; x

        mov esp, ebp    ; remove space for local variables, by reverting esp to its old value
        pop ebp         ; restore the old value of ebp to its old value, which is on top of the stack
        ret 0Ch         ; clean the stack, remove sizeof(x) + sizeof(y) + sizeof(z)
    


Last edited by Picnic on 26 Sep 2010, 09:13; edited 2 times in total
Post 25 Sep 2010, 23:45
View user's profile Send private message Visit poster's website Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 26 Sep 2010, 06:44
Nameless,

Stack frame (in most cases) is static structure, you don't have to balance it. Wink

Stack itself, on the other hand, is so dynamic that you can easily lose balance of pushs, pops and other things that change esp. Let's say that stack is balanced when esp has expected values at important locations (for example, at pop ebp it points to saved ebp value).

cdecl calling conventions, which wsprintf and .function use, requires caller to remove function arguments from stack. ccall/cinvoke macroinstructions handle this automagically (they count arguments while pushing them in stack and add appropriate constant to esp after the function was called).

stdcall calling conventions are almost similar to cdecl, but arguments are removed by callee (i.e. the function being called). That's where ret imm16 becomes handy: it combines functionality of simple ret with add esp, imm16.

Your new version looks better, yet there is some room for improvement. You don't have to preload function arguments in eax before invoking wsprintf, they can be passed to cinvoke directly (you'll need to specify argument size though — fasm can deduce it from mov eax, [ebp+8] but can't from push [ebp+8]).

----8<----
Picnic,

Didn't you mean void stdcall MyFunction(…?
Post 26 Sep 2010, 06:44
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1405
Location: Piraeus, Greece
Picnic 26 Sep 2010, 09:14
Oops, i edit my post Smile
Post 26 Sep 2010, 09:14
View user's profile Send private message Visit poster's website Reply with quote
Nameless



Joined: 30 Apr 2010
Posts: 95
Nameless 26 Sep 2010, 10:15
wohoooooooo Very Happy

thanks alot, i almost got it now

Code:
sub esp, 0Ch            ; space allocated on the stack for the local variables
    


local variables? so i can use push and pop freely inside the function? and when all done it gets back to normal?

or does "local variables" mean the variables created with the directive "locals ..... endl" ?
Post 26 Sep 2010, 10:15
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20518
Location: In your JS exploiting you and your system
revolution 26 Sep 2010, 10:44
Nameless wrote:
local variables? so i can use push and pop freely inside the function? and when all done it gets back to normal?
You still gotta match the pushes and pops (and also not over pop and eat up the higher memory space), otherwise, yes, you are free to use push/pop
Nameless wrote:
or does "local variables" mean the variables created with the directive "locals ..... endl" ?
Both. Locals/endl adjusts esp to make space for local variables.
Post 26 Sep 2010, 10:44
View user's profile Send private message Visit poster's website Reply with quote
Nameless



Joined: 30 Apr 2010
Posts: 95
Nameless 26 Sep 2010, 12:52
so whats the use of this line?
Code:
sub esp, 0Ch            ; space allocated on the stack for the local variables
    

??
Post 26 Sep 2010, 12:52
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20518
Location: In your JS exploiting you and your system
revolution 26 Sep 2010, 13:00
Nameless wrote:
so whats the use of this line?
Code:
sub esp, 0Ch            ; space allocated on the stack for the local variables
    

??
In case you want to store some stuff locally using ebp as a base register. You can use that, or push/pop, or both.
Post 26 Sep 2010, 13:00
View user's profile Send private message Visit poster's website Reply with quote
Nameless



Joined: 30 Apr 2010
Posts: 95
Nameless 26 Sep 2010, 13:06
im sorry to ask this, but can u show me an example?

thanks Smile
Post 26 Sep 2010, 13:06
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20518
Location: In your JS exploiting you and your system
revolution 26 Sep 2010, 13:09
Code:
mov ebp,esp
sub esp,4
mov [ebp-4],0x1234
;...
mov eax,[ebp-4]    


Last edited by revolution on 26 Sep 2010, 13:30; edited 1 time in total
Post 26 Sep 2010, 13:09
View user's profile Send private message Visit poster's website Reply with quote
Nameless



Joined: 30 Apr 2010
Posts: 95
Nameless 26 Sep 2010, 13:26
wohooooooooooooooooooo Very Happy <-------- Thats the real one Very Happy

i got it all now Very Happy, hehehe Very Happy

thanks alot Wink
Post 26 Sep 2010, 13:26
View user's profile Send private message 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.