Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


How to use "srand" correctly?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
Dr.Disrespect
Grandmaster Cheater
Reputation: 3

Joined: 17 Feb 2016
Posts: 526

PostPosted: Fri Mar 25, 2016 7:58 pm    Post subject: How to use "srand" correctly? Reply with quote

I have searched the forum and found a template of how to use "srand":
Code:

//Only once in a module {
  call getTickCount
  push eax
  call srand
//}

// as much as required
  call rand
// a new random number in eax
 call rand
// a new random number in eax


My questions is: where do I pop eax? or do I need to? Thanks in advance.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Fri Mar 25, 2016 9:11 pm    Post subject: Reply with quote

srand uses the cdecl calling convention, so the caller is responsible for cleaning up the stack. Just write add esp,4 after call srand.
_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Dr.Disrespect
Grandmaster Cheater
Reputation: 3

Joined: 17 Feb 2016
Posts: 526

PostPosted: Fri Mar 25, 2016 9:51 pm    Post subject: Reply with quote

ParkourPenguin wrote:
srand uses the cdecl calling convention, so the caller is responsible for cleaning up the stack. Just write add esp,4 after call srand.

Thank you so much for the reply. Do I also need to "add esp,4" after "call rand" since the result will be store in eax?

PS: where to find all this information? Thank you.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Fri Mar 25, 2016 10:04 pm    Post subject: Reply with quote

No, you don't need it.

When you pass an argument to a call, you push it on the stack. cdecl is a caller-cleanup calling convention, so the caller needs to clean up the stack. Since you only pushed one argument onto the stack (the seed), you need to add 4 bytes to esp to clean it up. You do not need to do this for the call to rand since rand doesn't need any arguments passed to it for it to work.

You can find this information from tutorials on x86 online. There's this CEF topic, but it's pretty oversimplified. This YouTube playlist is also an option, but it's pretty lengthy and has a bit more intricate diction compared to the CEF topic.

Please note everything I said is only relevant for a 32-bit process. x64 has a significantly different calling convention.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Dr.Disrespect
Grandmaster Cheater
Reputation: 3

Joined: 17 Feb 2016
Posts: 526

PostPosted: Fri Mar 25, 2016 10:14 pm    Post subject: Reply with quote

ParkourPenguin wrote:
No, you don't need it.

When you pass an argument to a call, you push it on the stack. cdecl is a caller-cleanup calling convention, so the caller needs to clean up the stack. Since you only pushed one argument onto the stack (the seed), you need to add 4 bytes to esp to clean it up. You do not need to do this for the call to rand since rand doesn't need any arguments passed to it for it to work.

You can find this information from tutorials on x86 online. There's this CEF topic, but it's pretty oversimplified. This YouTube playlist is also an option, but it's pretty lengthy and has a bit more intricate diction compared to the CEF topic.

Please note everything I said is only relevant for a 32-bit process. x64 has a significantly different calling convention.


Thanks for the info. I will ask one last question on this topic (sorry for asking too much): what do you mean by cleaning it up? Pushing onto the stack means save it in the memory block, right? By adding esp by 4, what actually happens in memory? I have read some tutorials, but I still cannot get a clear understanding about stack and stuff relates to it, such as esp, ebp, especially when adding esp with X or subtracting esp with X, or mov ebp,esp, or the other way around.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Fri Mar 25, 2016 10:53 pm    Post subject: Reply with quote

The term "the stack" refers to a section of contiguous memory that's used as a storage space for data. It's called a stack because you push and pop stuff on and off of it. When you push something on the stack, you take that data and put it at the very top of the stack, on top of everything else. When you pop something off of the stack, you take off whatever is on the top of the stack and use that.

The ESP register always stores the address of the very top of the stack. In other words, [ESP] is the value at the top of the stack. What's confusing for most beginners is the fact that the stack grows downwards. When you push something onto the stack, you're actually decreasing ESP by 4 and moving the data into the new top of the stack. Vise-versa for popping something off the stack. As an example:
Code:
push eax
// is equivalent to:
sub esp,4
mov [esp],eax

// ...and:
pop eax
// is equivalent to:
mov eax,[esp]
add esp,4

In your case when calling srand, it needs one argument in order to work: the seed. According to the cdecl calling convention, the arguments are passed to the function through the stack. So, you push the value onto the stack. The value in this case is eax- what the call to getTickCount returned. So, you push that onto the stack, call srand, and everything is happy.

After that call, however, that argument you passed to the function is still on the stack. That's because cdecl requires the caller to clean up the arguments. Since you don't care about the value returned by getTickCount anymore, you don't need to pop that value into any register, so you can clean it up by simply adding 4 to ESP.

Note that not all functions use the cdecl calling convention. If some function uses a callee-cleanup calling convention (e.g. stdcall), then you don't have to worry about cleaning up the arguments since that subroutine will clean it up for you.


