Welcome back AskPerf! Carrying on with our debugging / architectural theme from the last couple of weeks, today’s topic is about the stack. A stack is a way of storing information – a data structure. When a new object is placed on the stack it is placed on the top of the stack. Similar to a stack of plates, papers or anything else that you can stack and manipulate in the real world, the first thing removed from the stack is the last thing put on. This is referred to as LIFO – Last In, First Out.
There are two fundamental operations that are performed on the stack, the push and the pop . A push operation initializes the stack if it is empty, and if there are items already on the stack, then the push operation adds an item to the top of the stack. The pop operation removes an item from the top of the stack. The pop operation exposes the next item on the stack, or results in an empty stack.
Stack information is stored in values called registers. If you are analyzing a dump using the Windows Debugger, you can see what the register values are by using the r command as shown below:
If you haven’t done any debugging or programming, the output of the r command probably looks like gibberish. Don’t worry – once you learn how to decipher the information, it becomes clearer. The most common registers that you’ll see are listed below:
When we’re looking at a stack trace in a debugger, what we’ll be looking at is assembly code. There are a number of instructions that can be used in assembly, but some of the most common ones that you’ll see are listed below:
Armed with this information, here’s what a very simple assembly routine might look like (this is taken from an MSDN Article called Anatomy of a Stack Trace ):
|push ebp||Places the caller's base pointer (ebp) onto the stack|
|mov ebp,esp||Sets the base pointer (ebp) equal to the stack pointer (esp)|
|mov eax, [ebp+8]||Grab the value of the first argument off the stack and store it in eax|
|add eax, [ebp+c]||Add the second argument's value to the value in eax|
|pop ebp||Restore the caller's base pointer|
|ret 8||Return to the calling function and remove 8 bytes from the stack|
It may look extremely confusing, but what this routine does is add two values. Again, don’t worry too much if you’re not an Assembly language guru or if things here aren’t 100% clear – the purpose of this post is just to get our feet wet. In future posts, we’ll be digging in a little deeper and things should become clearer.
That’s all for today folks! Hope you enjoyed this post. Until next time …
|Share this post :||
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.