When the hardware pushes a segment register on the stack to save a far pointer because the calling procedure called a procedure in another segment, apparently, it does not save the invisible part of the segment register (the cached segment descriptor part) and only saves the selector part.
That, of course, is fine as that gives you really all you need to know to access the descriptor.
But, the selector is only 16 bits and if your addressing default size is 32 or 64, the hardware on its own invisible to the process will push the segment selector on the stack and increment the stack pointer 4 or 8 bytes despite the fact that the selector only requires 2.
This is to keep the stack pointer aligned which is important.
My question is: what does the hardware use to fill in the extra bytes?
Does it sign extend the selector?
Does it 0 extend the selector?
Does it just push the two selector bytes and then jump the stack pointer an extra 2 or 6 leaving whatever was there initially alone?
Thanks.
According to the entry for the PUSH instruction in the Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 2 (link)
So it seems to either 0 extend or leave what was there unmodified depending on the operand size.