News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Stack and calls

Started by kemicza, January 23, 2011, 02:44:17 PM

Previous topic - Next topic

kemicza

I'm having some difficulty understanding why the ESP register is substracted by some value (depending on the local variables) at the beginning of a call, when a program is assembled with masm, or I think in general this is always done. My question is why?


PUSH EBP ; store previous base pointer (frame)
MOV EBP,ESP ; ebp now points to the beginning of our paramaters and return address
ADD ESP,-8 ; Why is this necessary?
MOV DWORD PTR SS:[EBP-8],EBX ; store ebx in our first local variable
MOV EBX,DWORD PTR SS:[EBP+8] ; access the first parameter
MOV EAX,DWORD PTR SS:[EBP+C] ; access the second parameter
ADD EAX,EBX ; our result is the sum of those parameters and returned in eax
LEAVE ; reorganises the stack, which is mov esp,ebp and pop ebp
RETN 8 ; return and add 8 to esp (our parameters)


I don't see the reason why ESP is substracted. I know why, but I mean esp is not used to access anything or to write. I mean EBP is always used to reference to local variables. It shouldn't matter if you substract 4 to esp, it's just a value in a register, which is not even used. The only reason I might think of, is for debugging purpose, if you follow the stack you will always see it grow/shrink, plus allowing you to see the local variables aswell, but I'm not sure if this is the real reason?

Thanks
kemicza

kemicza

I think I figured it out lol... The reason is probably because of other calls within that procedure. Stack has gots to be organized for the next call otherwise the local variables will be overwritten by paramaters that are pushed for the next call. But anyway, if your procedure doesn't have any other calls, then it's possible to not substract the stack pointer I suppose.

BogdanOntanu

The ESP register is subtracted with the size of the local variables. You need to have some space reserved for them and this SUB leaves an empty space on the STACK for local variables. If you do not subtract then the local variables have no space reserved for them and any other operation that involves the stack will overwrite them. For example a simple PUSH/POP to save a register in an outer loop will trash them.

EBP references the same space on the STACK for local variables and PROC arguments ... hence it does not matter is the read/write is done by ESP or EBP because both do  refer to the same addresses locations on the stack (but with a different offset)

Practically this SUB ESP, "size of local variables" is the fastest way to allocate some temporary memory for variables or buffers. Kind of what _alloca() does in C.
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

hutch--

kemicza,

Th code you posted is a more or less normal stack frame as MASM sets up a normal procedure. A common variation in MASM is to write a procedure with no stack frame which slightly drops the call / ret overhead and makes the EBP register available which often matters with speed critical algorithms. You can write them manually with a bit of practice but you need to understand that you have to adjust the address of any memory operand that relies on a stack address when you use PUSH or POP. With a fair bit more work you can code local variables in the same manner but the stack corrections are by no means intuitive.

Procedures with no stack frame are usually small "leaf" procedures.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Twister

Making local variables through the stack is somewhat ineffective because you only have so much space left on the stack.

hutch--

That is actually not correct, stack space in a win32 executable is set with the linker and it is common to have a 1 meg stack in very ordinary executables but if for example you were writing functions that high levels of recursion you simply allocate more on the stack through the linker options.

Allocating LOCAL variables on the stack is a very efficient technique and also very convenient as they are automatically deallocated on procedure exit and they tend to be closer in memory so their access speed is usually better.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

dedndave

also - the CPU instructions that reference stack data via EBP are likely to be well optimized
the only problem with using the stack is grabbing large chunks all at once
you may have to probe the stack down to the desired address prior to using it

MichaelW

The probe is necessary when you are operating in reserved stack space that has not been committed. Using the linker you can set the stack size wherever you need, and commit all of it.
eschew obfuscation

kemicza

Thanks for all the help :) !