Search code examples
assemblyx86x86-64i386

An i386/x64 pop FS/GS instruction supports a variant where it increments the SP by 32 bits or 64 bits in stead of 16 bits. What is it used for?


According to the Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2 the pop fs supports 3 variants (the same goes for pop gs):

  • Pop top of stack into FS; increment stack pointer by 16 bits.
  • Pop top of stack into FS; increment stack pointer by 32 bits. (available in compat/leg mode)
  • Pop top of stack into FS; increment stack pointer by 64 bits. (available in 64-Bit mode)

The AMD64 documentation op pop doesn't describe explicitly what happens to the stack pointer. I tried to produce those and it seems gas does recognise them (I assumed they need the 66h prefix):

 80490d6:       0f a1                   pop    fs
 80490d8:       66 0f a1                popw   fs
 80490db:       0f a9                   pop    gs
 80490dd:       66 0f a9                popw   gs

I'm breaking my head over these. To my understanding, the FS and GS registers are 16 bits, I know they have a hidden portion, but I don't expect the pop instruction to be able to manipulate those right? Can somebody explain what the purpose of these variant are?


Solution

  • In 32 bit mode, each stack slot is 32 bit. It would be rather annoying if you had to adjust the stack pointer to a multiple of 4 bytes after pushing a segment register, so the CPU provides instructions to push segment registers into 4 byte stack slots.

    When a segment register is pushed with operand size 32 bit, the register contents are zero-extended to a dword. When it is popped, only the lower two byte are read into the segment register. The upper two byte are again ignored.