News:

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

Stack addresses

Started by n00b!, October 05, 2008, 07:49:57 PM

Previous topic - Next topic

n00b!

Hello,
I have a problem with the stack addresses for local variables.

test proc a:DWORD
mov eax, a ;address of a is ebp - 4
ret
test endp

main:
push 0
call test
end main


I think this should be alright, but doesn't the stack address has to get incremented, like this:

test2 proc b:DWORD
mov eax, b ;address of b is ebp - 8
ret
test2 endp

test proc a:DWORD
mov eax, a ;address of a is ebp - 4
push 0
call test2
ret
test endp

main:
push 0
call test
end main


So the stack address is relative to the caller or is it absolute in every proc?
Thanks!

jj2007

Assemble your program and run it with OllyDbg, step by step using F7. Watch what esp and ebp are doing. Everything will be crystal clear...

n00b!

So (for example) the first parameter is always ebp - 4, the second is ebp - 8, etc. since EBP always points to the stack-room, which is actually used?

RuiLoureiro

Quote from: n00b! on October 05, 2008, 07:49:57 PM
So the stack address is relative to the caller or is it absolute in every proc?
Hello
           It is absolute in every proc. Your     test2   proc    b:DWORD
                                                             ....
                                                             ret
                                                             test2  endp
would be
                        push     ebp
                        mov      ebp, esp
                        ....
                        pop      ebp
                        ret        4
Rui

jj2007

Quote from: n00b! on October 05, 2008, 08:52:37 PM
So (for example) the first parameter is always ebp - 4, the second is ebp - 8, etc. since EBP always points to the stack-room, which is actually used?
Exactly: mov ebp, esp creates a stack frame, i.e. a fixed temporary memory range relative to ebp, the base pointer. ebp remains constant, esp can be modified by push & pop.

n00b!

Ohh, I got it, Thanks  :bg

But I don't see this stack frame when debugging the sample application...
There's only an ENTER 0, 0 with a LEAVE

ebp remains constant, esp can be modified by push & pop.
I don't get what you say :-/

Btw: For what is ESP? What value does it hold?

BogdanOntanu

noob!

Tell me: is this code where you "see" ENTER 0,0 your code or you are reversing somebody else's code?

You ask questions that are suspicious and apparently way above your understanding of ASM as a newbie.

You also ask questions that are too vague and with little or no details about your project and why you think that you need to do things this way.

You should do more simple things first and I am sure that MASM does handle LOCAL variables, arguments and stack frames quite OK for what you need.  Hard coding EBP+xxx values is not the right way to go for a newbie. Maybe if you explain why you need this info we can direct you to other more safe and more sane ways of obtaining the very same results.

Answer my question about who's code it is....
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

japheth

Quote from: BogdanOntanu on October 06, 2008, 02:33:08 AM
noob!
Tell me: is this code where you "see" ENTER 0,0 your code or you are reversing somebody else's code?

You ask questions that are suspicious and apparently way above your understanding of ASM as a newbie.

You also ask questions that are too vague and with little or no details about your project and why you think that you need to do things this way.

You should do more simple things first and I am sure that MASM does handle LOCAL variables, arguments and stack frames quite OK for what you need.  Hard coding EBP+xxx values is not the right way to go for a newbie. Maybe if you explain why you need this info we can direct you to other more safe and more sane ways of obtaining the very same results.

Answer my question about who's code it is....


He might just use Tasm instead of Masm. Tasm prefers the ENTER 0,0 opcode to initialize the stack frame.

There is nothing suspicious with noob!'s questions.

n00b!

Hi, sorry I used pasm to assemble this.
It's the code from above.

And I want to know about ebp because I have a bunch of local variables, like:

foo proc
local a:DWORD
local x:DWORD
local y:DWORD
local m:BYTE, n:BYTE, o:BYTE
local val:WORD
endp


And I don't want to initialize them like this:

mov a, 0
mov x, 0
mov y, 0
mov m, 0
mov n, 0
mov o, 0
mov val, 0


I thought it would be nicer to create a loop which goes from offset of a to offset of val and writes zeros there :-/

PS: And this ENTER 0, 0  does the mov ebp, esp, too?
I read opcodes.chm but I understand it only a bit abstract (It creates a stack frame... but how?) and I don't know what it does exactly...

Thank you very much :U

jj2007

Quote from: n00b! on October 06, 2008, 10:50:54 AM

I thought it would be nicer to create a loop which goes from offset of a to offset of val and writes zeros there :-/

ClearLocVars proc ; first instruction after LOCALS - eax will be zero on exit
pop ClvEsp ; save the return address to a global variable - now
; the stack is identical to the calling procedure
xchg eax, ecx ; save ecx
mov ecx, ebp ; base page of calling procedure
sub ecx, esp ; ebp - esp = No. of bytes in locals
mov esp, ebp ; discard existing locals
shr ecx, 2 ; divide by four
@@: push 0 ; dwords on stack
loop @B
xchg eax, ecx ; restore ecx, 0 to eax
push ClvEsp ; restore the return address
ret
ClearLocVars endp

BogdanOntanu

Quote
Hi, sorry I used pasm to assemble this.
It's the code from above.

And I want to know about ebp because I have a bunch of local variables, like:

Code:
foo proc
local a:DWORD
local x:DWORD
local y:DWORD
local m:BYTE, n:BYTE, o:BYTE
local val:WORD
endp

