Archived

This topic is now archived and is closed to further replies.

XXXImp

asm question

Recommended Posts

Hello everyone. I’m trying to better understand how VC++ turns our C code into asm instructions. I have a few questions… Here is the C code int Test(int x, int y) { int temp = 0; int temp2 = 0; x = 0; temp = x + y; return temp; } Here is the asm code for this function with some questions 0: int Test(int x, int y) 41: { 70001030 push ebp 70001031 mov ebp,esp 70001033 sub esp,48h 70001036 push ebx 70001037 push esi 70001038 push edi 70001039 lea edi,[ebp-48h] 7000103C mov ecx,12h 70001041 mov eax,0CCCCCCCCh 70001046 rep stos dword ptr [edi] 42: int temp = 0; 70001048 mov dword ptr [ebp-4],0 43: int temp2 = 0; 7000104F mov dword ptr [ebp-8],0 44: x = 0; 70001056 mov dword ptr [ebp+8],0 45: temp = x + y; 7000105D mov eax,dword ptr [ebp+8] 70001060 add eax,dword ptr [ebp+0Ch] 70001063 mov dword ptr [ebp-4],eax 46: return temp; 70001066 mov eax,dword ptr [ebp-4] 47: } My question is, why when your manipulate the parameters(int x, int y), it adds to the ebp? Example : 70001056 mov dword ptr [ebp+8],0 but when you manipulate the local variables(temp and temp2), it subtracts from ebp? Exampe : 7000104F mov dword ptr [ebp-8],0 Other questions I have is, how big can the stack be for just that 1 function? Is there a limit of how much data can be used for that function in Win32(like a 1meg limit?), and if so, is there a switch to change the stack size for the function? The other question I have is with this part 70001030 push ebp 70001031 mov ebp,esp 70001033 sub esp,48h 70001036 push ebx 70001037 push esi 70001038 push edi 70001039 lea edi,[ebp-48h] 7000103C mov ecx,12h 70001041 mov eax,0CCCCCCCCh 70001046 rep stos dword ptr [edi] what is all this doing before I even do anything with my function? Thanks if anyone can help me. XXXImp

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The answer is in how the C compiler uses the stack.


When the compiler is going to call a function it pushes the arguments to the function (typically in reverse order), then does a "call" to the function. The "call" pushes the address to return to on the stack. Then the function typically copies the stack pointer into ebp register and subtracts however much space it needs for local variables. So the stack looks like this (with the stack growing downward):



ebp
offset
+0x0c int y (2nd parm pushed)
+0x08 int x (1st parm pushed)
+0x04 return address pushed by "call" instruction
+0x00 saved ebp register
-0x04 temp on stack
-0x08 temp2 on stack
(pad space from debug build filled with 0xcccccccc)
(esp moved -0x48 before these regs pushed)
-0x48 saved ebx
-0x4c saved esi
-0x50 saved edi
-0x54 new esp locatation (within function Test)


There is no real limit on stack size for 32 bit code except system memory. To use more stack space the function can subtract as much from esp as it needs to make room for its locals.


Sorry if this post got mangled...no preview option

Share this post


Link to post
Share on other sites
Thanks for responding. There are a few points i still don't understand. Ok, whenever you put new things on the stack, it should have a higher address than the thing before it, right? Ok, lets look at my function again.
int Test(int x, int y)
{
int temp = 0;
int temp2 = 0;
x = 0;
temp = x + y;
return temp;
}
I would think the stack looks like this :

temp2<==== end of stack frame
temp
x
y
function Address <==start of stack frame

but when i look at each variable address, that isn't correct, here are the variable address when i run it

y 0x0012f868
x 0x0012f864

---------------- gap in stack here, not sure what for?

temp 0x0012f858
temp2 0x0012f854

I wasn't sure how to find out the address of where the function is located? I thought maybe the gap in the stack was for the 32 bit address of the function, but 0x0012f864 - 0x0012f858 = 0x0c, which is not enough to hold a 32 bit address? So must be for something else. I tried to find it like this &Test, but this gives the address of where the function test is and not the address of where on the stack the address is located? In this example, it looks like the stack is growing down in address and not up in address? IF this is the case, once you hit 0x0000FFFF, you'll get an exception on Win2k because it's protected by the operating system. So, maybe someone can answer this question? Does the stack grow as in the address getting a higher number, or does it grow as LIFO, but the last thing on the stack will have a lower number, which means it grows down in address and not up?

XXXImp

Edited by - XXXImp on August 12, 2001 6:51:18 PM

Edited by - XXXImp on August 12, 2001 6:51:55 PM

Edited by - XXXImp on August 12, 2001 6:53:42 PM

Edited by - XXXImp on August 12, 2001 7:02:07 PM

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
No, the stack builds downward (towards lower memory addresses).
This is why the asm code _subtracts_ from esp to make "room" on the stack.

The gap you are talking about is shown in the diagram I posted.
The compiler saves several CPU registers on the stack as well as allocating some extra space to aid in debugging (the debug libs can check if the 0xcccccccc''s get overwritten indicating a bug).

The saved registers are reloaded when the function exits.

Is it starting to make sense yet?

Share this post


Link to post
Share on other sites