As for EBP, that register deals with stack frames. Stack frames are basically sections of the stack, and EBP stores where the current stack frame begins (the current stack frame always ends at the top of the stack). Significant subroutines will usually have their own stack frame. Side note: a subroutine is something that you can call; think of it like a function, more or less. When a subroutine is called to run, it will (usually) establish it's own stack frame with these instructions:
Code:
push ebp     // backs up calling subroutine's stack frame
mov ebp,esp  // establishes this subroutine's own stack frame

Once a subroutine does whatever it's suppose to do, it tears down it's stack frame and restores the calling subroutine's stack frame like so:
Code:
mov ebp,esp  // modifies the top of the stack (sometimes not needed)
pop ebp      // restores backup

Note that there are many ways to deal with stack frames. Sometimes, you'll see an enter and/or leave instruction, and other times, you may not even see a stack frame. Sometimes it's better to treat EBP as a general-purpose register.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Dr.Disrespect
Grandmaster Cheater
Reputation: 3

Joined: 17 Feb 2016
Posts: 526

PostPosted: Fri Mar 25, 2016 11:04 pm    Post subject: Reply with quote

ParkourPenguin wrote:
The term "the stack" refers to a section of contiguous memory that's used as a storage space for data. It's called a stack because you push and pop stuff on and off of it. When you push something on the stack, you take that data and put it at the very top of the stack, on top of everything else. When you pop something off of the stack, you take off whatever is on the top of the stack and use that.

The ESP register always stores the address of the very top of the stack. In other words, [ESP] is the value at the top of the stack. What's confusing for most beginners is the fact that the stack grows downwards. When you push something onto the stack, you're actually decreasing ESP by 4 and moving the data into the new top of the stack. Vise-versa for popping something off the stack. As an example:
Code:
push eax
// is equivalent to:
sub esp,4
mov [esp],eax

// ...and:
pop eax
// is equivalent to:
mov eax,[esp]
add esp,4

In your case when calling srand, it needs one argument in order to work: the seed. According to the cdecl calling convention, the arguments are passed to the function through the stack. So, you push the value onto the stack. The value in this case is eax- what the call to getTickCount returned. So, you push that onto the stack, call srand, and everything is happy.

After that call, however, that argument you passed to the function is still on the stack. That's because cdecl requires the caller to clean up the arguments. Since you don't care about the value returned by getTickCount anymore, you don't need to pop that value into any register, so you can clean it up by simply adding 4 to ESP.

Note that not all functions use the cdecl calling convention. If some function uses a callee-cleanup calling convention (e.g. stdcall), then you don't have to worry about cleaning up the arguments since that subroutine will clean it up for you.


As for EBP, that register deals with stack frames. Stack frames are basically sections of the stack, and EBP stores where the current stack frame begins (the current stack frame always ends at the top of the stack). Significant subroutines will usually have their own stack frame. Side note: a subroutine is something that you can call; think of it like a function, more or less. When a subroutine is called to run, it will (usually) establish it's own stack frame with these instructions:
Code:
push ebp     // backs up calling subroutine's stack frame
mov ebp,esp  // establishes this subroutine's own stack frame

Once a subroutine does whatever it's suppose to do, it tears down it's stack frame and restores the calling subroutine's stack frame like so:
Code:
mov ebp,esp  // modifies the top of the stack (sometimes not needed)
pop ebp      // restores backup

Note that there are many ways to deal with stack frames. Sometimes, you'll see an enter and/or leave instruction, and other times, you may not even see a stack frame. Sometimes it's better to treat EBP as a general-purpose register.


Thank you for clarifying for me. Sometimes I see "sub esp,16" or even"sub esp,28" instead of "sub, esp,4". I suppose that has something to do with the size of the value on the stack, right? This is really my last question. Very Happy
Thank you again, my friend!
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Fri Mar 25, 2016 11:18 pm    Post subject: Reply with quote

Kind of. It's almost always safe to assume everything inside the stack is 4 bytes long (in a 32-bit process). As such, subtracting more from ESP just means it intends on storing more things on the stack.

It's common to see an application substantially subtracting from the ESP register near the beginning of a subroutine. This is to allocate space for local variables in the subroutine. If it can, it will only use general-purpose registers for the local variables since that's faster than accessing memory. If you've got a big function (or a really unoptimized compiler), however, it may subtract a lot from ESP to allocate enough space for everything.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Dr.Disrespect
Grandmaster Cheater
Reputation: 3

Joined: 17 Feb 2016
Posts: 526

PostPosted: Fri Mar 25, 2016 11:25 pm    Post subject: Reply with quote

ParkourPenguin wrote:
Kind of. It's almost always safe to assume everything inside the stack is 4 bytes long (in a 32-bit process). As such, subtracting more from ESP just means it intends on storing more things on the stack.

It's common to see an application substantially subtracting from the ESP register near the beginning of a subroutine. This is to allocate space for local variables in the subroutine. If it can, it will only use general-purpose registers for the local variables since that's faster than accessing memory. If you've got a big function (or a really unoptimized compiler), however, it may subtract a lot from ESP to allocate enough space for everything.

Got it, thanks a lot. Smile
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites