Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.6k views
in Technique[技术] by (71.8m points)

assembly - Does each PUSH instruction push a multiple of 8 bytes on x64?

On x64, does each PUSH instruction push a multiple of 8 bytes? If not, how much does it push?

Also, how much stack space does each function parameter consume?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...