8

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?

Werner
  • 83
  • 4

1 Answers1

9

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.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • Ah, that gave me an entry for some subsequent reading. I thought that stack access is always 16bit aligned and that is it. I didn't know that misaligned access to 32bit numbers cause a performance penalty. – Werner May 19 '20 at 15:57