I was going through the C code in which i have to figure out the number of registers used in a particular trace of program.The code was neglecting to store ESP register whenever push or pop commands were encountered .I also referred X86 instructions,and it was written there "ESP,stack pointer,should not be used" .why??
3 Answers
On the x86, ESP is the stack pointer. Originally, on the 16-bit 8088 and 8086 processors, the register was simply called SP, for Stack Pointer. When 32-bit support was added in the 386 processor, the E prefix (for "extended") was added to all register names, so it became ESP. The stack pointer always has the same bit width as the processor's native word size in the current mode. That is, if you're executing in 32-bit protected mode, the stack pointer will be 32 bits wide and stored in ESP. If you're executing in 16-bit real mode, the stack pointer will be 16 bits wide and stored in SP.
The 64-bit extensions to the x86 architecture (variously known as AMD64, x86-64, or just x64) widened the registers to 64 bits and added the R prefix. Thus, the RSP register contains the stack pointer, which is 64 bits wide when executing in long (64-bit) mode.
Although this register is conceptually similar to the other registers (EAX, ECX, EDX, EBX, ESI, EDI, and EBP), it cannot be used in an equivalent fashion. It is designed only to hold the stack pointer and cannot be used as a general-purpose register.
The reason you do not explicitly push or pop the stack pointer is because this is done implicitly by other instructions. In fact, the PUSH and POP instructions are the ones that manipulate the stack pointer, since they push and pop things to the stack.
On x86, the stack always grows downwards in memory, so PUSH will subtract the appropriate number of bytes from the stack pointer (according to the size of the operand), while POP will add the appropriate number of bytes.
The CALL and RET instructions also implicitly manipulate the stack pointer. You can find more details by reading the Intel x86 architecture manuals, available here. There are lots of other resources available in the x86 tag wiki.
The only time you will see the ESP register being explicitly manipulated is when it is used as the destination operand in an ADD or SUB instruction. These are commonly inserted in a function's prologue and epilogue by optimizing compilers, incrementing or decrementing the stack pointer as necessary to make extra room to store values or to clean up the stack. They function similarly to PUSH and POP, except that they can have the effect of multiple pushes and pops in a row. For instance:
push eax
push eax
push eax
push eax
...
pop eax
pop eax
pop eax
pop eax
can be replaced with simply:
sub esp, 16
...
add esp, 16
(assuming that you were not actually trying to store the value of EAX and were just using the PUSH to make room on the stack).
- 541
- 5
- 13
- 239,200
- 50
- 490
- 574
it should not be used as General Purpose Register. Feel free to use it as a stack pointer with appropriate care. E.g. you may reserve some memory for local vars on the stack with 'sub esp, ...' instruction, but you must restore its original value before the ret instruction
- 6,088
- 17
- 27
-
from ur answer i make out that ,Its value must be restored because that's the only registers which points where to store the data on the stack rite>?so is that the reason they discourage it from messing things up? – archies50 Sep 19 '12 at 22:43
ESP is the stack pointer that push/pop depend on.
ESP is call-preserved (or approximately so in conventions where the caller pops args off the stack), but you achieve that by balancing your pushes and pops so it ends up pointing at the return address pushed by your caller when you reach the ret instruction.
You don't actually save/restore ESP because you leave it pointing at the stack while your function executes.
[esp] is the implicit destination where push ebx writes. (After decrementing ESP by 4).
You can't use push/pop to save/restore ESP and use it for something else, because ESP is the pointer to where you pushed stuff.
pop esp is equivalent to mov esp, [esp]; it depends on the old value, and not useful for "restoring" if you'd destroyed it.
If you wanted to use ESP as an extra temporary register, you could save it in mm0, or (in a non-thread-safe function) in a static storage location. You should usually not do this; it's mostly useful to understand that you could as an exercise in understanding how the machine works.
Any signal handler or exception handler that tries to run while ESP is pointing somewhere other than the stack will cause a big problem. (But in user-space under a multitasking OS, interrupt handlers will run on the kernel stack. Only in kernel code will the hardware asynchronously use memory below ESP).
- 328,167
- 45
- 605
- 847