0

(sorry, bad english)

Machine: PC with Windows 64-bit.
Compiler: 32-bit

push 11
push 22
mov eax, [esp+4]   ; eax == 11 == ok

I don't understand why this code works.
PUSH always pushes 64-bits on a 64-bit CPU, right?
Then why don't I have to use [esp+8] instead of [esp+4]?

Anyone have an explanation please?

Teddy
  • 19
  • 1
  • 2
    64-bit windows can run 32-bit code. 32-bit programs can run in 32-bit compatibility mode under a 64-bit Windows. In that environment 4 bytes are pushed. I assume that this code you are running is 32-bit code since you say you use a 32-bit compiler. – Michael Petch Jun 23 '22 at 10:50
  • @MichaelPetch Out of curiosity, is reading **E**SP valid in 64-bit mode? I mean, I know it will assemble, but can it work without unintended behaviour? – xiver77 Jun 23 '22 at 11:28
  • In 64-bit code You can use the value in ESP but it is only the lower 32-bits of RSP. So without the top 32-bits of RSP, using ESP could be pointing at the wrong place in memory. – Michael Petch Jun 23 '22 at 11:37
  • 1
    @xiver77 If the stack pointer points into the low 4 GB of memory, it can work. – fuz Jun 23 '22 at 11:51
  • 1
    @xiver77: 32-bit address-size is supported in 64-bit mode. But most mainstream OSes put the stack outside the low 32 bits of virtual address space in 64-bit processes, so ESP != RSP, i.e. RSP has some bits set in the high 32. and thus `mov eax, [esp+4]` will access an invalid address and segfault. One exception to this is the Linux x32 ABI (ILP32 in 64-bit mode), where `[esp+whatever]` works (because ESP is correctly zero-extended into RSP). That missed-optimization for `gcc -mx32` was fixed in GCC8 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82267). This is totally separate from `-m32`. – Peter Cordes Jun 23 '22 at 13:19
  • 1
    *PUSH always pushes 64-bits on a 64-bit CPU, right?* - No, only when the 64-bit CPU is running in 64-bit *mode*. https://en.wikipedia.org/wiki/X86-64#Operating_modes – Peter Cordes Jun 23 '22 at 13:24

0 Answers0