0

I've noticed that I'm only allowed to do push on an 8 byte or 2 byte value. For example:

push $5 # same as pushq
# sub  $8, %rsp
# movq $5,(%rsp)

Or:

pushw $3
# sub  $2, %rsp
# movw $3,(%rsp)

And making sure the stack looks correct with gdb:

>>> x/5hd $rsp
0x7fffffffe426: 3   5   0   0   0

However, all other suffixes give me:

Error: invalid instruction suffix for `push'

Why does push only allow using a 64 bit or 16 bit value? Is it common to use the sub...mov to be more specific, or is that an anti-pattern? Finally, does the CPU interpret push identical to a sub...mov instructions, or are they two different things entirely (that produce the same result) ?

samuelbrody1249
  • 4,379
  • 1
  • 15
  • 58
  • 1
    `sub` modifies FLAGS but `sub+mov` is otherwise identical in its effect on architectural state. I don't know exactly why the design decision was made *not* to let `REX.W=0` override the operand size from 64 to 32 in machine code, but that's why you can't encode a dword push in 64-bit mode. See the linked duplicate. – Peter Cordes Aug 29 '20 at 21:12
  • 1
    It's not an anti-pattern to reserve *multiple* qwords of space and use `mov` to write some of them, but it would be braindead to use multiple separate `sub rsp, 8` instructions mixed with mov stores. See [What C/C++ compiler can use push pop instructions for creating local variables, instead of just increasing esp once?](https://stackoverflow.com/q/49485395) for the minor optimization of using push to allocate + init locals. – Peter Cordes Aug 29 '20 at 21:13

0 Answers0