flat assembler
Message board for the users of flat assembler.

Index > Main > A bit confused about functions and the stack.

Author
Thread Post new topic Reply to topic
gavin



Joined: 20 Jul 2008
Posts: 23
gavin 20 Jul 2008, 22:10
I've been reading about x86 calling conventions, stack frames and the function prologue.


Take this __cdecl C function for example.

Code:
Function(1,2,3); 
    

asm
Code:
segment .code USE32
..start
PUSH ebp
MOV  ebp, esp
SUB  esp, 12 
push 3
push 2
push 1
call [Function]
mov esp, ebp
pop  ebp
ret
    



Before going any further however, I have a few questions which need clearing up.

1:The function prologue above is the first bit of code after the start.. label.
Q:I push ebp but whose ebp is it? Why bother if it's the first line of code in my program?

2: When a function is called, the return address for the function call, which the program needs to resume execution, is put into the stack.

Q: Where is the return address in the above code?

I hope you understand my questions.
Thanks alot .
Post 20 Jul 2008, 22:10
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 21 Jul 2008, 00:55
Quote:
Q:I push ebp but whose ebp is it?

EBP pushed in epilogue is caller's EBP.

Quote:
Why bother if it's the first line of code in my program?
Your C code doesn't include any function. Prologue and epilogue is only created for functions, so your ASM example is invalid.

Quote:
Q: Where is the return address in the above code?

It's notin code. It is on stack, right above the EBP. RET takes it from stack, and returns there.
Post 21 Jul 2008, 00:55
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
asmhack



Joined: 01 Feb 2008
Posts: 431
asmhack 21 Jul 2008, 02:10
Code:
push eax
;push eax onto stack, esp is the stack pointer
;after the push, esp will be decreased by the size of the source (by 4 in this situation)
;the stack accessing is LIFO - last in, first out

eip
;address of the code to be executed

call function
;pushes the eip* of the next line of code
;changes the eip to function's address

ret
;go to the eip*
    
Post 21 Jul 2008, 02:10
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1900
DOS386 21 Jul 2008, 04:15
gavin wrote:
I've been reading about x86 calling conventions, stack frames and the function prologue.


Smile

> Q:I push ebp but whose ebp is it? Why bother if it's the first line of code in my program?

Indeed useless, many HL compilers do nevertheless Very Happy

> Q: Where is the return address in the above code?

CALL pushes it automatically Wink

PS: the forum is buggy and slow as hell again Sad

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 21 Jul 2008, 04:15
View user's profile Send private message Reply with quote
iic2



Joined: 26 Jun 2008
Posts: 122
iic2 21 Jul 2008, 19:44
Quote:
PS: the forum is buggy and slow as hell again

I find Google packet storm the forum connection even when you never use or went to google and I never seen no flood of vistors here. Fasm get top listing for free, all over the world, regarless. How many assemblers are there that start with the letter (F). Google come stepping in trying to get notice for free off top listing back. That should be illegal. That's my only guest and it need to be addressed. They are not doing this site owner or any other top lister any favors.

Nearly every time I visit I have to shut down, flush the cache and cookies, wait five minutes, than go back and seach the forum very carefully... ( I see no google packet for a long while ... sometimes)
Post 21 Jul 2008, 19:44
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 21 Jul 2008, 21:12
gavin: this isn't documented anywhere, so it could basically change in any later windows version... however, for the windows versions I've seen, the first code executed in a new process is not the code at your PE executable's "AddressOfEntryPoint", but some initialization code in system DLLs - this is also the reason that things like NTDLL and KERNEL32 are always injected in your process on XP, and why win2k silently(!) refuses to load an executable that doesn't import from kernel32 (whether directly, or through a chain of imports).

So, if you end your program by doing a 'ret', you land back in the kernel32 function that actually calls your entrypoint, and that eventually does exit your program cleanly. This is not documented behavior, though, so you should end with an ExitProcess call - and in that case, there's no point in doing register preservation for your entrypoint routine.

DOS386: for C/C++ programs, main() isn't the PE entrypoint, so that routine has to follow regular calling conventions. The PE entrypoint is in libc code, usually a file called "crt0", which handles setting up the environment (stdin/stdout, et cetera).
Post 21 Jul 2008, 21:12
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1900
DOS386 23 Jul 2008, 02:43
Thanks for the additional info Smile
Post 23 Jul 2008, 02:43
View user's profile Send private message Reply with quote
gavin



