Page 1 of 1

Setting up the stack: is the Wiki code correct?

Posted: Mon Dec 01, 2014 12:34 pm
by Espanish
According to [Wiki] the stack is set up so:

Code: Select all

SECTION .text

setup_stack:
    
    MOV  ESP, stack_end  ; Set the stack pointer

SECTION .bss

stack_begin:
    RESB 4096  ; Reserve 4 KiB stack space
stack_end:
My question: doesn't stack_end point one byte beyond the reserved space, instead of the 4096'th byte?
Shouldn't the stack setup be instead:

Code: Select all

MOV ESP, stack_end - 1

Re: Setting up the stack: is the Wiki code correct?

Posted: Mon Dec 01, 2014 12:37 pm
by iansjack
When pushing values to the stack the stack counter is pre-decremented. The code is correct.

Re: Setting up the stack: is the Wiki code correct?

Posted: Mon Dec 01, 2014 1:23 pm
by Espanish
iansjack wrote:When pushing values to the stack the stack counter is pre-decremented. The code is correct.
Thanks for answering.
On [this site] it writes that push first decrements ESP by 4 (one word). This would mean that if we set up a stack of size X bytes, we can only ever use X-3 bytes, with the current code.

I am considering to use the code below. Am I going too far to fix a non-issue?

Code: Select all

SECTION .text

setup_stack:
   
    MOV  ESP, stack_end - 1  ; Set the stack pointer

SECTION .bss

stack_begin:
    RESB 4096  ; Reserve 4 KiB stack space
    RESW 1
stack_end:

Re: Setting up the stack: is the Wiki code correct?

Posted: Mon Dec 01, 2014 1:50 pm
by Combuster
You're seeing ghosts.

- If you push something in 32-bit mode, you write 32 bits = 4 bytes to the stack.
- A word is not 4 bytes. For intel, it's two, and it can be anything else depending on the platform. Therefore it's a horrible term to use.
- A stack always has the values stored adjacent in memory, so it always uses exactly a multiple of 4 bytes. It makes no sense to add two bytes because they can't hold a full entry and would be wasted.
- A stack should be aligned. Anything else is a bug.

A 32-bit push decrements ESP by four, then writes four bytes at ESP (that is, ESP+0, ESP+1, ESP+2 and ESP+3). If you would still want to manually write a byte at ESP+4 you'd write after stack_end, and therefore not into any memory you've defined. If you point ESP at stack_end - 1 then the last byte of the stack doesn't get used (and you lose three at the other end)

Re: Setting up the stack: is the Wiki code correct?

Posted: Mon Dec 01, 2014 2:00 pm
by iansjack
If you don't understand what various instructions do to the registers and memory then the easiest thing to do is to single-step code in a debugger. Write a simple program that sets up a stack and pushes a value to it. Step that program in your debugger and watch what happens to the stack pointer and to the stack itself; then you will see how it works.

Again, the Wiki is correct - you set SP to stack_end not stack_end - 1.

Re: Setting up the stack: is the Wiki code correct?

Posted: Mon Dec 01, 2014 2:56 pm
by Espanish
Thank you for your posts. I misunderstood what stack_end stands for.
I thought stack_end points to an imaginary 4097'th byte, but instead it really does point to the last byte, 4096'th.

Here is a drawing to illustrate what I got wrong:

Code: Select all

stack_begin -> byte1
               byte2
               byte3
                ...
               byte4096
stack_end ->   byte4097 (?)

Re: Setting up the stack: is the Wiki code correct?

Posted: Mon Dec 01, 2014 3:06 pm
by Combuster
It does point after the last byte. It also points at 4096.

stack_begin points to the 0th byte.

Re: Setting up the stack: is the Wiki code correct?

Posted: Mon Dec 01, 2014 5:39 pm
by sortie
esp points to the last pushed value.