Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 344
Werner Avatar asked May 19 '20 14:05

Werner


1 Answers

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.

like image 77
fuz Avatar answered Oct 14 '22 01:10

fuz