Joined: 20 Jul 2008
Posts: 23
gavin 23 Jul 2008, 18:06
You guys are great.
I've a few more questions I hope you don't mind.

Fodder I tried what you said and here it is in action.
The bottum attachment is the first one thennext is second and third then is the exit code,
As you can see I get an exitcode of 5 on that. Is there any reason to xor,eax,eax before I use the return.Or is this just a formality for most programs in nasm.

I've a few more questions aswell concerning c functions.

Code:
;NASM Win32 stack
;
;compile with:
;NASMW.EXE -fobj 2.asm
;link with:
;ALINK.EXE 2.obj -c -oPE

%include "D:\programming\nasm\include\windows.inc"

EXTERN ExitProcess
IMPORT ExitProcess kernel32.dll

segment .data USE32

segment .code USE32

..start
jmp here

function:
push ebp
mov ebp,esp
mov eax,[ebp+8]
mov edx,[ebp+12]
add eax,edx
mov [var],eax          ;put the sum into a variable
pop ebp
ret

here:
push 3
push 2
call function

add esp, 8

ret
;push 0
;call [ExitProcess]
    


Imagine the above is a C function that adds 2 numbers .
When I run this in my debugger it skips the call .When i change the call to a jump it crashes because it's missing what the call does.(push eip+2)

Am i correct?
Any ideas?

Thanks alot.


Description:
Filesize: 145.18 KB
Viewed: 7584 Time(s)

3.jpg


Description:
Filesize: 129.08 KB
Viewed: 7584 Time(s)

2.jpg


Description:
Filesize: 119.54 KB
Viewed: 7586 Time(s)

1.jpg


Post 23 Jul 2008, 18:06
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1900
DOS386 25 Jul 2008, 03:19
gavin wrote:
As you can see I get an exitcode of 5 on that. Is there any reason to xor,eax,eax before I use the return.Or is this just a formality for most programs in nasm.


It's not NASM's fault, it's calling convention -> return value 0.

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 25 Jul 2008, 03:19
View user's profile Send private message Reply with quote
gavin



Joined: 20 Jul 2008
Posts: 23
gavin 25 Jul 2008, 03:31
That whole sentence came out wrong.
What I was trying to convey was.Every program ends with the usual push 0 call exitprocess.After looking into fodders method of just using the ret instead of exit process, does the number 5 matter? Thats all.
Post 25 Jul 2008, 03:31
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 26 Jul 2008, 11:04
gavin wrote:
...
.After looking into fodders method of just using the ret instead of exit process, does the number 5 matter? Thats all.
...

You can use ret if your stack is balanced. It will return to BaseProcessStart and invoke ExitProcess as well.
Post 26 Jul 2008, 11:04
View user's profile Send private message Reply with quote
asmcoder



Joined: 02 Jun 2008
Posts: 784
asmcoder 26 Jul 2008, 11:59
[content deleted]


Last edited by asmcoder on 14 Aug 2009, 14:57; edited 1 time in total
Post 26 Jul 2008, 11:59
View user's profile Send private message Reply with quote
gavin



Joined: 20 Jul 2008
Posts: 23
gavin 27 Jul 2008, 13:23
Thanks for them tips much appreciated.
Post 27 Jul 2008, 13:23
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 29 Jul 2008, 04:25
asmcoder wrote:
Quote:
and invoke ExitProcess as well.

Not ExitThread? 0.o
You're 100 % correct! Both BaseProcessStart and BaseThreadStart invoke ExitThread, my mistake was rather mechanical (you know, "...ProcessStart..." then "...ExitProcess..." Wink).

There is some quirk, probably it's related to GUI subsystem and/or WMI: if you use GUI system call (I've checked at least MessageBox* and CreateWindow* on SP2), Windows create another thread using AdvAPI32!WmipEventPump, so you can't just do this:
Code:
invoke MessageBox, NULL, "Hello, world", "Greeting", MB_OK
ret    
or else your process will not terminate (as it has active thread, but not created by you Wink).

ExitProcess will mercifully kill that thread.

I'll try to research this further (I don't like when system does something behind my back, but when it doesn't clean up after... I simply go ballistic!).
Post 29 Jul 2008, 04:25
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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.