It may be relatively safe to say that far pointers belong to the past when it comes to the application development level; however, it would not be right not to mention them here, as, after all, there are a few useful things we can do with it. Putting it simply, a far pointer combines a segment selector and an offset into the segment. Originating in the era of 16-bit modes of operation, surviving the 32-bit protected mode, far pointers have made it to the long mode, although they are hardly relevant, as, especially in long mode, all memory is considered to be a flat array and we are hardly going to use them.
The instructions used (some are obsolete) for loading a far pointer into the segment register: general-purpose register pairs are as follows:
- LDS: This loads the selector part of the far pointer into the DS
- LSS: This loads the selector part of the far pointer into the SS
- LES: This loads the selector part of the far pointer into the ES
- LFS: This loads the selector part of the far pointer into the FS
- LGS: This loads the selector part of the far pointer into the GS
However, let's see how we can make use of them anyway. For the sake of simplicity, we will consider a short 32-bit example for Windows, where we are obtaining the address of the Process Environment Block (PEB):
; This goes into the code section
mov word [far_ptr + 4], fs ; Store FS selector to the selector part of the far_ptr
lgs edx, [far_ptr] ; Load the pointer
mov eax, [gs:edx] ; Load EAX with the address of the TIB
mov eax, [eax + 0x30] ; Load EAX with the address of the PEB
; This goes into the data section
far_ptr dp 0 ; Six bytes far pointer:
; four bytes offset
; two bytes segment selector
As you may see, the code in this example is quite redundant as we already have the proper selector loaded into the FS register, but it still illustrates the mechanism. In the real world, no one would've gone this way in order to obtain the address of PEB; instead, the following instruction would have been issued:
mov eax, [fs:0x30]
This would have loaded the eax register with the address of the PEB, as fs:0x00000000 is already the far pointer pointing to TIB.