7

In x86_64, fs and gs registers involve in a limited form of segmentation. Just taking, fs as an example, how does fs register, FSBase MSR work together to generate the effective address?

What happens if I change fs base without changing fs? Or does changing fs base automatically change fs?

What happens if I change fs register without changing fs base? How are the effective address calculations affected?

We can take a quick example of

mov %fs:(%eax), %ebx
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
PoorGuy998
  • 73
  • 4
  • Hi, welcome to stack overflow. You need to provide all the details and mention the issue clearly what exactly you want and what you did to try to solve this issue. Please refer the [ask] link for more detail and update your question accordingly. – Jeroen Heier Jan 18 '20 at 06:32
  • 1
    My question here was simple. How is effective address calculated when both fs and fsBase are involved? What is the value stored in fs? – PoorGuy998 Jan 18 '20 at 06:36
  • 2
    @JeroenHeier: This actually is clear already. It's technical and obscure stuff that doesn't normally come up, but people who know the answer (or are looking for the answer) will I think be able to understand the question just fine. – Peter Cordes Jan 18 '20 at 06:46

1 Answers1

8

The FS architectural register is separate from the FS-base internal register.

As always, using a segment override just selects the segment base associated with that segment, instead of the default DS base or SS base (which are fixed at 0 in 64-bit mode).

The actual value in the fs architectural register itself has nothing to do with it. It only comes into play if you were to mov %fs, %eax to actually read the FS register itself, rather than use the internal base / limit "registers" associated with it.

Since there are ways to set the internal FS base (e.g. with wrmsr or on more recent CPUs the wrfsbase instruction) that are more efficient than mov to %fs (to make it load a base and limit from the GDT or LDT), OSes normally leave FS and GS architectural registers = 0, the null selector.

On bare metal, you can do that, too. Don't bother creating a GDT entry with a base you want and moving a selector into %fs or %gs; just set the base directly with wrmsr or wrfsbase.

What happens if I change fs register without changing fs base?

You can't, AFAIK. mov %reg/mem, %fs will trigger loading the internal segment base / limit registers from the GDT or LDT (depending on the value you mov).

Note that some people call these internal things a "cache", but they're not caches. They're guaranteed to keep the values from when you loaded them, so they'll never happen to change if you change a GDT entry without also reloading the segment register with that selector.

How are the effective address calculations affected?

The same as always. base + index*scale + displacement. Note that an "effective address" is just the offset part of full address, not including the segment selector or base. What is an effective address?

The linear address is also calculated the same as always: segment_base + offset, where the offset part is the effective address specified by the addressing mode.

Addressing modes default to using the DS segment base unless the "base register" in the addressing mode is E/RBP or E/RSP, in which case it's the SS base. But a prefix byte can override the default; that's what the %fs: tells the assembler to emit.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • So, is the actual value of fs completely useless in this situation? – PoorGuy998 Jan 18 '20 at 06:56
  • 1
    @PoorGuy998: Yes. I just updated my with some extra clarification before you commented. You might want to look at the diff. – Peter Cordes Jan 18 '20 at 06:57
  • Quick clarification, in the above example, mov %fs:%eax, %ebx, will the final value in ebx be just FsBase + eax? Assuming null segments loaded into fs – PoorGuy998 Jan 18 '20 at 15:04
  • No, the final value in EBX will be the value loaded from memory at the address FSBASE + EAX. – prl Jan 18 '20 at 17:47
  • 1
    @PoorGuy998: `%fs:%eax` isn't valid AT&T syntax because it's not a *memory* addressing mode. If it did assemble, the FS prefix would be meaningless for a mov between registers. If you had written `mov %fs:(%eax), %ebx` like in the question, then it would be as @ prl commented: a load from memory at linear (virtual) address `FSBASE + EAX`. – Peter Cordes Jan 18 '20 at 20:17