X86 assembly procedure prologue help.

Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
12 replies · 4K views
perplexabot
Gold Member
Messages
328
Reaction score
5
Hey all, I was doing a bit of reading and ran into the following code (this is a function prologue for a main function, if you need more code or the actual C code let me know):

push ebp
mov ebp, esp
sub esp, 0x18
and esp, 0xblackf0
mov eax, 0x0
sub esp, eax

So I understand the first three lines. first save the base pointer to the stack, second assign the base pointer and lastly set the new stack pointer with enough space for the local variables.

What I don't understand are the last three lines. I know what the and, mov and sub opcodes do but I can't get the general picture. Also what exactly is eax used for? Is it a gpr? Those last three lines don't appear in regular functions, so I am guessing it has something to do with the main function.

Any help will be much appreciated, thank you.
 
Physics news on Phys.org
"and esp, 0xblackf0" - truncates esp to a 16 byte boundary

"mov eax, 0x0" "sub esp, eax" - accomplishes nothing.
 
  • Like
Likes   Reactions: 1 person
rcgldr said:
"and esp, 0xblackf0" - truncates esp to a 16 byte boundary

"mov eax, 0x0" "sub esp, eax" - accomplishes nothing.

Hmmm thank you. If you don't mind me asking though, why truncate it and why have the second to last line if it does nothing (I can see that it does nothing)?

Thanks.
 
One possibility is that some type of structure that is some multiple of 16 bytes long could be allocated on the stack. For example, the "mov eax, 0x0", could instead be "mov eax, 0x40", to allocate 64 bytes from the stack on a 16 byte boundary. I haven't seen this done with any of the microsoft compilers I use. Perhaps the space is allocated for some type of optional debug mode.
 
Last edited:
  • Like
Likes   Reactions: 1 person
rcgldr said:
One possibility is that some type of structure that is some multiple of 16 bytes long could be allocated on the stack. For example, the "mov eax, 0x0", could instead be "mov eax, 0x40", to allocate 64 bytes from the stack on a 16 byte boundary. I haven't seen this done with any of the microsoft compilers I use. Perhaps the space is allocated for some type of optional debug mode.

Thank you.
 
rcgldr said:
"and esp, 0xblackf0" - truncates esp to a 16 byte boundary

That may be to optimize the access speed to physical memory, and/or the CPU chip's memory cache(s).

"mov eax, 0x0" "sub esp, eax" - accomplishes nothing.

I'm not sure, but could that reset some of the CPU flags to a known state? (this sort of trick can be quicker than setting the flags directly).

It certainly sets eax to a known state, so it does accomplish "something".
 
  • Like
Likes   Reactions: 1 person
"mov eax, 0x0" "sub esp, eax" - accomplishes nothing.

AlephZero said:
I'm not sure, but could that reset some of the CPU flags to a known state? (this sort of trick can be quicker than setting the flags directly).
The flags are just set to indicate the unsigned result is greater than zero (esp - 0). I doubt it's used, as the cpu flags will get set again on any math like instruction that occurs later.

"mov eax, 0x0"

AlephZero said:
It certainly sets eax to a known state, so it does accomplish "something".
But it's likely that eax is going to get changed during the function. eax is the return values so a return(0) will translate into "mov eax,0", or more likely "xor eax,eax", but at the end of the function, just before "ret". As mentioned before, I haven't seen those last 3 lines of function header code with microsoft compilers.
 
Interesting, I didn't know that eax was for the return values. Good info. Thanks.
I also was wondering if those last three lines were compiler optimizations.
 
perplexabot said:
I also was wondering if those last three lines were compiler optimizations.
Just the opposite, optimization would not add lines of code that accomplish nothing. What compiler generated that code?
 
rcgldr said:
Just the opposite, optimization would not add lines of code that accomplish nothing. What compiler generated that code?

Hmmm, that makes sense, thank you for correcting my logic. This was disassembled using gdb.
 
perplexabot said:
Hmmm, that makes sense, thank you for correcting my logic. This was disassembled using gdb.
I was wondering what compiler created that code, not how you disassembled it.
 
Oops, sorry, was compiled using gcc.
 
perplexabot said:
Oops, sorry, was compiled using gcc.
See what the various options are for gcc, perhaps ones that disable any debug stuff and increase optimization to see if you get the same function entry code.