21

For example if I pushed ax is [SP] points to my value of ax or the word after ax? Also is it differs from real mode to protected mode? I ask this because the Art of assembly book illustrates and explains as the sp points to last pushed data, and on this page OSDev Wiki - Stack it illustrated as it points to empty word after last pushed data.

3
  • 2
    Intel reference manuals include pseudocode for each instruction. To answer your question, it points to the topmost value on the stack. Commented Dec 27, 2012 at 19:59
  • For 8086 SP pointed to the next free stack position, and for later x86 CPUs (starting with 80186 I think) it was changed so that SP points to the last used stack position. Because of this change there technically isn't one behavior that is correct for "all x86" (but in practice it's reasonable assume all x86 CPUs that you care about are new enough to have the same/new behavior). Commented Apr 2, 2022 at 10:26
  • @Brendan - The value the stack pointer points to ([SP + 0]) is always the last value pushed, the stack pointer being decremented before writing the value. The difference between the 8086/8088 and later x86 CPUs (starting with the 186) is the value pushed onto the stack if the stack pointer itself is pushed (PUSH SP): It used to be the value of SP after it was decremented, but later the pre-decremented value was saved, and that's the value that was pushed. (I think this came along with the PUSHA/POPA instruction, which also necessitated the original stack pointer to be saved.) Commented Oct 25, 2023 at 0:15

4 Answers 4

30

Wikipedia says here:

The stack is implemented with an implicitly decrementing (push) and incrementing (pop) stack pointer. In 16-bit mode, this implicit stack pointer is addressed as SS:[SP], in 32-bit mode it is SS:[ESP], and in 64-bit mode it is [RSP]. The stack pointer actually points to the last value that was stored, under the assumption that its size will match the operating mode of the processor (i.e., 16, 32, or 64 bits) to match the default width of the push/pop/call/ret instructions.

This is the way my way-back memory says it works, too.

Sign up to request clarification or add additional context in comments.

5 Comments

Ok thank you but do you have any idea why osdev wiki illustrates esp at after the end of the stack. Is that a mistake?
You can try it. Push something weird on the stack and then see if [esp] is the same value. Try it with several values to make sure it isn't an accident.
@user1180619: Stacks work upside down. They start at the high address, and work down from there. Don't know why, but that's how it is.
I went and looked at osdev wiki and you are right. It does show SP and ESP pointing at the empty spot after the top of the stack. (Well ... since the stack grows into lower memory addresses, it points 'before' the top stack entry.) I don't know why it does that. Perhaps they stole the diagrams from some other type of processor and failed to fix them up. If you notice all the descriptions and the code examples still work since they never show a move out of [ESP].
I am concerned that the examples on osdev showing how to reference parameters and stack variables are wrong for simple function calling. (Remember that some languages will pass arguments in registers depending on compile options. If they do that, the arguments take no stack space and the code runs faster. But there are only so many registers.)
24
push eax

Is equivalent to:

sub esp, 4
mov [esp], eax

So after a push, esp will hold the address of the pushed value.

Comments

2

As per Lee Meador's and Cory Nelson's answers, the stack pointer points on the last value that was pushed.

From the Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2 (2A, 2B & 2C): Instruction Set Reference, A-Z, the first line from the description of the PUSH instruction reads as follow:

Decrements the stack pointer and then stores the source operand on the top of the stack.

Comments

0

I think I understand why OP is asking this question. Why is the first variable 8 bytes from SP and not 4?

After some research I found this which indicates that:

SP+0 is the old EBP SP+4 is the old EIP (instruction pointer)

Hence, naturally, the first parameter is at SP+8.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.