And I don't want to initialize them like this:

Code:
mov a, 0
mov x, 0
mov y, 0
mov m, 0
mov n, 0
mov o, 0
mov val, 0

I thought it would be nicer to create a loop which goes from offset of a to offset of val and writes zeros there :-/

PS: And this ENTER 0, 0  does the mov ebp, esp, too?
I read opcodes.chm but I understand it only a bit abstract (It creates a stack frame... but how?) and I don't know what it does exactly...

Thank you very much ThumbsUp

OK then but still I can not find this "pasm" assembler :P what purpose do you ahve in using it?

If you are using TASM as a noob then maybe it is better to switch to MASM or Japeth's JWASM that is almost fully compatible with MASM and has a "commercial free" license. This way we could help you better and faster.

TASM has some strange bugs. As experienced programmers we can work arround that bugs but for a newbie they can block you for weeks or months or even worst point you into the wrong conceptual direction. Besides TASM is not free and you have to buy it to be correct and we can not answer questions about it if you did not buy it. (Yes I did buy it with invoice)


Hence IF you just want to clear the LOCALS then you should be aware that:
1) Yes ENTER also makes mov ebp,esp and sub esp,size_of_locals. hence fisrt local is at ebp-4 next local at ebp-8 and so on...
2) ENTER also makes something extra but only IF the second parameter is not zero and this is rare

3)Take care with jj2007  code because MASM and other compilers will generate the PROLOGUE at first instruction they find in PROC's body.

Hence if USES ebx,esi,edi is present THEN you will also erase the saved registers because at the first instruction ESP will point after the PUSH for USES.

However this location might depend on the compiler/assembler because is is their duty to make the stack frame in PROC and each assembler can have small variations. Oh...and saving a stack return address to a global variable is not a good idea.

In this case maybe it is better that you manage your own Stack FRAME (for locals, arguments and uses)  like this:

start:
push ebp
mov ebp,esp
add esp, size_of_locals

... your code here

end:
mov esp,ebp
pop ebp
ret size_of_arguments


This way you can control things "better" but you will have to do extra work by hand. PROC usually does this work for you.


What you could also do it to get the address ot first local and the address of last local and do a REP STOSB or STOSD with zero there.


lea edi, last_local
mov eax,edi
lea ecx, first_local
sub ecx,eax ; size of locals
xor eax, eax
rep stosb


Observe that the first local is at a higher address that last local ;)
Of course you could also shr ecx,2 ... stosd :P


To japeth
Quote
He might just use Tasm instead of Masm. Tasm prefers the ENTER 0,0 opcode to initialize the stack frame.
There is nothing suspicious with noob!'s questions.

Yes I know but it is my "job" to ask the "bad" questions here and get the blame for it. Somebody has to do it and I can take "the hit" :D If people answer nicely and decent then nothing "happens" ...

Besides did he buy TASM? and as I have said above TASM might be OK for me and for you but for a newbie it is a hard bumpy ride.


Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

jj2007

Quote from: BogdanOntanu on October 06, 2008, 04:42:16 PM
3)Take care with jj2007  code because MASM and other compilers will generate the PROLOGUE at first instruction they find in PROC's body.

Hence if USES ebx,esi,edi is present THEN you will also erase the saved registers because at the first instruction ESP will point after the PUSH for USES.

Bogdan is right, there should be a warning. There is a simple workaround - instead of uses esi edi,  do the push & pop manually:

MyProc proc arg1:DWORD ....
LOCAL a, b, c
LOCAL chrg:CHARRANGE
call ClearLocVars
push esi
push edi
...
pop edi
pop esi
ret
MyProc endp

This works fine.

Vortex


n00b!

Uff, thanks for your elaborate answers  :D
Pasm is Paradigm Assembler :P

"If you are using TASM as a noob"
Newb[ie] means that you're simply not experienced but you'll learn it.

Noob means that you're not experienced and you won't learn it because you're an unskilled idiot.
Thanks for this :P

PS: I'm just looking trough the assembled codes in OllyDbg, it's very enlightening :0

invoke hello, 5, 0
pushes the 0 to the stack, then the 5, after that the eip of the next instruction and then comes a jump to offset hello.
That means, that the parameters of a procedure are not in the stack frame.
After the procedure follows a ret with the size of the parameters to correct the stack.
some kind like this:
00002C - esp
000030 - local d:DWORD
000034 - local c:BYTE
000038 - local b:DWORD
00003C - local a:DWORD
000040 - ebp


And the distance between the stack addresses are always 4Byte long. (Why? )
Means, even if you write local a:BYTE, b:DWORD it will produce a = ebp - 4, b = ebp - 8 (not 5...)

address of b is equal to ebp - 8 what is equal to esp + 4,  esp defines the upper bound of the stack frame, ebp the lower.

But esp and ebp points to unused stack locations, isn't this wastage of Memory, to reserve Bytes on the stack which won't be used?

ENTER 4, 0
(Shouldn't the first value ever be a power of 4? )
reserves 4 Bytes on the stack. means "local mylocvar"
equal to add esp, 4

LEAVE
equal to sub esp, 4

Is this by then correct?

Vortex

n00b!,

Take it easy, nobody wants to hurt you here. People are trying to help you. Using Tasm requires some additional level of experience and I am sure you will reach this point after doing some practices with Masm.