Pushing segment registers on the stack for far calls

181 views Asked by At

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.

1

There are 1 answers

1
dacada On

According to the entry for the PUSH instruction in the Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 2 (link)

If the source operand is a segment register (16 bits) and the operand size is 64-bits, a zero-extended value is pushed on the stack; if the operand size is 32-bits, either a zero-extended value is pushed on the stack or the segment selector is written on the stack using a 16-bit move. For the last case, all recent Core and Atom processors perform a 16-bit move, leaving the upper portion of the stack location unmodified.

So it seems to either 0 extend or leave what was there unmodified depending on the operand size.