1

I came across “pushq %rsp” and I couldn’t figure out the exact operations CPU does.

On x86-64 Assembly,

.text
.globl pushtest pushtest:
  movq    %rsp, %rax
  pushq   %rsp
  popq    %rdx
  subq    %rdx, %rax
  ret

the return value %rax is 0, by subtracting the new value of %rsp in %rdx from the old value of %rsp in %rax.

But formal definition of push instruction is:

  1. decrement %rsp by 8
  2. push the designated value (in this case, the value of %rsp) onto the stack.

So when we do “pushq %rsp,” doesn’t it decrements the %rsp first, then push the decremented %rsp value onto the stack, which would result in the subtraction being 8 instead of 0?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
vsr3y
  • 29
  • 4
  • 2
    The manual (https://www.felixcloutier.com/x86/push) documents this special case. It pushes the *original* value. – Peter Cordes Mar 19 '20 at 18:05
  • 1
    That formal definition is over-simplified for the case where the "designated value" is the RSP register, or an addressing mode using RSP as the base. Intel's text description covers this; the Operation pseudocode doesn't really address it other than `src` being implicitly read into a temporary before the pseudocode starts. – Peter Cordes Mar 19 '20 at 18:15
  • 1
    It's interesting that you stumbled upon this. On the original 8086 processor, `push sp` would indeed first decrement `sp` and then push it. This was changed with the 80186 to push the value of `sp` before it is decremented to form the address of the value just pushed. – fuz Mar 19 '20 at 19:04
  • 1
    you could look at pushq as `movq src, -8(%rsp)` *then* decrement the stack pointer (all as one uninterruptible operation so the memory below RSP can't be clobbered by an interrupt) – Peter Cordes Mar 19 '20 at 19:09

0 Answers0