PUSH Operand Size in 64-bit mode
The size of the value pushed on the stack and the amount that the stack pointer is adjusted by depends on the operand size of the PUSH instruction. In 64-bit mode the operand size can only be 16-bit or 64-bit. It's not possible to encode a 32-bit PUSH instruction in 64-bit mode and it's not possible to encode an 8-bit PUSH instruction in any mode.
For example, these are all 64-bit PUSH instructions:
push rax
push 1 ; 8-bit immediate sign-extended to 64 bits
push 65536 ; 32-bit immediate sign-extended to 64 bits
push QWORD PTR[0]
push fs ; 16-bit segment register zero-extended to 64 bits
The above instructions all subtract 8 from RSP and then write a 64-bit value to the location pointed to by RSP.
These are all 16-bit PUSH instructions:
push ax
push WORD PTR[0]
These instructions subtract 2 from RSP and then write a 16-bit value to the location pointed by RSP. Because they badly misalign the stack, using a 16-bit PUSH in 64-bit mode is pretty much always a mistake. Instead you should load the 16-bit value into a register (if not already there), extend it as necessary, and then use a 64-bit PUSH.
The following instructions are illegal and can't be encoded in 64-bit mode:
push al
push eax
push BYTE PTR[0]
push DWORD PTR[0]
push 0100000000h ; 64-bit immediate value isn't supported
Pushing an 8-bit or 32-bit value on the stack requires loading the value into a register, extending it and then using a 64-bit PUSH, just like you should do with 16-bit values.
Parameter Passing in 64-bit mode
Generally speaking, in 64-bit mode function arguments aren't passed on stack. Both the Microsoft and Linux 64-bit x86 calling conventions pass most arguments in registers. The stack is only used when there's not enough room in registers to pass the arguments to a function. In that case each argument takes up one or more 8 byte stack slots. Note that compilers won't necessarily use PUSH instructions to place these arguments onto the stack. A common strategy is to allocate enough space on the stack for all of a function's outgoing arguments in the function prologue and then use MOV instructions to put arguments on the stack as necessary.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…