First published on TECHNET on Jul 31, 2009
<br/>
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:
kd> r
eax=ffdff13c ebx=000000e2 ecx=00000000 edx=00000100 esi=80d10cc0 edi=80d10c08
eip=804fc1bb esp=fbbfebf4 ebp=fbbfec0c iopl=0 nv up ei ng nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000286
nt!KeBugCheckEx+0x19:
804fc1bb 5d pop ebp
eax=ffdff13c ebx=000000e2 ecx=00000000 edx=00000100 esi=80d10cc0 edi=80d10c08
eip=804fc1bb esp=fbbfebf4 ebp=fbbfec0c iopl=0 nv up ei ng nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000286
nt!KeBugCheckEx+0x19:
804fc1bb 5d pop ebp
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:
- esp = stack pointer
- ebp = base pointer
- eip = instruction pointer
- eax, ebx, ecx, edx = general-purpose registers that are used to store intermediate results
- edi, esi = used as general registers
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:
- push – adds an item to the top of the stack or initializes the stack if it is empty
- pop – removes an item from the top of the stack, or results in an empty stack
- add / sub – add / subtract operations
- cmp – compare the values of two
- ret – return to the calling function
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 ):
Assembly Code | Explanation |
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 …
Additional Resources:
Share this post : |
|
|
|
|
|
|
|
|
<br/>
Updated Mar 16, 2019
Version 2.0CraigMarcho
Microsoft
Joined March 15, 2019
Ask The Performance Team
Follow this blog board to get notified when there's new activity